Self-hosted service
ochinchina/supervisord avatar
ochinchina/supervisord

ochinchina/supervisord: a Go reimplementation of supervisord for containers without Python

a go-lang supervisor implementation

4,271 stars630 forksGoMIT

At a glance

What is it?
It keeps the supervisord configuration format and control protocol but ships as a single static binary, which is why it fits Docker images and minimal Linux hosts where installing Python is unacceptable. The trade-off is a smaller feature set and a control channel that requires the HTTP server.
Who is it for?
Adopt it when your constraint is image size or a host with no Python, and when the INI programs you already run are simple: command, autostart, autorestart, numprocs. Do not adopt it if you depend on supervisorctl features the README does not list, or if you need unix-socket control, since the README states Unix domain socket is not currently supported for that purpose.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is the Python runtime, not process supervision

The README opens with the motivation in plain terms: the Python supervisord is a powerful tool, but it requires that the big python environment be installed in the target system, and in a Docker environment the python is too big. This project re-implements supervisord in Go so the compiled result can run where Python is not installed.

The audience follows from that sentence. Anyone already happy with Python supervisord and its plugin ecosystem has no reason to switch. The project targets people who need process supervision inside a small container image, on a stripped host, or on Windows, where the README gives a separate build path. The value proposition is the artifact, not the feature list: one binary, no interpreter, no site-packages.

What the Go implementation actually contains

The repository layout shows the shape of the program: supervisor.go holds the supervisor itself, process/ the per-program state machine, xmlrpc.go and rest-rpc.go the RPC surfaces, webgui.go and webgui/ the browser UI, ctl.go the command-line client, and zombie_reaper.go the child-process reaping. There are OS-specific files too: daemonize_windows.go, rlimit_windows.go, zombie_reaper_windows.go, plus rlimit_freebsd.go, so the platform split is handled per file rather than through build tags alone.

The configuration parser is not the Python one. go.mod depends on github.com/ochinchina/go-ini, an INI reader maintained under the same account, and on github.com/ochinchina/gorilla-xmlrpc for the RPC layer. The daemon mechanics come from github.com/ochinchina/go-daemon, and the service integration from github.com/kardianos/service, which is the library used to register a program as a system service. Prometheus client_golang and robfig/cron are also direct dependencies, so metrics export and scheduled work exist in the codebase even though the README section shown here does not describe them. That gap matters: the README is the primary documentation and it does not cover every dependency you can see in go.mod.

The supervised-program options are the familiar supervisord vocabulary: command, process_name, numprocs, autostart, startsecs, startretries, autorestart, exitcodes, stopsignal. The README describes startsecs as the time a program must stay running to move from STARTING to RUNNING, startretries as the number of serial failures before the process enters FATAL, and exitcodes as the expected-code list used with autorestart. One entry in that list is marked numprocs_start with a literal question mark, which tells you the README was written alongside the code rather than after it. If you rely on numprocs_start, read the source.

Installing and running your first supervised program

There is no package manager step in the README. You build the binary yourself, and the README requires go-lang 1.11+ for that. For Linux it gives this sequence, which produces a statically linked executable:

bash
go generate
GOOS=linux go build -tags release -a -ldflags "-linkmode external -extldflags -static" -o supervisord

On Windows the README instead tells you to run go mod tidy and then go build -tags release -o supervisord.exe on a Windows PC. If you would rather not build at all, the repository ships a Dockerfile that compiles with CGO_ENABLED=0 and copies the result into a scratch image, so the runtime layer holds only the binary.

Once you have the binary, the README's own example is a two-line config and a single invocation. Create a file with a program section, then start the daemon against it:

ini
[program:test]
command = /your/program args
bash
supervisord -c supervisor.conf

The -c flag is optional in practice, because the config file is autodetected in a fixed order: $CWD/supervisord.conf, then $CWD/etc/supervisord.conf, then /etc/supervisord.conf, then /etc/supervisor/supervisord.conf, then ../etc/supervisord.conf relative to the executable, and finally ../supervisord.conf relative to the executable. In a container, passing -c explicitly avoids depending on the working directory.

For a long-running daemon with the web UI, add an HTTP listener and pass -d:

ini
[inet_http_server]
port=127.0.0.1:9001
bash
supervisord -c supervisor.conf -d

With that listener up, supervisord ctl becomes usable. The README lists status, start, stop, shutdown, reload, restart, signal, pid, fg, tail, add, remove, update, clear and reread as subcommands, and they accept explicit names, group: wildcards, or all. A first check after starting the daemon is supervisord ctl status, which should print the state of the program you defined. The README is explicit that ctl works correctly only if an HTTP server is enabled in [inet_http_server] and serverurl is set correctly.

serverurl resolution and the unix-socket gap

The client does not take a host on the command line by default. It resolves the server URL in four steps: an -s or --serverurl option wins; otherwise, if -c is present and the [supervisorctl] section defines serverurl, that value is used; otherwise the autodetected config file is checked for the same key; otherwise it falls back to http://localhost:9001. That fallback is the reason a daemon listening on a different port silently confuses the client.

