-
Notifications
You must be signed in to change notification settings - Fork 0
One machine
The usual setup. One warden looks after one machine and hands out ports from a single pool.
warden serve██ ██ ██ ██ █████ ██████ ██████ ███████ ███ ██
███ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
█████████ ██ █ ██ ███████ ██████ ██ ██ █████ ██ ██ ██
██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
█████████ ███ ███ ██ ██ ██ ██ ██████ ███████ ██ ████
█████████████████
███ █ ███ █ ███ nothing binds a port without asking
███ █ ███ █ ███
███ ███ v0.1.0 listening on http://127.0.0.1:7010
pool 8000-8999 1 reserved
It listens on 127.0.0.1:7010 and hands out 8000-8999. The registry port
itself is reserved automatically, which is the 1 reserved above.
Leave it running. Everything else talks to it.
$ warden register shop-api --kind backend --project shop
8000The only output is the port, so it drops straight into a script:
PORT=$(warden register shop-api --kind backend)
exec ./server --port "$PORT"--kind says what the service is: backend, frontend, worker, database,
cache, proxy, or anything else you like. It is what colours the dashboard and
what --kind filters on. --project groups the services of one codebase.
$ warden ls
SERVICE KIND PROJECT ADDRESS PID
shop-api backend shop 127.0.0.1:8000 -
shop-web frontend shop 127.0.0.1:8001 -Narrow it with --project shop or --kind backend, or get machine-readable
output with --json.
Instead of hardcoding a neighbour's address:
$ warden get shop-api
127.0.0.1:8000warden release shop-webTwo different wishes, two different flags:
# "3000 would be nice, but anything free will do."
warden register shop-web --kind frontend --preferred-port 3000
# "It has to be 3000, the number is baked into a config I cannot change."
warden register legacy-crm --kind backend --require-port 3000--preferred-port quietly falls back to the pool when the port is taken,
reserved or already in use. --require-port fails with a 409 instead. Both may
name a port outside the pool, which is how a legacy service on 3000 joins the
registry at all.
A service can ask for its own port as it starts:
import uvicorn
from warden import register
port = register("shop-api", kind="backend", project="shop")
uvicorn.run(app, port=port)Look a neighbour up rather than hardcoding it:
from warden import WardenClient
with WardenClient() as client:
backend = client.lookup("shop-api")
base_url = f"http://{backend.address}"Short-lived processes can hand the port back on the way out:
from warden import reserve
with reserve("test-fixture", kind="worker") as port:
run_server(port)A registration lasts until it is released. In CI or a test fixture, nothing gets the chance:
warden register ci-runner --kind worker --ttl 600The entry disappears ten minutes later unless something renews it. A heartbeat pushes the expiry out again:
curl -X POST localhost:7010/v1/services/ci-runner/heartbeat -d '{}' \
-H 'content-type: application/json'Sent without a ttl, a heartbeat renews the lease the service registered with.
It can never turn a lease into a permanent registration by accident.
warden tuiTwo live tables, two seconds apart. tab swaps between what warden handed out
and what is actually listening.
| Key | Action |
|---|---|
↑ ↓ j k
|
Move |
tab |
Switch view |
r |
Reload now |
d |
Release the service, or stop the process |
q |
Quit |
warden serve --pool 4000-4999 --reserved 4200,4500-4510Or, so it sticks:
WARDEN_POOL_START=4000
WARDEN_POOL_END=4999
WARDEN_RESERVED=4200,4500-4510See Configuration for the full list, including a .env file.
warden is a plain HTTP server; anything that keeps a process alive will do.
Windows, Task Scheduler: a task at logon running
%USERPROFILE%\.local\bin\warden.exe serve.
Linux, a user service in ~/.config/systemd/user/warden.service:
[Unit]
Description=warden
[Service]
ExecStart=%h/.local/bin/warden serve
Restart=on-failure
[Install]
WantedBy=default.targetsystemctl --user enable --now wardenThe registry survives restarts, so services keep the ports they had.
warden — nothing binds a port without asking ·
uv tool install warden-ports
Repository · Issues · Releases · PyPI · MIT
Getting started
While it runs
Several machines
Reference