section3

command module
v0.0.0-...-5effa60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 24 Imported by: 0

README

section3 icon

section3

Service supervisor in a single static binary.

section3 starts the services listed in one YAML file, restarts them when they crash, and rotates their logs. It is built to be the entrypoint of a Docker container that runs more than one process, and works the same way outside containers.

CLI

section3               Start the supervisor (default when run without args)
section3 status        Show status of all services
section3 status <name> Show status of one service
section3 start <name>  Start a service
section3 stop <name>   Stop a service
section3 restart <name> Restart a service
section3 reload        Reload config (add/remove/redefine services)
section3 tail [-n N] [name]  Show last N log lines (default: 20, all if no name)
section3 version       Show binary version
section3 self exit     Stop all services and exit
section3 self update   Update the binary to the latest release
section3 help          Show this help

The first invocation starts the daemon; every other command talks to it over a unix socket.

Configuration

section3 reads /workspace/section3.yml:

defaults:
  dir: /workspace        # working directory for services that don't set their own
  restart: always        # always | never | on-crash
  log_max_size: 10M      # log rotation threshold, default 1M

services:
  web:
    command: /usr/local/bin/my-web-server --port 8080

  worker:
    command: /usr/local/bin/my-worker --queue default
    restart: on-crash
    depends_on:
      - web

  init-once:
    command: /usr/local/bin/migrate-db.sh
    restart: never
    dir: /tmp

  dockerd:
    command: dockerd-rootless.sh
    stop_timeout: 60s      # needs longer than the 5s default to stop containers

Restart policies:

  • always — restart on any exit (default)
  • never — do not restart
  • on-crash — restart only on non-zero exit

Restarts back off exponentially up to 60s; a run of at least 60s counts as recovery and resets the backoff. section3 reload (or SIGHUP) stops services removed from the config, starts newly added ones, and restarts any whose command, dir or restart policy changed. Services whose definition is unchanged keep running and are not disturbed.

log_max_size, stop_timeout and depends_on do not count as changes: the first decides where output goes rather than what runs, the second how it stops, and the third is start ordering that has already happened. All take effect for the next start of that service.

Docker

section3 works as the container entrypoint, supervising everything inside:

RUN curl -fsSL https://signalshell.com/install-section3 | sh
COPY section3.yml /workspace/section3.yml
ENTRYPOINT ["/usr/local/bin/section3"]

With docker-compose:

services:
  app:
    build: .
    init: true

Use init: true (or docker run --init) so Docker puts a small init process at PID 1. section3 reaps its own direct children, but when a service forks and dies, its orphaned children reparent to PID 1, and the init process reaps those.

Docker lifecycle:

  • docker stop → SIGTERM → section3 stops all services gracefully, then exits
  • docker kill -s HUP <ctr> or docker exec <ctr> section3 reload → config reload
  • docker exec <ctr> section3 status → service status from outside

Alternatively, from an entrypoint script, exec it so signals reach the supervisor directly:

#!/bin/bash
exec /usr/local/bin/section3

Install

curl -fsSL https://signalshell.com/install-section3 | sh

Downloads the latest release (linux amd64/arm64), verifies its minisign signature against the same key the binary embeds, and installs to /usr/local/bin or ~/.local/bin (or $SECTION3_INSTALL_DIR).

It refuses to install anything it cannot verify. If neither minisign nor openssl is present it stops and says so, rather than continuing unverified. That closes the one gap in the chain: self update has always checked the signature, but the first install had no trusted binary to check with, and until 2026-09-07 it compared a sha256 fetched from the same server as the binary, which catches a corrupted download and nothing else.

Source: install.sh in this repo, kept byte-identical to install-section3 in the signalshell-landing repo, which is what the URL serves. make check-installer diffs them; sh install_test.sh tests the real thing against the live release (including that a tampered binary is refused by both verifiers).

Update later with:

section3 self update    # fetch latest release, verify minisign signature, replace binary

A running daemon keeps the old version until it is restarted. Note that restarting the daemon restarts all of its services.

Run

# Start supervisor (blocks)
section3

# Or in background, then check status
section3 &
section3 status

Logs

Logs go to /tmp/section3-logs/<name>.log

Output is piped through the supervisor, so logs rotate even while a service is running, keeping last 5 versions (<name>.log.1 ... <name>.log.5). The rotation threshold is log_max_size (default 1MB), settable per service or in defaults:. The daemon's own section3.log rotates the same way.

Building from source

make build    # → bin/section3
make test

Releasing (maintainer)

make release

Bumps VERSION, builds linux amd64/arm64, signs with minisign, uploads the binaries and install.sh to signalshell.com/releases/section3/, commits and tags. The self update command verifies against the public key embedded in selfupdate.go.

Pushing that tag runs .github/workflows/release.yml, which mirrors the published, signed artifacts onto GitHub Releases. It does not build or sign: the key stays on the release machine, and publishing unsigned binaries would reopen the hole install.sh closes. signalshell.com remains the source of truth for self update.

The public key appears in three places (selfupdate.go, install.sh, the workflow). The workflow fails if they disagree.

Files

main.go          # supervisor source
selfupdate.go    # self version/update commands
install.sh       # signature-verifying installer (mirrored to the landing site)
install_test.sh  # differential test of install.sh against the live release
Makefile         # build + release
README.md        # this file
SPEC.md         # design spec
docs/           # architecture docs
VERSION         # version
section3.yml    # example config
bin/section3    # compiled binary (gitignored)

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL