Files
housecarl/docs/cli.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

8.2 KiB

The hc CLI

hc talks to housecarld's REST API. hc help COMMAND describes each command and its flags.

Connecting

  • On the firewall, with nothing configured, the CLI uses housecarld's local socket, /run/housecarl/housecarl.sock. Root and the housecarl user are administrators there without a token, and their changes need no confirmation: sudo hc status.

  • From elsewhere, give the server's URL and an API token:

    hc config set server https://fw.example.com:8070
    hc config set token          # asks for it
    

    The settings are in ~/.config/housecarl/config.yaml (on macOS ~/Library/Application Support/housecarl/config.yaml, on Windows %AppData%\housecarl\config.yaml).

Flag Environment
-s, --server URL HOUSECARL_SERVER the server; local for the local socket
--token TOKEN or @FILE HOUSECARL_TOKEN the API token
--config FILE HOUSECARL_CLI_CONFIG the CLI's configuration file
HOUSECARL_SOCKET the local socket's path
--insecure, --ca-cert FILE TLS: skip the check, or trust another CA
-n, --dry-run check and show a change without making it
-o, --output FORMAT table (default), json, yaml or id
-q, --quiet print only errors (and the IDs of new objects)

Exit codes: 0 ok, 1 error, 3 not authenticated or not allowed, 4 not found, 5 conflict, 6 invalid or refused by validation or nftables, 7 server error.

Changes

Every change is checked as a whole, then by nftables, before it is put in force. A refused change says why, with the problem's code (validation.md). An applied one says its history entry and any new warnings. Over the network, it is on probation:

$ hc rule add input --from trusted --service ssh --comment "SSH from home"
created rule input #31 (from trusted · ssh)
applied on probation (history 12): confirm with 'hc confirm' within 2m0s, or it is rolled back
$ hc confirm
confirmed 1 change; it is kept and loaded at boot

Through the socket the change is kept at once:

applied and saved (history 12; undo with 'hc history undo 12')

-n shows what would change without changing it; nftables checks it too.

Commands

Objects are named by ID or, for zones, sets, services and port forwards, by name.

status and the ruleset

Command
status the ruleset (in force or not), changes on probation, problems, interfaces, other tables
interfaces the machine's interfaces, their addresses and zones
ruleset the nftables ruleset Housecarl builds
counters the hits of every rule, NAT rule, built-in and policy, by mark (r12, f3, b-established, p-input)
log [-f] [--search TEXT] [--limit N] the packets logged by rules and policies (operations.md)

zone, set, service

Command
zone list, zone show ZONE
zone add NAME -i IFACE... [--external] [--comment C]
zone update ZONE [-i IFACE]... [--add IFACE] [--remove IFACE] [--external[=false]] [--name N] [--comment C] -i replaces the interfaces
zone delete ZONE refused while rules use it
set list, set show SET
set add NAME [ENTRY...] [--dynamic] [--timeout 24h] [--comment C]
set update SET [--entry E]... [--add E] [--remove E] [--timeout] [--name] [--comment] --entry replaces the entries
set entries SET, set entries add SET ADDRESS [--timeout 1h], set entries remove SET ADDRESS a dynamic set's entries
set delete SET
service list, service show SERVICE with the built-in ones
service add NAME ENTRY... [--comment C] entries tcp/22, udp/1000-2000, icmp/echo-request, icmpv6/packet-too-big
service update SERVICE, service delete SERVICE

See rules.md.

rule

Command
rule list [CHAIN] in order, with their hits
rule show ID
rule add CHAIN [MATCH] [-a ACTION] [--first|--before ID|--after ID] at the end of its chain unless placed
rule update ID [flags] only the flags given
rule move ID --before ID|--after ID|--first|--last|--chain CHAIN
rule enable|disable ID
rule delete ID

The match flags (rule add, snat add, redirect add):

--in ZONE, --out ZONE (--not-in, --not-out) zones
--from, --to (--not-from, --not-to) sets, addresses, prefixes, ranges
--service services or entries
--family ipv4|ipv6

And for rules: --state, --status, --days, --hours, --limit 10/minute[,burst=N][,over][,per-source], --conn-limit N, -a accept|drop|reject|log, --reject-with tcp-reset, --log, --log-prefix, --raw RULE, --comment, --disabled (rules.md).

forward, snat, redirect

Command
forward list, forward show FORWARD port forwards, with their hits
forward add PORTS --to HOST[:PORT] [--proto tcp,udp] [--public ADDR]... [--from SRC]... [--hairpin] [--hairpin-from SRC]... [--to6 HOST] [--name N] [--comment C]
forward update FORWARD [flags], forward delete FORWARD
snat list, snat add [MATCH] [--snat-to ADDR], snat update ID, snat delete ID source NAT, in order; masquerade without --snat-to
redirect list, redirect add [MATCH] [--to-port PORT], redirect update ID, redirect delete ID

See nat.md.

settings

Command
settings show
settings set [--input-policy|--forward-policy|--output-policy accept|drop] [--log-drops on|off] [--builtin NAME=on|off]... [--own-prefix P]... [--antispoof-v4 P]... [--antispoof-v6 P]... [--flowtable DEV]... [--probation 2m] lists given replace the old ones

probation, history, import

Command
confirm keep the changes on probation; the ruleset is saved for the boot
rollback undo the changes on probation now
history list [--limit N] changes, newest first
history show ID each object before and after
history undo ID apply the change backwards (refused if something it touched has changed since)
import [FILE|-] [--text FILE] [--defines FILE] [--table T] [--replace] import.md
takeover TABLE... [-y] delete tables Housecarl's ruleset replaces (administrators)

cert

Administrators only (certificates.md).

Command
cert the certificate: name, CA, validity, renewal, the last check
cert check check that the challenge can be published through Jarl and seen, without the CA (exit code 1 if it can't)
cert renew [-w] get a new certificate now; -w waits and shows the result

users, tokens, audit

Command
whoami who you are to the server, and what you may do
user list|add|update|delete users (administrators); user add NAME --role operator
token list [--all], token create NAME [--role R] [--grant G]... [--expires 90d] [--user U] [--save], token revoke ID API tokens
token rotate ID|--current [--grace 1h] [--expires 90d|never] [--save] a new secret for a token, the old one working for the grace period
password change your password
audit [--user U] [--action PREFIX] [--search TEXT] the audit log
config show, config set server|token|insecure|ca_cert [VALUE] this CLI's settings

permissions.md explains roles and grants.

housecarld

The daemon's own commands work on the database directly, as root or the housecarl user (sudo -u housecarl housecarld ...):

Command
housecarld serve run (the systemd unit does)
housecarld init [-u NAME] [--token] create the database and the first administrator (asks for the name on a terminal)
housecarld user add NAME [--admin], user password NAME, user token NAME TOKEN-NAME when the API can't be used
housecarld check check the configuration against this machine's interfaces
housecarld backup [FILE], housecarld restore FILE operations.md
housecarld config [--example] the settings in use, or a commented example
housecarld version

All take -c FILE for another configuration file.