The sharper limitation is stated in the same paragraph: Unix domain socket is not currently supported for this purpose. The README separately says the HTTP server itself can work over both a unix domain socket and TCP, configured through [unix_http_server] and [inet_http_server]. So the daemon can serve over a socket, but supervisord ctl cannot talk to it that way. If your security model depends on a socket-only control channel, this implementation does not give it to you, and you would have to drive the XML-RPC or REST interface yourself.

Daemon settings that differ from muscle memory

The [supervisord] section covers logfile, logfile_maxbytes, logfile_backups, logfile_timestamp_suffix, loglevel, pidfile, minfds, minprocs and identifier. Two details are worth flagging. loglevel accepts trace, debug, info, warning, error, fatal and panic, and the README attributes that list to the logging module used for the feature, which is logrus in go.mod. And logfile_timestamp_suffix defaults to true, meaning rotated files get a 2006-01-02T15:04:05 suffix instead of a numeric 1 to logfile_backups suffix. If your log-shipping rules match numeric suffixes, set this key explicitly.

The identifier key is required when more than one supervisord runs on the same machine in the same namespace, which is the normal situation in a container host running several images. minfds and minprocs map to rlimit nofiles and noproc, and the platform-specific rlimit files in the repository root show those limits are implemented per OS rather than uniformly.

When to keep the Python original or use systemd

The honest comparison is with the Python supervisord this project copies. The Python version brings an ecosystem of plugins and a longer track record; the Go version brings a static binary and no interpreter. If your image already installs Python for the application itself, the size argument disappears and you gain nothing by switching. If your image is scratch-based, as the Dockerfile here suggests, the Go binary is the only option of the two that fits at all.

Against systemd the difference is scope. systemd manages services for a machine and expects to be PID 1 with a running init; it is not present in most containers. This project is a userspace supervisor that runs as whatever PID you give it and reaps zombies through its own reaper files. The RELATED SEARCHES phrase supervisord vs systemd points at exactly this split, and the answer is that they are not substitutes: one supervises a host, the other supervises a process tree inside a container or a user session.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-15, the same day as the v0.7.5 release. That is recent, so describing the project as maintained is fair on the evidence available. There is also a v0.0.2-test tag published after v0.7.5 on the same day, which looks like a test artifact rather than a release line; pin to v0.7.5 or a later numbered release rather than to a tag named test.

The licence is MIT, which is permissive and imposes no copyleft obligation on your own code. That is a statement about the licence text, not legal advice; if you redistribute the binary, keep the licence file and read the terms yourself.

Upgrade cost is low if you stay inside the documented INI vocabulary, because the binary is self-contained and the config format is the one you already have. It rises if you depend on behaviour the README does not describe. The dependencies in go.mod include a Prometheus client and a cron library, and neither appears in the README section shown here, so treat any metrics or scheduling you rely on as undocumented and verify it against the source before you build a workflow on it.

Editorial conclusion

Adopt it when your constraint is image size or a host with no Python, and when the INI programs you already run are simple: command, autostart, autorestart, numprocs. Do not adopt it if you depend on supervisorctl features the README does not list, or if you need unix-socket control, since the README states Unix domain socket is not currently supported for that purpose. Before rolling it out, verify two things against your own config: that your [program:x] options appear in the supported list, and that supervisord ctl status reaches your daemon through the serverurl resolution order described above.

Frequently asked questions

What is ochinchina/supervisord used for?

It supervises long-running programs described in a supervisord-style INI file, starting them, restarting them according to autorestart and exitcodes, and exposing control over an HTTP interface. The README frames it as a Go reimplementation of the Python supervisord for environments where Python is not installed.

How do I install ochinchina/supervisord?

The README does not describe a package install. It tells you to build the binary with go generate and GOOS=linux go build -tags release -a -ldflags "-linkmode external -extldflags -static" -o supervisord, or to build supervisord.exe on Windows with go build -tags release.

How do I use ochinchina/supervisord in Docker?

The repository ships a Dockerfile that builds with CGO_ENABLED=0 and copies the binary into a scratch image with supervisord as the entrypoint. You then supply a configuration with a [program:name] section, and add [inet_http_server] with a port if you want the control commands to work.

How do I restart a program with ochinchina/supervisord?

Use the ctl subcommand, for example supervisord ctl restart program-1, supervisord ctl restart group:*, or supervisord ctl restart all. The README notes that ctl only works when the HTTP server is enabled in [inet_http_server] and serverurl is set correctly.

What is the supervisord.conf file in ochinchina/supervisord?

It is the INI configuration that defines the daemon settings in [supervisord], supervised programs in [program:name], and the optional HTTP listeners in [inet_http_server] and [unix_http_server]. If you do not pass -c, the file is autodetected from a fixed list of locations starting with $CWD/supervisord.conf.

How do I use ochinchina/supervisord?

Create a config with a [program:name] section, start the binary with supervisord -c supervisor.conf, and add [inet_http_server] with a port plus the -d flag if you want the daemon and the ctl subcommands. The README's own example is a single [program:test] section with a command line and supervisord -c supervisor.conf.

Official sources

  1. Issues
  2. License: MIT
  3. ochinchina/supervisord on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ochinchina-supervisord.svg)](https://hysenlabs.com/projects/ochinchina-supervisord)