For anyone who runs more than one service on localhost and forgets which port does what.
Ferrule
One binary answers for every local service you run.
Ferrule terminates TLS for made-up local domains like api.local, routes them to whatever is listening on your machine, and restarts the process when it falls over. No Docker, no nginx.conf, no fourth terminal tab running node worker.js that you'll forget about by Thursday.
Four jobs, one process tree
Ferrule doesn't try to be a service mesh. It does the four things a local multi-service setup actually needs, and stops there.
Name-based routing
Give each service a host in ferrule.toml and Ferrule answers for it — api.local, admin.local, whatever you like. No /etc/hosts editing beyond the one-time wildcard entry the installer offers to add for you.
Real TLS, not a browser warning
Ferrule runs a local certificate authority the first time you start it, and asks once to install its root into your system trust store. After that, every *.local host gets a certificate your browser already trusts — no exceptions to click through.
Process supervision
Services can be a command instead of a proxy_to. Ferrule starts it, restarts it on the policy you set (never, on-failure, or always), and applies exponential backoff so a crash loop doesn't pin a core.
One place to look
ferrule up opens a small terminal dashboard with every service's status, port, and last log line. ferrule logs api tails just one. You stop hunting across terminal tabs for the process that died twenty minutes ago.
This is not an abbreviated example
A three-service local stack — a frontend, an API with a health check, and a supervised worker — fits in fifteen lines.
# started with `ferrule init`, edited by hand
[server]
bind = "127.0.0.1"
http_port = 80
https_port = 443
local_ca = true
[[service]]
name = "web"
host = "app.local"
proxy_to = "127.0.0.1:5173"
[[service]]
name = "api"
host = "api.local"
proxy_to = "127.0.0.1:4000"
health_check = "/healthz"
[[service]]
name = "worker"
command = "node worker.js"
restart = "on-failure"
backoff = "2s..30s"
Every key, its type, and its default → is in the configuration reference.
Compared to what you'd reach for instead
Ferrule is scoped for local development and small single-box deployments. It is not trying to replace Traefik in a Kubernetes cluster.
| Ferrule | nginx + systemd | Traefik + Compose | Plain Caddy | |
|---|---|---|---|---|
| Config format | one ferrule.toml |
nginx.conf + unit files |
YAML labels + compose file | one Caddyfile |
TLS for *.local |
built-in local CA, on by default | manual, usually mkcert | manual or a plugin | built-in, on-demand |
| Runs your processes | yes — restart policies, backoff | no, needs systemd units | no, needs containers | no |
| Needs Docker | no | no | yes | no |
| Footprint | ~9 MB, one binary | part of the OS already | Traefik + Docker Engine | ~40 MB, one binary |
| Best fit | solo devs / small teams, local machines | production Linux hosts | container-native teams | simple static & prod proxying |
Fifteen minutes, start to routed
Install the binary, write the config above, run ferrule up. The quick start walks through it on macOS, Linux, and Windows, including the one-time step of trusting the local CA.