Build from source
Compile Warden from source and install it on any Linux distribution.
Most people should install the package instead — it’s faster and upgrades cleanly. If your distribution has one, use the Debian / Ubuntu or Fedora guide. Build from source when there’s no package for your distribution (Arch, RHEL, openSUSE, …), when you want to turn on optional features, or when you need to target an older glibc than the prebuilt package supports.
Nothing here touches your network until the last step: you compile the binary, install it alongside a hardened systemd unit, free up port 53, then start Warden and confirm it’s blocking.
Requirements
- A Linux distribution with
systemd - Architecture:
x86_64(aarch64 / ARM is cross-compile only — see the end) - Root /
sudo
Because you build on your own machine, the binary links whatever glibc that machine already has — so there’s no minimum-version hurdle the way there is with the prebuilt package. The build tools themselves are installed in the next step.
1. Install build tools
You need a C compiler, make, pkg-config, git, and a Rust toolchain (1.94 or newer). Warden’s TLS stack is pure Rust (rustls + ring) — there is no OpenSSL dependency to install.
# Fedora / RHEL
sudo dnf install gcc make pkg-config git
# Debian / Ubuntu
sudo apt install build-essential make pkg-config gitInstall Rust with rustup (the toolchain manager) if you don’t already have it:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source ~/.cargo/envYou’ll also want dig for the final check — it’s bind-utils on Fedora (usually pre-installed) and dnsutils on Debian / Ubuntu.
2. Get the source
git clone {{TODO: clone URL}}
cd wardenRun every command below from this directory — the build and install steps use paths relative to the repository root.
3. Build
cargo build --releaseThis produces the warden binary at target/release/warden — the daemon and the CLI in one executable.
Optional features are off by default. Turn one on at build time if you need it, for example cargo build --release --features dnssec (also doq and cluster).
4. Install
Install the binary, scaffold the config, then drop in the systemd unit:
sudo install -m 0755 target/release/warden /usr/local/bin/warden
sudo warden init --yes
sudo install -m 0644 systemd/purge-warden.service /etc/systemd/system/
sudo systemctl daemon-reloadWhat each line does:
- installs the
wardenbinary to/usr/local/bin warden init --yescreates thepurge-wardensystem user, a working default config at/var/lib/purge-warden/config.toml, and the data directories — with--yesit accepts the defaults non-interactively; drop--yesto pick your blocklists and allowed clients at a prompt- installs the hardened unit, which runs Warden as the unprivileged
purge-wardenuser and grants it onlyCAP_NET_BIND_SERVICEso it can bind port 53 — nosetcapstep needed
Prefer a shortcut? sudo make install places the binary, unit, and an example config in one step; you still run sudo warden init --yes afterwards to create the user and live config, then sudo systemctl daemon-reload.
5. Free port 53 (if needed)
Check what holds port 53 first with sudo ss -ulpn 'sport = :53'. If nothing is listening there, skip this step. Otherwise, if this machine runs systemd-resolved on port 53 (common on desktop Linux), hand port 53 to Warden by disabling only the stub listener:
printf '[Resolve]\nDNSStubListener=no\n' | \
sudo tee /etc/systemd/resolved.conf.d/purge-warden-no-stub.conf
sudo systemctl restart systemd-resolved6. Enable + start
sudo systemctl enable --now purge-warden7. Verify
On first start Warden fetches its blocklists, so allow a few moments before doubleclick.net resolves to 0.0.0.0.
Point your router’s or devices’ DNS at this machine’s IP to protect the whole network.
Upgrading
Pull the latest source, rebuild, and replace the binary:
git pull
cargo build --release
sudo install -m 0755 target/release/warden /usr/local/bin/warden
sudo systemctl restart purge-wardenYour config in /var/lib/purge-warden/config.toml is preserved across upgrades. If a release ships a changed systemd unit, reinstall it as in step 4 and re-run sudo systemctl daemon-reload before restarting.
Removing
There’s no package manager to undo a source install, so remove the pieces by hand:
sudo systemctl disable --now purge-warden
sudo rm /usr/local/bin/warden /etc/systemd/system/purge-warden.service
sudo systemctl daemon-reloadThat stops and removes the program but leaves your config and data in /var/lib/purge-warden. For a clean slate, also delete that directory and the system user:
sudo rm -rf /var/lib/purge-warden
sudo userdel purge-wardenBuilding for ARM (aarch64)
ARM builds are cross-compiled and best-effort — not yet packaged or tested on real hardware. If you want to try, BUILDING.md in the repository documents the cross build --target aarch64-unknown-linux-musl route. Note that the shipped systemd unit’s syscall filter kills a static musl binary — it was rejected on x86_64 for exactly this reason — so an ARM build needs the unit’s hardening relaxed.
Older distributions (glibc < 2.39)
Building on the target machine sidesteps this entirely — cargo links whatever glibc is already installed, so a binary built on Ubuntu 22.04 runs on Ubuntu 22.04. The only hard floor is Rust 1.94, which rustup provides on any distro. You only need a build container or cargo-zigbuild tricks in BUILDING.md when cross-building on a newer host for an older target.