-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
Run warden setup once, and warden settings whenever you want to see or change
what it wrote. Nothing below has to be done by hand.
$ warden setup
Ports to hand out [8000-8999]: 4000-4099
Ports never to hand out: 4200
Port warden itself listens on [7010]:
Reachable from other machines? [y/N]:
Does this warden report to another one? [y/N]:
Allow stopping processes over the API? [y/N]:Enter accepts every default, so it is six keystrokes if you only came for the pool.
| System | Path |
|---|---|
| Windows | %LOCALAPPDATA%\warden\warden.toml |
| Linux | ~/.config/warden/warden.toml |
| macOS | ~/Library/Application Support/warden/warden.toml |
WARDEN_CONFIG points somewhere else, which is how two wardens on one machine
keep out of each other's way.
warden settings opens the same screen warden setup uses, over what is
already written down. Naming a part goes straight there:
warden settings # the screen, on the first tab
warden settings embed # what each event looks like in a chat window
warden settings firewall # which backend, and how long before it rolls backThe parts are ports, reach, fleet, events, embed, firewall and
risk — ctrl+left and ctrl+right move between them. Leaving with ctrl+s
writes over the file rather than replacing it, so a setting the screen never
asks about survives.
Without a terminal — a script, a build machine — it prints the table instead,
and --plain or warden settings list asks for that on purpose:
$ warden settings --plain
SETTING VALUE FROM
host 127.0.0.1 default
port 7010 config file
pool_start 4000 config file
pool_end 4099 config file
token set environmentThe FROM column is the point of the table. "Why is the pool 4000-4099 when the
file says otherwise" is the question that costs an afternoon, and this answers
it. Secrets show as set rather than being printed.
warden settings set pool_end 4199
warden settings unset probe # back to its default
warden settings --json # for a scriptA value is checked before it is written, so the file never holds something warden would refuse to start with. Setting one that the environment overrides says so, rather than looking like it worked.
The first of these with an answer wins:
- a flag on
warden serve - an environment variable —
WARDEN_and the setting's name in capitals - a
.envfile in the directory the process starts in - the config file
- the default
The environment is what a container or a systemd unit will use, and the file is
for a machine somebody sits at. Both work together, and warden settings says
which one you are actually getting.
# .env, beside the process
WARDEN_POOL_START=4000
WARDEN_TOKEN=a-long-random-stringSetting names below are the file's keys. As an environment variable each takes
the WARDEN_ prefix in capitals: pool_start becomes WARDEN_POOL_START.
| Setting | Flag | Default | Meaning |
|---|---|---|---|
host |
--host |
127.0.0.1 |
Interface it listens on |
port |
--port |
7010 |
Port it listens on |
database |
--database |
platform data directory | SQLite file holding everything |
The database defaults to %LOCALAPPDATA%\warden\registry.db on Windows,
~/.local/share/warden/registry.db on Linux and
~/Library/Application Support/warden/registry.db on macOS. It is created on
first use, along with any missing parent directories.
| Setting | Flag | Default | Meaning |
|---|---|---|---|
pool_start |
--pool 8000-8999 |
8000 |
First port that may be handed out |
pool_end |
--pool 8000-8999 |
8999 |
Last port that may be handed out |
reserved |
--reserved |
empty | Ports never handed out |
probe |
--no-probe |
true |
Test a port for an existing listener before handing it out |
reserved takes single ports and ranges, separated by commas:
8080,8443,9000-9010.
The registry's own port is added to the reserved set automatically when it falls inside the pool. It lives on the same machine, so it could never be handed out anyway.
--no-probe turns off the bind test. Only worth it if something in your
environment makes binding expensive; you lose the ability to notice ports that
were taken outside the registry.
| Setting | Default | Meaning |
|---|---|---|
token |
empty | One token that reaches everywhere, including the firewall |
tokens |
empty | Named tokens, each reaching only as far as it says |
cluster_token |
empty | The secret wardens use with each other: announcing, and reading |
allow_kill |
false |
Let the API stop processes |
allow_remote_update |
false |
Let a caller ask this warden to update itself |
update_command |
empty | What updating means on this machine |
update_check |
true |
Ask GitHub whether a newer release exists |
update_repo |
vxnsin/warden |
Which repository to ask about |
update_interval |
21600 |
Seconds between checks, at least 300 |
Empty means no check at all, which is fine while warden listens on loopback. Set
token before binding to anything else — warden setup asks for one as soon as
you say the machine should be reachable.
allow_kill is off on purpose. A warden reachable from the network would
otherwise let anyone holding the token end processes on that machine, a far
bigger thing to hand out than a port number. warden kill on the command line is
unaffected; it acts locally and never asks the API.
One token opens everything: it registers a service, it writes a firewall rule,
it applies a ruleset across a fleet. That was fine while the API only handed out
ports inside a pool. Handing a deploy script that token now hands it the
firewall of every machine it can reach.
So a token can be given a name and a reach:
tokens = [
{ name = "deploy", scope = "registry", secret = "..." },
{ name = "grafana", scope = "read", secret = "..." },
{ name = "walls", scope = "firewall", secret = "..." },
]or, where the environment is what configures the machine:
WARDEN_TOKENS="deploy:registry:s3cret, grafana:read:hunter2"name:scope:secret, and the secret is everything after the second colon — so a
secret with colons in it needs no escaping.
| Scope | Reaches |
|---|---|
read |
Anything that only looks: services, pool, history, rules, the fleet views |
registry |
Registering, renewing, releasing, stopping a process — and reading |
firewall |
Writing, closing, applying, confirming and restoring rules — and reading |
all |
Everything. What a single token has always meant |
Reading is the floor: a token that may change a thing may also look at it, and never needs a second token to see what it just did.
A refusal says which token and how far it reaches, because "403" on its own has sent more than one person looking for the wrong problem:
the token 'deploy' may only registry, and this is a firewall thing to do
Nothing changes for a machine that has not asked for this. A single token
is still a token that reaches everywhere, and a machine with neither still asks
for nothing on loopback, exactly as before.
Named tokens are also the first time warden can say who. Every change records
the name of the token it arrived with, and warden history shows it:
WHEN WHAT SERVICE KIND ADDRESS PID ASKED BY
2m ago registered shop-api backend 10.4.0.7:8000 4242 deploy
5m ago released docs docs 10.4.0.7:8002 - at the machine
"at the machine" is somebody running warden release on the machine itself.
There is no token at a keyboard, so there is nobody to name — and the column
only appears where at least one row has a name.
| Setting | Default | Meaning |
|---|---|---|
webhook |
empty | Address events are posted to; must be http or https
|
webhook_format |
json |
json, discord, slack or teams
|
webhook_events |
all but renewed
|
Which actions are worth posting |
webhook_secret |
empty | Key the posted body is signed with, for json
|
webhook_colours |
empty |
node.stale=#e5544b, one event at a time |
webhook_titles |
empty |
node.stale=has stopped answering, the words after the subject |
webhook_icons |
empty |
node.stale=!, what stands in front of it; a single - means none |
warden settings embed edits the last three against a preview of the message,
which is easier than writing an inline table by hand.
webhook_events takes a whole scope (firewall.*), a full name
(node.stale), or the bare name a port event had in 0.2.0 (registered), in
any mix. A name that is none of those is refused by name rather than quietly
ignored, and warden events --known prints the whole list. port.renewed is
left out by default: a channel told about every heartbeat is a channel people
mute within the week.
The webhook applies to this warden only. In a fleet, every node reports its own events, so every node you want to hear from needs the setting.
See Events and webhooks.
| Setting | Default | Meaning |
|---|---|---|
firewall_backend |
the machine's own |
nftables, iptables, pf or windows
|
firewall_rollback |
60 |
Seconds to wait for a confirmation; 0 turns it off |
firewall_from_registry |
false |
Let the registry's ports be opened at all |
firewall_allow_from |
empty | Networks a rule from the registry may open to, either family |
allow_remote_firewall |
false |
Let a caller over the API change the rules |
firewall_from_registry and firewall_allow_from are off and empty on
purpose. Nothing declared is nothing allowed: a registry that could open ports
out of the box would be a way around the firewall rather than a firewall.
allow_remote_firewall is a separate decision about who may ask. Reading the
rules over the API is what a token already allows; changing them needs this,
and warden doctor fails a warden that has it set, listens beyond loopback and
asks for no token. See Firewall.
| Setting | Default | Meaning |
|---|---|---|
node |
the machine name | This warden's name in the fleet |
upstream |
empty | Hub to report to; empty means this one is a hub |
advertise |
from host and port | Address the hub should use to reach it |
node_ttl |
90 |
Seconds a node's entry stays fresh (10 to 86400) |
require_https |
false |
Refuse to register or send a token to a plain HTTP node |
The machine name is lowercased and stripped of anything a service name would not
accept, so BUILD-01.office.lan becomes build-01.office.lan rather than
refusing to start.
A node reports three times per node_ttl, never more often than every five
seconds.
See Cluster for what these do together.
| Variable | Flag | Default | Meaning |
|---|---|---|---|
WARDEN_URL |
--url, -u
|
http://127.0.0.1:7010 |
Which warden the CLI and the Python client talk to |
WARDEN_TOKEN |
--token |
empty | Token to send with each request |
WARDEN_URL is what points warden ls at a warden on another machine. Note that
warden ports and warden kill ignore it: they read the local machine directly.
| Thing | Rule |
|---|---|
| Service name | lowercase letters, digits, . _ -, starting with a letter or digit, up to 64 characters |
| Kind | lowercase letters, digits and -, up to 32 characters |
| Project | same shape as a service name |
ttl on a registration |
1 second to 24 hours |
node_ttl |
10 seconds to 24 hours |
| Ports | 1 to 65535, and pool_start may not exceed pool_end
|
A setting outside its range stops warden at startup with a message naming the
setting, rather than being quietly clamped. warden settings set refuses it
before it ever reaches the file.
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