serve
serve
Start the ephemerd daemon. This is the default command – running ephemerd without a subcommand is equivalent to ephemerd serve.
ephemerd serve [flags]Flags
| Flag | Default | Description |
|---|---|---|
--config, -c | <data-dir>/config.toml | Path to config file |
--containerd-tcp-port | (none) | Also expose containerd on a TCP port (used by WSL host integration) |
--containerd-tcp-addr | 127.0.0.1 | Bind address for the containerd TCP listener (use 0.0.0.0 when host lives outside the network namespace) |
--containerd-only | false | Only run containerd and the dispatch worker (no scheduler, no GitHub polling, no runner extraction) |
--dind | false | Mount a fake Docker socket into each container (overrides config file setting) |
Startup sequence
When serve starts, it performs these steps in order:
- Check for existing instance – connects to the gRPC control socket to verify no other ephemerd is already running.
- Load configuration – reads the TOML config file from
--configor<data-dir>/config.toml. - Write PID file – writes
ephemerd.pidto the data directory (used by thedraincommand). - Start container runtime – launches the embedded containerd server in-process. On macOS, this boots a Linux VM via Virtualization.framework instead.
- Extract embedded runner – unpacks the GitHub Actions runner binary (
.tar.gzon Linux,.zipon Windows). - Extract CNI plugins – unpacks the embedded CNI plugin binaries.
- Initialize networking – sets up the container network (CNI bridge on Linux, HCN NAT on Windows).
- Install firewall rules – blocks container access to RFC1918 and link-local ranges.
- Create GitHub client – authenticates using
GITHUB_TOKENor GitHub App credentials from the config. - Wait for Linux dispatcher – if a WSL2 VM is booting in the background (Windows only), waits for the gRPC dispatch client to become ready.
- Configure webhook tunnel – sets up localtunnel or ngrok for webhook delivery, or falls back to polling mode.
- Start scheduler – begins discovering and processing GitHub Actions jobs.
- Start metrics server – if metrics are enabled in the config, starts the Prometheus metrics endpoint.
Containerd-only mode
When --containerd-only is set, the daemon runs a stripped-down mode intended for the WSL2 Linux worker:
- Starts containerd with the TCP listener.
- Extracts the runner and CNI plugins.
- Cleans stale CNI bridges from previous WSL boots.
- Sets up networking and firewall rules.
- Starts the gRPC dispatch server on
containerd-tcp-port + 1. - Does not start the scheduler, poll GitHub, or require GitHub credentials.
The Windows host dispatches Linux jobs to this worker via gRPC.
Signal handling
The daemon listens for SIGINT and SIGTERM. On receipt, it stops accepting new jobs and waits for running jobs to finish before exiting. The PID file is cleaned up on exit.
Environment variables
| Variable | Description |
|---|---|
GITHUB_TOKEN | GitHub personal access token (alternative to setting github.token in config) |
EPHEMERD_DATA_DIR | Override the default data directory |
Ports
- Webhook / health endpoint: configured via
webhook.portin config (default varies by setup) - Metrics: configured via
metrics.portin config, only active whenmetrics.enabled = true
Examples
# Start with default config
sudo ephemerd serve
# Start with a custom config file
sudo ephemerd serve --config /etc/ephemerd/config.toml
# Start in WSL worker mode (used by Windows host integration)
ephemerd serve --containerd-tcp-port 10000 --containerd-tcp-addr 0.0.0.0 --containerd-only
# Start with Docker-in-Docker support
sudo ephemerd serve --dind