# 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: ```sh 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](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](operations.md#the-log)) | ### 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](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](rules.md#rules)). ### 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](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](import.md) | | `takeover TABLE... [-y]` | delete tables Housecarl's ruleset replaces (administrators) | ### cert Administrators only ([certificates.md](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](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](operations.md) | | `housecarld config [--example]` | the settings in use, or a commented example | | `housecarld version` | | All take `-c FILE` for another configuration file.