systemd service
Warden runs as a systemd service. Here is what the units do and how to manage them.
What this is
The installer sets up three systemd units in /etc/systemd/system/:
| Unit | What it is |
|---|---|
purge-warden.service | The DNS daemon. Enabled and started by the installer. |
purge-warden-backup.service | A one-shot job that runs warden config backup --auto. You do not start it yourself. |
purge-warden-backup.timer | Wakes the backup job every hour. Enabled and started by the installer. |
All three run as the purge-warden user, never as root. They run the real binary
at /usr/local/libexec/purge-warden/warden, not the /usr/local/bin/warden
wrapper.
Everyday commands
systemctl status purge-warden # is it up?
sudo systemctl restart purge-warden # full restart
sudo systemctl reload purge-warden # reload the configuration without a restart
journalctl -u purge-warden -f # follow the log
journalctl -u purge-warden --since "1 hour ago"reload sends the daemon SIGHUP, which re-reads the configuration and the
lists without dropping queries. warden reload does the same through the
control socket.
To stop Warden from starting at boot:
sudo systemctl disable --now purge-wardenStopping the daemon means this machine no longer answers DNS. If your router points at it, every device loses name resolution until you start it again.
Which configuration the service reads
The service passes no --config flag. It finds the configuration the same way
the warden command does for the purge-warden user: first
/etc/purge-warden/config.toml, then /var/lib/purge-warden/config.toml. A
fresh install of 0.44.0 or later uses the first. A host upgraded from an earlier release
keeps using the second until you run warden config relocate. The unit needs no
change when you move. See Upgrade.
What the daemon unit allows
purge-warden.service runs the daemon in a tight sandbox:
- Port 53 without root. The unit grants only
CAP_NET_BIND_SERVICE, throughAmbientCapabilities. No other capability is available. - Read-only system.
ProtectSystem=strictmakes the whole file system read-only for the daemon, except these paths:/etc/purge-warden(the unit ignores it if it does not exist),/var/lib/purge-warden, and/run/purge-warden.ProtectHome=yeshides home directories. - No new privileges, private
/tmpand devices, and no access to kernel settings, modules or logs. - Network. Only IPv4, IPv6, Unix sockets and netlink.
- System calls. Filtered to the
@system-serviceset, without the privileged and resource groups. A statically linked musl build is killed by this filter. See Build from source. - Files it creates are private to the service (
UMask=0077). The state directory/var/lib/purge-wardenhas mode0750, and/run/purge-wardenhas mode0755.
The daemon rewrites config.toml whenever you change something with a
warden command, so /etc/purge-warden has to stay writable for it. That is
why the unit lists it under ReadWritePaths.
Restart behavior
The unit restarts the daemon after a failure, five seconds later
(Restart=on-failure, RestartSec=5). After a few failed starts in quick
succession, systemd stops trying and the unit shows failed. Fix the cause, then
run sudo systemctl reset-failed purge-warden and start it again.
Exit status 75 from the daemon is not a failure. It means a Warden Nodes
operation needs a fresh process, and systemd restarts the daemon on purpose
(SuccessExitStatus=75 and RestartForceExitStatus=75). Do not remove these
two lines or list 75 under RestartPreventExitStatus=. The daemon refuses a
managed restart when the unit is set up that way.
The backup timer
purge-warden-backup.timer fires 15 minutes after boot and then every hour. If
the machine was off when a run was due, it runs at the next boot. The job reads
[backup] auto_interval and does nothing when no backup is due yet, so an hour
is only how often Warden asks. A fresh install sets no auto_interval, so the
job does nothing until you add one under [backup], for example
auto_interval = "24h". Check it with:
systemctl status purge-warden-backup.timer
systemctl list-timers purge-warden-backup.timer
journalctl -u purge-warden-backup.serviceThe backup job has the same sandbox, with these differences: it opens no
network sockets, and it has RestrictSUIDSGID=no, because tar on Fedora 44
needs it. The job writes only to /etc/purge-warden and /var/lib/purge-warden.
If you keep archives somewhere else, give it that path with a drop-in (see
below). See Backup & restore for the
settings.
Change a unit safely
Do not edit the files in /etc/systemd/system/ by hand. The installer and
install.sh --upgrade replace them. Use a drop-in, which survives upgrades:
sudo systemctl edit purge-warden-backup.serviceFor example, to let the scheduled backup write to /srv/purge-backups:
[Service]
ReadWritePaths=/srv/purge-backupsThen run sudo systemctl daemon-reload. The drop-in adds to the unit’s
ReadWritePaths; it does not replace them. The directory must exist and belong
to purge-warden.
See also
- Backup & restore: the timer, the schedule and the state file.
- Upgrade: how the upgrade replaces the binary and the units.
- File paths: every path the service touches.
- Troubleshooting: what to check when the service will not start.