A terminal UI for inspecting and managing nftables on Linux, written in Go.
Inspired by k9s, htop, and Midnight Commander: a multi-pane, keyboard-driven
view of the live ruleset that lets a firewall administrator navigate from
ruleset → table → chain → rule without leaving the terminal, then stage and
commit changes safely.
v1.0 ready. All six phases of the roadmap are shipped. The full read → edit → dry-run → commit → snapshot → restore loop works end-to-end against the real kernel; see docs/06-roadmap.md for the release summary and docs/07-deferred.md for known follow-ups.
- Netlink read path via
google/nftables— nonftshell-out for inspection - Live counters refreshed every 2 s (tunable), plus an opt-in
NFT_MSG_NEW*subscription that refreshes within 250 ms of any external change - Tree explorer + rule table with configurable column presets,
/filter,:global search,yyank to clipboard via OSC 52 - Live monitor (
m) — top-N rules by pps / bps / Δpkts, per-rule Unicode-block sparkline over the last ~2 min - Staged edits (
--write):aadd,o/Oinsert,eedit,ddelete;Dopens the diff page; F3 dry-runs vianft -c, F2 commits vianft -f - Form + raw editor, F8 toggles. The form covers the common-case fields; raw mode handles 100% of nftables
- Snapshot / restore via
:w <path>/:r <path>. Restore is guarded by a 60-second dead-man's switch that auto-rolls-back if not confirmed — recovers from SSH-lockout scenarios automatically - Audit log in
$XDG_STATE_HOME/nft-tui/— per-commit nft files plus a rollingaudit.logwith timestamp / UID / username / action / payload - Themes (
default,high-contrast,mono) via--theme - Single static binary (
CGO_ENABLED=0);.deb/.rpm/tar.gzbuilds via goreleaser; groff man page
Read-only inspection:
$ sudo nft-tuiWith editing enabled:
$ sudo nft-tui -writeDump the parsed ruleset (no TUI, pipe-friendly):
$ sudo nft-tui -dump | grep "dport 22"Development without privileges, inside an unshared user/net namespace:
$ unshare -rn ./nft-tuiVia the prebuilt container image (multi-arch, Alpine base with
nft installed):
$ docker run --rm -it --net=host --cap-add=NET_ADMIN \
ghcr.io/dobrevit/nft-tui:latest--net=host puts nft-tui in the host's network namespace so the
netlink socket sees the real ruleset; --cap-add=NET_ADMIN is what
lets it issue the nf_tables syscalls.
| Source | Command |
|---|---|
.deb (Debian / Ubuntu) |
sudo dpkg -i nft-tui_<ver>_linux_amd64.deb |
.rpm (Fedora / RHEL) |
sudo rpm -i nft-tui-<ver>.linux_amd64.rpm |
| Homebrew (Linuxbrew) | brew tap dobrevit/nft-tui && brew install nft-tui |
| Snap | sudo snap install --dangerous --classic nft-tui_<ver>_amd64.snap |
| Container | docker pull ghcr.io/dobrevit/nft-tui:latest |
| Static binary | grab the .tar.gz from the release page and tar xf; copy nft-tui to /usr/local/bin |
The static binary is the lowest-friction option — CGO_ENABLED=0,
runs against any glibc or musl. Every other format is a wrapper
around the same binary plus the man page, shell completions, and
example config.
See nft-tui -help and man nft-tui for the full reference.
nft-tui reads defaults from $XDG_CONFIG_HOME/nft-tui/config.toml
(or ~/.config/nft-tui/config.toml when XDG_CONFIG_HOME is unset).
CLI flags always override; a missing default file is silent. To
point at a specific file:
nft-tui --config /etc/nft-tui/config.tomlA documented sample lives at examples/config.toml
in the source tree (and is installed at
/usr/share/doc/nft-tui/config.toml.example by the .deb / .rpm).
Every release artifact's SHA-256 is in checksums.txt, and that file
is signed with cosign
via GitHub Actions OIDC (keyless — no public keys to chase). To
verify before installing:
# 1. Download the release artifacts:
# nft-tui_<version>_linux_amd64.tar.gz
# checksums.txt
# checksums.txt.sig
# checksums.txt.pem
# 2. Verify the signature against the GitHub workflow identity.
cosign verify-blob \
--certificate-identity-regexp 'https://github.com/dobrevit/nft-tui' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--cert checksums.txt.pem --signature checksums.txt.sig \
checksums.txt
# 3. Verify the artifact against the (now-trusted) checksum.
sha256sum --check --ignore-missing checksums.txtEach archive and binary also ships an SPDX-JSON SBOM
(<artifact>.sbom.json) for downstream scanners.
make build # → ./nft-tui (static, CGO disabled)
make test # unit tests
make integration # integration tests inside unshare -rn (needs nft binary)
make install # → $PREFIX/bin/nft-tui + $PREFIX/share/man/man1/nft-tui.1For release tagging, push a vX.Y.Z tag and run goreleaser release --clean
(see .goreleaser.yaml).
- Product brief — who, what, why
- Architecture — netlink reads,
nft -fwrites - Screen designs — ASCII mockups of every view
- Keybindings — the keymap, in one page
- Data model — how nftables maps to UI state
- Roadmap — phased delivery (all phases shipped)
- Deferred work — what was punted and why
Bug reports, patches, and ideas are welcome — see
CONTRIBUTING.md for the local dev loop, code
conventions, commit-message style, and how to report security issues
privately (devops@dobrev.it).
MIT — see the LICENSE file for the full text.
- A configuration generator for people who don't already know nftables. The
audience is admins who can write
nftby hand but want a faster way to inspect, diff, and edit a running ruleset. - A
firewalld/ufwreplacement. We target raw nftables; higher-level abstractions are out of scope. - A daemon.
nft-tuiis a short-lived interactive process. Persistent rule storage is whatever the OS already does (/etc/nftables.conf, systemd). - Multi-host fanout. If you want to manage 50 routers at once, use Ansible to
push
nftfiles; this tool is one host at a time.