Files
housecarl/docs/operations.md
T
abrown38andClaude Opus 5.5 34292eeebb Build Housecarl 0.1.0: the nftables firewall manager
Zones, address sets (IPv4 and IPv6 mixed, dynamic sets with timeouts) and
services, ordered rules in the early, input, forward and output chains,
port forwards with hairpin NAT and IPv6 pinholes, source NAT, redirects,
and switchable built-ins (loopback, conntrack, ICMPv6, antispoofing, MSS
clamping, DHCPv6 client, flowtable). Every change is validated, checked
with nft -c and applied in one transaction to Housecarl's own table,
inet housecarl; changes made over the network roll back unless
confirmed, and the confirmed ruleset is loaded at boot by
housecarl-ruleset.service. An empty configuration applies nothing.

Also: hit counters and the drop log (nflog), 'hc import' of an existing
nftables ruleset and 'hc takeover', the hc CLI, the REST API and the web
UI, users, scoped tokens (sets:write:NAME), the audit log, the web UI's
certificate through Jarl, Debian packages, docs, unit tests with real
nft 1.1.3, and an e2e test with real traffic (71 checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 07:57:14 +01:00

4.7 KiB

Running Housecarl

The services

systemctl status housecarl          # housecarld: the API, the web UI, the log
journalctl -u housecarl -f
systemctl reload housecarl          # reread the TLS certificate
systemctl status housecarl-ruleset  # the ruleset loaded at boot

The firewall itself is the kernel's: it stays in force while housecarld is stopped, restarted or upgraded. Without housecarld there is no API, no web UI, no log and no probation timer.

housecarld logs each change it applies, rollbacks, and what it couldn't apply. When it starts, it applies the configuration again (rolling back first what was on probation when it stopped).

Changes on probation

Changes made over the network roll back unless confirmed (design.md):

hc status              # Probation: 2 changes roll back in 97s unless confirmed
hc confirm
hc rollback            # or undo them now

The web UI shows a banner with a countdown and both buttons. A rollback is in the history, as an undo by housecarl via rollback, so it can be undone like any change.

If you are cut off by a change: wait. When the time is up, the previous ruleset comes back by itself. If you are cut off by a confirmed change, use the console, or SSH from a source the rules still let in:

sudo hc history list
sudo hc history undo 42

The ruleset at boot

A confirmed ruleset (or one changed through the socket) is saved to /var/lib/housecarl/ruleset.nft, which housecarl-ruleset.service loads before the network comes up. To see what would load:

sudo cat /var/lib/housecarl/ruleset.nft
sudo nft -c -f /var/lib/housecarl/ruleset.nft     # check it

Dynamic sets start empty after a reboot.

Keep Debian's nftables.service disabled, or /etc/nftables.conf without flush ruleset: otherwise it deletes Housecarl's table at boot. housecarl-ruleset.service runs after it, which covers the ordinary case.

Hits

Every rule, NAT rule, built-in and policy has a counter. hc rule list, hc forward list and the web UI show packets; hc counters shows them all, with bytes. They count from housecarld's start, and carry across changes to the ruleset.

The log

Rules with --log (Log in the web UI) and, with hc settings set --log-drops on, what the input and forward policies drop (at most 10 packets a second) are logged:

hc log -f
hc log --search 198.51.100.7
10:02:13  hc input #95 drop:     wan  -   198.51.100.7:53868 -> 203.0.113.7:22   tcp syn
10:02:15  hc forward policy drop: wan  enp2s0  198.51.100.9:443 -> 10.0.10.20:51432  tcp

The packets go to netlink log group 4171, where housecarld reads them; the last 2000 are kept in memory. They aren't written to the kernel log or the journal. A rule's log isn't rate-limited: on a busy rule, give it a limit, or log only new connections (--state new).

When something doesn't get through

  1. hc log -f with --log-drops on: is it dropped by a policy (no rule accepted it), or by a rule (its number is in the line)?
  2. hc rule list forward (or input): hits on the rule you expect?
  3. hc ruleset: the rule as nftables sees it, with the zones' interfaces and the sets' families.
  4. hc status: other tables. A Docker or Incus table, or an old one, can drop what Housecarl accepts.
  5. Port forwards: hc forward list hits, and the inside host's own firewall and default route (answers must go back through Housecarl).

Backups

housecarl-backup.timer runs housecarld backup daily. It writes a consistent copy of the database to backup.dir (/var/backups/housecarl/housecarl-<time>.db), and deletes those older than backup.retention (30 days), keeping at least backup.keep_at_least (7). A backup holds everything: configuration, history, users, tokens (hashed) and the audit log.

sudo -u housecarl housecarld backup                 # now
sudo -u housecarl housecarld backup /tmp/h.db       # to a file of your choice
sudo systemctl disable --now housecarl-backup.timer # no daily backups

To restore, stop housecarld first; restore refuses to replace the database under it:

sudo systemctl stop housecarl
sudo -u housecarl housecarld restore /var/backups/housecarl/housecarl-20261014T020000Z.db
sudo systemctl start housecarl

housecarld applies the restored configuration when it starts. The old database is kept next to it as housecarl.db.before-restore-<time>.

Upgrades

apt upgrade restarts a running housecarld. A new version upgrades the database when it starts, and an older one refuses a database a newer one has upgraded: restore a backup to go back.

Checks

housecarld check validates the configuration in the database against this machine's interfaces, the same checks as hc status shows (validation.md).