A lightweight, PID-1-aware process manager for containers. Single static Go binary, no runtime dependencies. Designed to be a Docker ENTRYPOINT that orchestrates multiple long-running services, but works equally well for local development.
- PID 1 aware — auto-detects container context, performs SIGCHLD-driven zombie reaping without racing with
os/exec. - Signal forwarding — SIGTERM/SIGINT trigger graceful shutdown; SIGHUP/SIGUSR1/SIGUSR2 are forwarded to children.
- Per-process privilege dropping —
user/group(when started as root). - Conditional startup — environment variables, file existence, TCP port reachability, or arbitrary shell commands.
- Dependency graph —
dependsOnwith cycle detection;parallelorsequentialstartup modes. - Multi-instance processes — run N identical copies of a worker.
- Configurable restart policy — exponential backoff with jitter, max-retry caps, post-stability reset.
- Customizable shutdown — per-process
stopSignalandstopTimeout. - Built-in log multiplexing — process stdout/stderr prefixed on gonner's stdout and (optionally) appended to a private log file with size-based rotation.
- Health endpoint — opt-in HTTP API exposing
/health(liveness),/ready(readiness),/status, and optional/metrics(Prometheus text format) with bearer-token auth and TLS support (min TLS 1.2). - Container-friendly defaults — secure log file mode
0o600, HTTP timeouts, panic-safe goroutines.
| Topic | Document |
|---|---|
| Install & quickstart | this file |
| Full configuration reference | docs/configuration.md |
| Deployment patterns | docs/deployment.md |
| Security model & hardening | docs/security.md |
| Operations / health / metrics | docs/operations.md |
| Architecture overview | docs/architecture.md |
| Troubleshooting | docs/troubleshooting.md |
Download a prebuilt binary from Releases, or build from source:
# requires Go 1.25+
go install github.com/michaelishri/gonner/cmd/gonner@latestOr from a checkout (requires Task):
task build # writes bin/gonnerCreate gonner.json in your project directory:
{
"run": [
{ "name": "web", "command": "nginx", "critical": true },
{ "name": "scheduler", "command": "php artisan schedule:work", "autoRestart": true },
{ "name": "queue", "command": "php artisan queue:work", "autoRestart": true, "instances": 4, "dependsOn": ["web"] }
]
}gonnerGonner auto-discovers gonner.json in the working directory, starts the processes, and forwards container signals.
FROM alpine
COPY gonner /usr/local/bin/gonner
COPY gonner.json /etc/gonner/gonner.json
ENTRYPOINT ["gonner"]Gonner picks up /etc/gonner/gonner.json automatically (see discovery order).
gonner # alias for `gonner run`
gonner run [--config PATH] [--health-port N] [--health-bind ADDR]
gonner validate [--config PATH] # validate without starting anything
gonner status [--host H] [--port N] [--token T] [--tls] [--insecure]
gonner version
See gonner <cmd> --help for full flag listings, or docs/configuration.md.
Before shipping a container with gonner:
- Set
health.bindAddrto127.0.0.1(or behind a reverse proxy) unless the endpoint is needed externally. - If exposing the health endpoint, set
health.authToken(viaGONNER_HEALTH_TOKENenv var; min 16 chars). - Enable
/metricsonly on a private network. - Drop privileges per process with
user/groupif gonner runs as root. - Configure
logRotatefor anylogFileyou write. - Mark exactly one process
critical: trueso a crash takes down the container (lets your orchestrator restart it cleanly). - Set realistic
shutdownTimeout/ per-processstopTimeoutfor slow-draining services. - Run
gonner validatein CI.
See docs/security.md for the full hardening guide.
MIT