CLI and environment reference
This reference applies to v0.1.8 and its oonfeewrtd and oonfeewrt-recoverycheck executables. Matching artifacts are available only after the exact-tag workflow and GitHub release complete.
Version and command boundary
v0.1.8 corrects LLDP rendering and shared-PHY radio identity while retaining v0.1.6 and v0.1.7 schema 25; it does not add a CLI command for firmware flashing, installing the optional helper, or extracting a newer backup into v0.1.5. Use a matching executable/recovery helper and follow migration and rollback. The separate synthetic preview commands are documented in Explore the isolated demo; they never open controller data.
oonfeewrtd
oonfeewrtd [flags]Flags
| Flag | Default | Meaning |
|---|---|---|
-data-dir <absolute-path> | /data, or OONFEE_DATA_DIR | Directory containing oonfeewrt.db, keyring.json, logs, and private job/recovery directories |
-listen <host:port> | :8080, or OONFEE_LISTEN | HTTP bind address |
-passphrase-file <path> | unset, or OONFEE_PASSPHRASE_FILE | Read runtime passphrase from a protected regular file instead of prompting |
-log-level <level> | info | One of debug, info, warn, error |
-healthcheck | false | Probe the configured listener's /healthz and exit without opening controller data |
-version | false | Print the embedded version and exit without opening controller data |
-h, -help | — | Print standard flag help; v0.1.8 then exits non-zero (a known CLI quirk) |
Flags are parsed after environment configuration, so an explicit flag overrides a valid corresponding environment value. Environment loading/validation happens first; an invalid non-empty environment setting fails before flags are parsed.
Environment variables
| Variable | Accepted value | Notes |
|---|---|---|
OONFEE_DATA_DIR | Absolute directory path | Default /data |
OONFEE_LISTEN | Go-style host:port | Default :8080 |
OONFEE_PASSPHRASE_FILE | Path to protected regular file | Used for unattended startup and recovery tooling |
OONFEE_PASSPHRASE | Rejected | A passphrase value must never be supplied through the environment |
OONFEE_PASSPHRASE fails startup because environment values can be exposed through process inspection, child processes, crash reports, and docker inspect.
Data-directory rules
-data-dir must be absolute. A relative path is rejected so a working-directory change cannot silently create a second empty controller.
The process secures the data directory to mode 0700 and newly created SQLite database/WAL/SHM files to 0600. Run it as the operating-system user that owns the state. The container defaults to UID 65532; bind-mounted deployments may instead explicitly run as the owning host UID/GID.
Passphrase-file rules
The file must:
- be a regular file, not a directory or device;
- not be group- or world-readable;
- be non-empty; and
- be readable by the controller process.
One trailing LF or CRLF sequence is removed; other whitespace is retained. Mode 0600 is the documented choice.
The first interactive start, with no passphrase file, prompts twice to create the keyring. Later interactive starts prompt once. A non-interactive process without -passphrase-file has no passphrase source and fails instead of starting with an empty keyring.
Common daemon commands
Print the version
oonfeewrtd -versionFor release v0.1.8 the output must be:
v0.1.8Interactive local start
install -d -m 0700 "$PWD/data"
oonfeewrtd \
-data-dir "$PWD/data" \
-listen 127.0.0.1:80802
3
4
Open http://127.0.0.1:8080 after the controller reports that it is listening.
Unattended local start
install -d -m 0700 "$HOME/.local/share/oonfeewrt" "$HOME/.config/oonfeewrt"
umask 077
head -c 32 /dev/urandom | base64 > "$HOME/.config/oonfeewrt/passphrase"
chmod 600 "$HOME/.config/oonfeewrt/passphrase"
oonfeewrtd \
-data-dir "$HOME/.local/share/oonfeewrt" \
-passphrase-file "$HOME/.config/oonfeewrt/passphrase" \
-listen 127.0.0.1:80802
3
4
5
6
7
8
9
The generated passphrase file is now the unattended unlock secret, not an independent second factor. Back it up and protect it accordingly.
Set environment configuration
export OONFEE_DATA_DIR=/absolute/path/to/oonfeewrt-data
export OONFEE_LISTEN=127.0.0.1:8080
export OONFEE_PASSPHRASE_FILE=/absolute/path/to/mode-600-passphrase
oonfeewrtd2
3
4
Do not export the passphrase value itself.
Change log level
oonfeewrtd \
-data-dir /absolute/path/to/oonfeewrt-data \
-passphrase-file /absolute/path/to/mode-600-passphrase \
-listen 127.0.0.1:8080 \
-log-level debug2
3
4
5
Debug logging can contain more operational detail. Reproduce the problem, collect a diagnostics bundle if appropriate, then return to info.
Release features without daemon flags
v0.1.2 compatibility export and v0.1.3 effective-WAN selection are automatic application behavior; neither adds a daemon flag or environment variable.
- To create a compatibility report, sign in as Administrator or Owner, open Adopt a device, complete read-only Inspect, and choose Export sanitized compatibility report. The browser downloads the server-produced JSON. There is no supported command that serializes the full Inspect response, because it contains fields outside the share-safe allowlist.
- Effective-WAN evidence is collected automatically for adopted gateways on the network/topology cycle. Existing v0.1.2 adoptions need no CLI migration, ACL refresh, or re-adoption. There is no manual-WAN-selection flag in v0.1.8.
v0.1.4 adds per-network IPv6 policy, router-time observation, topology projection fixes, and filter- and page-independent current state/action UI for IPv6 warning conditions as application behavior, not daemon flags. Exact-row warning compaction predates this release and shipped in v0.1.1. Verified quiet log coverage clears the current condition banner without deleting retained history or router logs.
Existing adoptions keep ordinary polling and management access. Router-clock status alone needs a separately reviewed controller-access payload refresh; re-adoption is not required. Explicit management-LAN IPv6 modes are a narrow exception to the normal owned-section write rule: behind Preview and Apply they may patch only allowlisted options on exact existing LAN/DHCP and supported conventional wan/wan6 sections, never create, claim, rename, or delete them.
v0.1.5 management mode and policy sets are API/UI behavior, not daemon flags. Existing devices migrate to Managed. Selecting Monitor only during adoption installs the distinct read-only oonfeewrt-monitor ACL after review; changing an adopted device's mode requires the reviewed un-adopt/re-adopt workflow, and the daemon has no reclassification flag. Named exact-MAC policy sets are maintained in Policy Engine and can be referenced by firewall rules; changing a set does not bypass Preview or Apply. There is no CLI override for the local managed-Gateway MAC-scope proof: any policy-set member, direct or set-backed MAC Secure draft, and client block or fixed-address intent requires a stored local observation from the currently adopted Managed Gateway. Monitor-only observations neither satisfy nor contaminate that source-relative proof, including after un-adoption. After an upgrade or portable restore, active MAC intent can fail Preview until the next successful managed- Gateway poll recreates missing observations; portable restore deliberately clears them. Evidence outside the 30-day age and five-minute future-skew window is rejected independently of cleanup. Existing blocked/fixed-address intent can still be cleared one client at a time.
The Phase 5 flow-visibility page is a feasibility record. v0.1.8 adds no nlbwmon, netifyd, DPI, or flow-collector daemon flag and installs no such package.
OONFEE_HTTP_BIND belongs to the supplied Docker Compose file and selects the host-side publish address. It is not read by oonfeewrtd and does not replace the container's OONFEE_LISTEN=:8080.
v0.1.8 retains v0.1.6 and v0.1.7 database schema 25 without a new migration. From v0.1.5, the existing automatic path is 23 → 24 → 25: persistent alert state, then encrypted AdGuard Home settings. It does not create rules, connect a service, install a helper, or configure routers. Older supported versions apply their existing migrations first. Before startup, preserve and verify the matching pre-upgrade database, keyring, runtime passphrase, and old executable/image. A v0.1.5 executable cannot open schema 24 or 25. A rollback must restore its schema-23 recovery unit; changing only the executable or image tag is not a rollback. Returning to v0.1.4 needs its own schema-20 unit. There is no CLI schema-downgrade or firmware-flashing override. CLI compatibility does not extend the current REST/WebSocket surface into a stable third-party API guarantee.
Healthcheck
oonfeewrtd -listen 127.0.0.1:8080 -healthcheckThe healthcheck:
- derives
http://<listener>/healthzfrom the configured listener; - converts wildcard
0.0.0.0to127.0.0.1and::to::1; - uses a four-second timeout;
- does not use ambient HTTP proxy variables;
- expects status
200and body exactlyok; and - does not open the database, keyring, data directory, or passphrase file.
It checks process HTTP liveness, not router reachability, database backup quality, or full fleet health.
Container example:
docker exec oonfeewrt /oonfeewrtd -healthcheckThe release container uses this executable healthcheck internally.
Signals and shutdown
SIGINT and SIGTERM start graceful shutdown. The controller stops accepting work, drains bounded requests/background jobs, lets an Apply that reached its critical stage resolve its confirm/rollback outcome, flushes complete metric windows, checkpoints SQLite, and exits.
Do not use SIGKILL for routine upgrades. The supplied container uses a 150-second stop timeout to give Apply and storage work room to finish.
oonfeewrt-recoverycheck
The release archive includes a read-only recovery helper:
oonfeewrt-recoverycheck /path/to/recovery/oonfeewrt.dbIt has no data/listen flags. Set OONFEE_PASSPHRASE_FILE to the controller runtime passphrase file:
OONFEE_PASSPHRASE_FILE=/absolute/path/to/mode-600-passphrase \
oonfeewrt-recoverycheck /absolute/path/to/backup/oonfeewrt.db2
The helper requires:
- exactly one database path;
- a regular, non-symlink database file;
- a regular, non-symlink sibling
keyring.json; - no non-empty
oonfeewrt.db-waloroonfeewrt.db-journalsidecar; - a current-schema database; and
- the passphrase that opens that exact keyring.
It opens SQLite through the read-only recovery boundary and makes no network call. A successful result has this shape:
schema=23 devices=<n> credentials=<n> owned_sections=<n> wlans=<n> meshes=<n>Those counts prove that the pair can be opened and its recovery invariants are readable. They do not prove that every router is reachable or currently matches the stored desired state, that a compatibility report can be produced, or that the current default route can be proved.
Manual backup verification example
For a live binary installation, use SQLite's online backup API and copy the matching keyring:
install -d -m 0700 /absolute/path/to/private-backup
sqlite3 /absolute/path/to/live/oonfeewrt.db \
".backup '/absolute/path/to/private-backup/oonfeewrt.db'"
cp -p /absolute/path/to/live/keyring.json \
/absolute/path/to/private-backup/keyring.json
OONFEE_PASSPHRASE_FILE=/absolute/path/to/mode-600-passphrase \
oonfeewrt-recoverycheck /absolute/path/to/private-backup/oonfeewrt.db2
3
4
5
6
7
8
Do not copy only the live main SQLite file while WAL mode is active.
Exit behavior
- Normal
-version, successful-healthcheck, and clean daemon shutdown exit successfully. - Configuration, startup, listener, passphrase, or healthcheck failures print an
oonfeewrtd:error to standard error and exit non-zero. oonfeewrt-recoverycheckexits2for invocation/path errors and1when the selected recovery pair fails validation.
See Requirements, Data and retention, and Troubleshooting.