§7d Process Supervisor (Supervisord)
This section describes a non-root supervisord integration inside
pkgs/bigfred/server. The Go backend owns declarative process groups, renders
supervisord configuration from embedded Go templates, and applies changes
via supervisord's built-in hot reload (supervisorctl reread +
supervisorctl update).
The component replaces the ad-hoc exec.Command child-process supervisor
described in §7 cross-cutting #12 with a
general-purpose layer that can manage multiple sibling processes
(scripts-executor today; command-station bridges, pollers, MCP workers,
… tomorrow) while keeping the same process-isolation guarantees from
§2 High-Level Architecture.
Overview & design goals
Why supervisord, non-root constraints, ownership model.
Service API & configuration model
Go structs, SupervisordService, Go templates, supervisord INI layout.
Lifecycle, reload & health
Daemon start/stop, config regeneration, hot reload, status polling.
Integration with the server
Wiring in cli/root.go, scripts-executor migration, system.status events.
Quick reference
| Concern | Decision |
|---|---|
| Runs as | the same Unix user as loco server (never root) |
| Config & runtime paths | Hub paths under /data/etc/supervisord/, /data/run/, /data/log/ |
| Config authoring | embedded text/template → atomic write to supervisord.conf |
| Apply config changes | regenerate file, then supervisorctl reread + update (built-in hot reload); full daemon restart only when global sections change |
| Process declaration | (command, autostart, autorestart) inside a named process group; command is wrapped as /bin/bash -c '…' |
| Single instance | one loco server per machine — no multi-instance ownership checks |
| External dependency | supervisord + supervisorctl binaries on PATH (Python supervisor package) |