Skip to content

Add Socketfile support for systemd-style socket activation#816

Open
Ericson2314 wants to merge 2 commits into
ddollar:mainfrom
Ericson2314:socketfile
Open

Add Socketfile support for systemd-style socket activation#816
Ericson2314 wants to merge 2 commits into
ddollar:mainfrom
Ericson2314:socketfile

Conversation

@Ericson2314
Copy link
Copy Markdown

@Ericson2314 Ericson2314 commented May 5, 2026

Note

I don't know if this project would accept a such a blatantly new feature extending the Procfile defacto spec, but it was useful for me, so I am making this PR. Look at https://github.com/mitsuhiko/systemfd for some prior art.

Foreman can now pre-bind sockets and pass them to child processes using the LISTEN_FDS / LISTEN_FDNAMES protocol (the same protocol systemd uses for socket activation). This lets processes survive restarts without rebinding their listen addresses.

A Socketfile declares which process gets which sockets:

web: http=:3000
api: grpc=:50051

Foreman binds these before spawning children, then maps them to fd 3, 4, ... via Process.spawn and sets the corresponding environment variables.

Foreman can now pre-bind sockets and pass them to child processes using
the `LISTEN_FDS` / `LISTEN_FDNAMES` protocol (the same protocol systemd
uses for socket activation). This lets processes survive restarts without
rebinding their listen addresses.

A `Socketfile` declares which process gets which sockets:

    web: http=:3000
    api: grpc=:50051

Foreman binds these before spawning children, then maps them to fd 3, 4, ...
via `Process.spawn` and sets the corresponding environment variables.
Ericson2314 added a commit to obsidiansystems/hydra that referenced this pull request May 6, 2026
Add a `Socketfile` that declares sockets for `hydra-server` and
`hydra-queue-runner`, so foreman can pass sockets to them just like
systemd socket activation would. This means that development with
foreman is once again exercising the same code paths that production
will use.

The foreman start scripts are updated accordingly:

- `hydra-server` switches from `hydra-dev-server --port` to
  `hydra-server -f` (Starman with fork mode), picking up the socket via
  the `Net::Server::Systemd::PreFork` personality.

- `hydra-queue-runner` gets `--rest-bind - --grpc-bind -` to use socket
  activation for both its REST and gRPC servers.

- All services now `wait_for_hydra_db` before starting, since with
  socket activation the listen port is open before the server is ready,
  so `wait_for_hydra_server` alone is no longer sufficient.

- `queue_runner_endpoint` is added to the generated `hydra.conf` so the
  web UI can fetch machine status.

The foreman fork (Ericson2314/foreman@socketfile, PR
ddollar/foreman#816) adds the `Socketfile`
feature. Foreman is packaged from source in `packaging/foreman/` because
it was not clear how to override the Nixpkgs version which gets its
source from rubygems.

I would not use forked projects when I am far from sure that upstream
would accept the change in production, but foreman is just a developer
convenience in the dev shell. That to me makes this OK --- it's just for
developer convenience.
Ericson2314 added a commit to obsidiansystems/hydra that referenced this pull request May 6, 2026
Add a `Socketfile` that declares sockets for `hydra-server` and
`hydra-queue-runner`, so foreman can pass sockets to them just like
systemd socket activation would. This means that development with
foreman is once again exercising the same code paths that production
will use.

The foreman start scripts are updated accordingly:

- `hydra-server` switches from `hydra-dev-server --port` to
  `hydra-server -f` (Starman with fork mode), picking up the socket via
  the `Net::Server::Systemd::PreFork` personality.

- `hydra-queue-runner` gets `--rest-bind - --grpc-bind -` to use socket
  activation for both its REST and gRPC servers.

- All services now `wait_for_hydra_db` before starting, since with
  socket activation the listen port is open before the server is ready,
  so `wait_for_hydra_server` alone is no longer sufficient.

- `queue_runner_endpoint` is added to the generated `hydra.conf` so the
  web UI can fetch machine status.

The foreman fork (Ericson2314/foreman@socketfile, PR
ddollar/foreman#816) adds the `Socketfile`
feature. Foreman is packaged from source in `packaging/foreman/` because
it was not clear how to override the Nixpkgs version which gets its
source from rubygems.

I would not use forked projects when I am far from sure that upstream
would accept the change in production, but foreman is just a developer
convenience in the dev shell. That to me makes this OK --- it's just for
developer convenience.
Ericson2314 added a commit to obsidiansystems/hydra that referenced this pull request May 6, 2026
Add a `Socketfile` that declares sockets for `hydra-server` and
`hydra-queue-runner`, so foreman can pass sockets to them just like
systemd socket activation would. This means that development with
foreman is once again exercising the same code paths that production
will use.

The foreman start scripts are updated accordingly:

- `hydra-server` switches from `hydra-dev-server --port` to
  `hydra-server -f` (Starman with fork mode), picking up the socket via
  the `Net::Server::Systemd::PreFork` personality.

- `hydra-queue-runner` gets `--rest-bind - --grpc-bind -` to use socket
  activation for both its REST and gRPC servers.

- All services now `wait_for_hydra_db` before starting, since with
  socket activation the listen port is open before the server is ready,
  so `wait_for_hydra_server` alone is no longer sufficient.

The foreman fork (Ericson2314/foreman@socketfile, PR
ddollar/foreman#816) adds the `Socketfile`
feature. Foreman is packaged from source in `packaging/foreman/` because
it was not clear how to override the Nixpkgs version which gets its
source from rubygems.

I would not use forked projects when I am far from sure that upstream
would accept the change in production, but foreman is just a developer
convenience in the dev shell. That to me makes this OK --- it's just for
developer convenience.
Require explicit `tcp://` or `unix://` scheme prefixes:

    hydra-server: http=tcp://:3000
    hydra-drv-daemon: daemon=unix:///tmp/drv-daemon.sock

Unix sockets are cleaned up on shutdown.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant