Skip to content

FHS Compliance

Antonios Voulvoulis edited this page Jul 11, 2026 · 19 revisions

FHS Compliance

Last verified against code: v1.218.7 (2026-07-08). All tables on this page are cross-checked against build/fhs-spec.yaml, install/systemd/tmpfiles.d/nftban.conf, install/systemd/sysusers.d/nftban.conf, install/packaging/deb/nftban-dir-attrs.list, install/packaging/rpm/nftban-files.inc, and packaging/build_nftban.sh at that HEAD. If you make a packaging change, please update this page in the same review.

NFTBan follows the Linux Filesystem Hierarchy Standard (FHS 3.0) for all file placement, ownership, and permissions.


Table of Contents


Purpose

Ensure all NFTBan files are placed according to Linux FHS 3.0 conventions for security, maintainability, and distribution compatibility. All paths, permissions, and ownership are defined in a single canonical specification and enforced at install time, runtime, and via periodic health checks.


Source of Truth

All filesystem paths are defined in build/fhs-spec.yaml. Packaging artifacts (tmpfiles.d, sysusers.d, RPM %files, DEB postinst) are generated from this file. Do not manually edit generated files.

The runtime implementation is in cli/lib/nftban/core/nftban_fhs_spec.sh, which provides programmatic access to paths, permissions, and validation functions.


System Users and Groups

The intended identity set is declared in /usr/lib/sysusers.d/nftban.conf (generated from fhs-spec.yaml).

Type Name Purpose
Group nftban Admin/Operator group (full CLI access + Polkit)
Group nftban-auditor Auditor group (read-only report and log access)
Group nftban-panel (retired v1.137) Historical panel-integration group — not created by current packages (only nftban + nftban-auditor are)
User nftban Service account (home: /var/lib/nftban, shell: /usr/sbin/nologin)

The nftban user is also a member of the nftban-auditor group.

The sysusers.d file is the declarative identity recipe — it states what identities the package expects to exist. The execution mechanism that actually creates these identities at install time is the package scriptlet (DEB postinst / RPM %pre), not systemd-sysusers. See Identity authority model below.


Identity authority model: sysusers.d format vs identity creation mechanism

NFTBan adopts the sysusers.d declarative format as the source of identity intent, but does not yet adopt systemd-sysusers as the runtime execution mechanism. These are two separate decisions; the project has made the first one and deliberately deferred the second.

Why distinguish format from mechanism

A package can ship a sysusers.d file as a recipe for system identities without that recipe being executed by systemd-sysusers. The recipe records the contract — names, group memberships, descriptions — and the mechanism that materialises that contract is a separate concern. Many distributions allow either:

  • Declarative + systemd-sysusers execution — the file is consumed by systemd-sysusers at package-install time.
  • Declarative + scriptlet execution — the file is shipped as the recipe of record, but getent / groupadd / useradd in DEB postinst / RPM %pre actually create the identities.

NFTBan currently uses the second model. The sysusers.d file is the recipe; the lifecycle scriptlets are the mechanism.

Current execution path

Production package install (both DEB and RPM) creates identities through getent / groupadd / useradd in lifecycle scriptlets — see the postinst heredoc constructed in packaging/build_nftban.sh. systemd-sysusers is not invoked during install.

# Conceptual shape of the postinst (DEB) / %pre (RPM) — actual production mechanism:
getent group nftban         >/dev/null || groupadd -r nftban
getent group nftban-auditor >/dev/null || groupadd -r nftban-auditor
# nftban-panel group retired v1.137 — current packages create only nftban + nftban-auditor
getent passwd nftban        >/dev/null || useradd -r -g nftban \
    -d /var/lib/nftban -s /usr/sbin/nologin -c "NFTBan system user" nftban

Three different files named nftban.conf — directory is the namespace

The basename nftban.conf appears in three different locations with three different authorities. The directory determines the meaning; the basename alone is ambiguous.

Path Role Operator-editable?
/etc/nftban/nftban.conf NFTBan application/operator config (runtime behaviour, feeds, thresholds) yes
install/systemd/sysusers.d/nftban.conf/usr/lib/sysusers.d/nftban.conf systemd identity recipe (declares groups + user) no — generated
install/systemd/tmpfiles.d/nftban.conf/usr/lib/tmpfiles.d/nftban.conf systemd directory/runtime path recipe (declares mode + owner of /var/lib/nftban/*, /run/nftban, etc.) no — generated

When referring to any of these in code review, audit notes, or operator docs, always include the full path or the qualifier (sysusers.d/nftban.conf, tmpfiles.d/nftban.conf). The bare basename without directory context is not enough.

Precedent in other distributions

This format-first, mechanism-second adoption is consistent with packaging direction in major distributions, without overclaiming alignment:

  • Fedora has discussed adopting the sysusers.d format as the canonical identity declaration while keeping macros/scriptlets that call useradd / groupadd as the execution mechanism — the format declaration migrates first, the execution path migrates later.
  • OpenSUSE uses user(<name>) / group(<name>) virtual Provides: to express identity dependencies in package metadata, with similar separation between declaration and creation mechanism.
  • Arch ships sysusers.d files and runs systemd-sysusers from install hooks, illustrating the fully-migrated end-state.
  • Debian has historically created identities via adduser / addgroup in maintainer scripts (postinst). Debhelper now provides dh_installsysusers, which lets a Debian package ship a sysusers.d file as the recipe and have it processed at install time — but maintainer-script adduser/addgroup remain the canonical mechanism in most existing packages. The format-vs-mechanism separation is the same idea expressed in Debian's own packaging vocabulary.
  • Ubuntu inherits the Debian model directly. The same sysusers.d-as-recipe / scriptlet-as-mechanism split applies on Ubuntu releases that ship NFTBan (22.04, 24.04). NFTBan's CI Runtime Truth matrix exercises Ubuntu 24.04 explicitly to confirm the recipe + scriptlet combination produces the documented on-disk state.

NFTBan is at the same starting point as modern Linux distros adopting this model: declarative recipe shipped, scriptlet execution preserved. Migration to systemd-sysusers execution is a future step, not a current one.

Cautions

  • Do not edit /usr/lib/sysusers.d/nftban.conf or install/systemd/sysusers.d/nftban.conf manually. Both are generated from build/fhs-spec.yaml; manual edits are overwritten on the next regeneration.

  • Do not confuse the sysusers recipe with the application config. /etc/nftban/nftban.conf is for operators; the systemd recipes are for the package builder.

  • Do not switch production from groupadd/useradd to systemd-sysusers without a separate gated redesign. A migration to systemd-sysusers execution requires:

    • Resolving the SYSUSERS-GECOS-G-LINES format-strictness gap (a known dormant gap in the current g-line declarations that systemd-sysusers rejects but groupadd accepts);
    • Confirming the broader Self-Healing Authority redesign scope before changing the production identity-creation mechanism.

    Until both are resolved, the recipe-only adoption is the contract. The CI Runtime Truth Gate verifies that the tmpfiles.d directory authority — which depends on the identities being present — produces the expected on-disk state regardless of whether the mechanism that materialised them was scriptlet or systemd-sysusers.


Directory Layout

Binaries and Libraries

Path Mode Owner Purpose
/usr/sbin/nftban 0750 root:nftban Main CLI entry point (RPM %attr(0750,root,nftban); DEB equivalent — group-readable so the nftban group can run it without sudo)
/usr/lib/nftban/ 0755 root:root Application libraries and modules
/usr/lib/nftban/bin/ 0755 root:root Go binaries (nftban-core, nftband, nftban validate, nftban-installer, bundled yq)
/usr/lib/nftban/core/ 0755 root:root Core modules
/usr/lib/nftban/cli/ 0755 root:root CLI command modules
/usr/lib/nftban/lib/ 0755 root:root Library modules
/usr/lib/nftban/exporters/ 0755 root:root Metrics exporters
/usr/lib/nftban/helpers/ 0755 root:root Helper scripts (trace, autoheal)
/usr/lib/nftban/modules/ 0755 root:root Protection modules (portscan, ddos, login)
/usr/lib/nftban/sbin/ 0755 root:root System helper binaries
/usr/lib/nftban/health/ 0755 root:root Health check modules
/usr/lib/nftban/setup/ 0755 root:root Setup and installation scripts
/usr/lib/nftban/cron/ 0755 root:root Cron/timer job scripts
/usr/lib/nftban/tests/ 0755 root:root Test scripts (selftest suite, validation)
/usr/lib/nftban/data/ 0755 root:root Static data files (registries, schemas)
/usr/lib/nftban/tools/ 0755 root:root Utility tools and scripts
/usr/lib/nftban/scripts/ 0755 root:root Generator + post-install helper scripts
/usr/lib/nftban/templates/ 0755 root:root Library-side templates (e.g. nftables.conf.tpl)

Configuration

All configuration is under /etc/nftban/. Owned by root:nftban with mode 0750 so the daemon can read via group membership but cannot modify.

Path Mode Owner Purpose
/etc/nftban/ 0750 root:nftban Configuration root
/etc/nftban/nftban.conf 0640 root:nftban Primary config (immutable, chattr +i)
/etc/nftban/conf.d/ 0750 root:nftban Module configurations
/etc/nftban/conf.d/ddos/ 0750 root:nftban DDoS protection configuration
/etc/nftban/conf.d/portscan/ 0750 root:nftban Port scan detection configuration
/etc/nftban/conf.d/login/ 0750 root:nftban Login monitoring configuration
/etc/nftban/conf.d/panels/ 0750 root:nftban Control panel configurations
/etc/nftban/conf.d/botscan/ 0750 root:nftban Bot scanner configuration
/etc/nftban/whitelist.d/ 0750 root:nftban Whitelist entries
/etc/nftban/blacklist.d/ 0750 root:nftban Blacklist entries
/etc/nftban/ports.d/ 0750 root:nftban Port whitelist entries
/etc/nftban/rules.d/ 0750 root:nftban Custom nftables rules
/etc/nftban/patterns.d/ 0750 root:nftban Detection pattern files
/etc/nftban/patterns.d/botscan/ 0750 root:nftban Bot scanner patterns
/etc/nftban/connectors/ 0750 root:nftban Connector configs (Zabbix, Elasticsearch, Kafka)
/etc/nftban/distros/ 0750 root:nftban Distribution-specific configuration
/etc/nftban/access.d/ 0750 root:nftban Access-control entries
/etc/nftban/templates/ 0750 root:nftban Operator-facing templates (logrotate, etc.)
/etc/nftban/nftables.d/ 0750 root:nftban Operator nftables overrides
/etc/nftban/ssl/ 0750 root:nftban TLS material for outbound connectors
/etc/nftban/conf.d/rbl/ 0750 root:nftban RBL (DNSBL) configuration
/etc/nftban/conf.d/geoban/ 0750 root:nftban GeoBan configuration
/etc/nftban/conf.d/geoip/ 0750 root:nftban GeoIP module configuration
/etc/nftban/conf.d/botguard/ 0750 root:nftban BotGuard configuration
/etc/nftban/conf.d/botguard/profiles/ 0750 root:nftban BotGuard profile presets
/etc/nftban/conf.d/suricata/ 0750 root:nftban Suricata-integration configuration
/etc/nftban/conf.d/tunnel/ 0750 root:nftban DNS-tunnel detector configuration
/etc/nftban/suricata/ (+ profiles/, config/, rules/, cache/, state/, state/last-good/) 0750 root:nftban Suricata profile/rule/state tree

Distro configs in /etc/nftban/distros/: almalinux.conf, centos.conf, debian.conf, fedora.conf, rhel.conf, rocky.conf, ubuntu.conf.

Variable Data

Top-level /var/lib/nftban/ is owned by root:nftban as a security boundary to prevent privilege escalation. Most subdirectories where the daemon writes are nftban:nftban. A small number of directories deliberately keep root:nftban ownership (backup territory) or open one specific channel to a different group (the auditor write-channel).

The table below is sourced from install/systemd/tmpfiles.d/nftban.conf and install/packaging/rpm/nftban-files.inc — the two generated authority files. /var/lib/nftban/ and /var/lib/nftban/community/ are package-shipped (RPM %dir %attr + DEB nftban.dirs); the remaining subdirectories are tmpfiles-managed (created at boot or after a systemd-tmpfiles --create run).

Path Mode Owner Authority Purpose
/var/lib/nftban/ 0750 root:nftban package Application state (security boundary)
/var/lib/nftban/community/ 0750 nftban:nftban package Community (shared) data
/var/lib/nftban/banned/ 0750 nftban:nftban tmpfiles Banned IP state files
/var/lib/nftban/whitelist/ 0750 nftban:nftban tmpfiles Whitelist state files
/var/lib/nftban/feeds/ 0750 nftban:nftban tmpfiles Threat feed data
/var/lib/nftban/geoip/ 0750 nftban:nftban tmpfiles GeoIP databases (.mmdb files)
/var/lib/nftban/reports/ 0750 nftban:nftban tmpfiles Generated reports
/var/lib/nftban/reports/baseline/ 0750 nftban:nftban tmpfiles Baseline reports
/var/lib/nftban/reports/watchdog/ 0750 nftban:nftban tmpfiles Watchdog system reports
/var/lib/nftban/reports/auditors/ 0770 root:nftban-auditor tmpfiles Auditor write-channel (compliance access)
/var/lib/nftban/reports/archive/ 0750 nftban:nftban tmpfiles Archived reports
/var/lib/nftban/metrics/ 0750 nftban:nftban tmpfiles Metrics database
/var/lib/nftban/stats/ 0750 nftban:nftban tmpfiles Runtime statistics
/var/lib/nftban/stats/history/ 0750 nftban:nftban tmpfiles Stats history
/var/lib/nftban/stats/profiles/ 0750 nftban:nftban tmpfiles Stats profiles
/var/lib/nftban/snapshots/ 0750 nftban:nftban tmpfiles Hourly stats snapshots
/var/lib/nftban/exports/ 0750 nftban:nftban tmpfiles User data exports (JSON, CSV)
/var/lib/nftban/queue/ 0750 nftban:nftban tmpfiles Task queue root
/var/lib/nftban/queue/pending/ 0750 nftban:nftban tmpfiles Pending tasks
/var/lib/nftban/queue/work/ 0750 nftban:nftban tmpfiles In-progress tasks
/var/lib/nftban/queue/dlq/ 0750 nftban:nftban tmpfiles Dead letter queue
/var/lib/nftban/mailspool/ 0750 nftban:nftban tmpfiles Failed mail retry queue
/var/lib/nftban/state/ 0750 nftban:nftban tmpfiles Runtime state
/var/lib/nftban/staging/ 0750 nftban:nftban tmpfiles Staging area
/var/lib/nftban/config/ 0750 nftban:nftban tmpfiles Runtime-derived config cache
/var/lib/nftban/login/ 0750 nftban:nftban tmpfiles Login monitoring state
/var/lib/nftban/portscan/ 0750 nftban:nftban tmpfiles Port scan detector state
/var/lib/nftban/panels/ 0750 nftban:nftban tmpfiles Panel adapter state
/var/lib/nftban/botguard/ 0750 nftban:nftban tmpfiles BotGuard state
/var/lib/nftban/tunnel/ 0750 nftban:nftban tmpfiles DNS-tunnel detector state
/var/lib/nftban/analytics/ 0750 nftban:nftban tmpfiles Analytics state
/var/lib/nftban/recorder/ 0750 nftban:nftban tmpfiles Event recorder state
/var/lib/nftban/suricata/ 0750 nftban:nftban tmpfiles Suricata integration state
/var/lib/nftban/watchdog/ 0750 nftban:nftban tmpfiles Watchdog state
/var/lib/nftban/backup/ 0750 root:nftban tmpfiles Backup territory (root-owned by intent)
/var/lib/nftban/update-backups/ 0750 root:nftban tmpfiles Update-rollback backups (root-owned by intent)
/var/lib/nftban/pro/ 0750 root:nftban tmpfiles Pro subscription data (root-owned by intent)

Logs

The directory layer is the only part of the log tree the package authority covers. Per-file ownership and mode for individual log files (bans.log, nftban-actions.log, portscan.log, etc.) are not declared in tmpfiles.d, nftban-files.inc, or nftban-dir-attrs.list; those files are created at runtime by the daemon and the project does not currently ship a per-file authority assertion for them. If you need an exact statement of per-file mode/owner, read it from the running system rather than from this page.

The directory rows below are sourced from install/systemd/tmpfiles.d/nftban.conf:

Path Mode Owner Purpose
/var/log/nftban/ 0750 nftban:nftban Log root
/var/log/nftban/watchdog/ 0750 nftban:nftban Watchdog logs
/var/log/nftban/reports/ 0750 nftban:nftban Report logs
/var/log/nftban/rbl/ 0750 nftban:nftban RBL check cache
/var/log/nftban/botguard/ 0750 nftban:nftban BotGuard logs
/var/log/nftban/metrics/ 0750 nftban:nftban Metrics logs
/var/log/nftban/soak/ 0750 nftban:nftban Soak-test logs

Log rotation is configured in /etc/logrotate.d/nftban, installed by the package from install/config/nftban.logrotate (mode 0644, %config(noreplace)). The Suricata-integration logs use a separate drop-in: /etc/logrotate.d/nftban-suricata. Both files use copytruncate so processes that hold open file handles do not need to be reloaded after rotation.

Cache and Runtime

Path Mode Owner Purpose
/var/cache/nftban/ 0755 nftban:nftban Cache files
/var/cache/nftban/health/ 0750 nftban:nftban Health check status cache
/run/nftban/ 0755 nftban:nftban Runtime data (PID files, sockets, locks)

/run/nftban/ is managed by tmpfiles.d only. Do not use RuntimeDirectory= in unit files to avoid ownership conflicts.

Shared Data

Read-only application data, installed by the package.

Path Mode Owner Purpose
/usr/share/nftban/ 0755 root:root Shared application data
/usr/share/nftban/templates/ 0755 root:root Templates root
/usr/share/nftban/templates/mail/ 0755 root:root Mail templates
/usr/share/nftban/templates/reports/ 0755 root:root Report templates
/usr/share/nftban/templates/zabbix/ 0755 root:root Zabbix import templates
/usr/share/nftban/dashboards/grafana/ 0755 root:root Grafana dashboard JSON files
/usr/share/nftban/specs/ 0755 root:root Specification files
/usr/share/bash-completion/completions/nftban 0644 root:root Bash tab completion

Note: the package does not ship a man page. CLI documentation is registry-driven (commands.registry.yml consumed by nftban help / scripts/generate-help.sh). The hand-maintained install/man/man8/nftban.8 was retired because it competed with the registry source-of-truth and caused symmetric DEB+RPM Phase-6 verify failures. If you see a /usr/share/man/man8/nftban.8 on a host, it is a leftover from an older install — newer packages do not place it.


Systemd Integration

tmpfiles.d

/usr/lib/tmpfiles.d/nftban.conf creates the runtime directory tree under /var/lib/nftban/, /var/log/nftban/, /var/cache/nftban/, and /run/nftban/. Generated from fhs-spec.yaml.

systemd-tmpfiles --create /usr/lib/tmpfiles.d/nftban.conf

The current generated file uses only d (create) directives — there are no z/Z (enforce-ownership) directives in the current authority. If a directory already exists at the time tmpfiles runs, systemd-tmpfiles will not silently re-chown it. Ownership convergence on an existing tree is the responsibility of the install scriptlet (postinst chown loop reading nftban-dir-attrs.list) and the nftban permissions enforce command.

nftband.socket does not create /run/nftban/ — its previous RuntimeDirectory= directive was removed; the socket unit now relies on tmpfiles.d having created the directory.

sysusers.d

/usr/lib/sysusers.d/nftban.conf is the declarative identity recipe, generated from fhs-spec.yaml. It records the intended groups and user.

In current packages, systemd-sysusers is not the identity-creation mechanism. The DEB postinst / RPM %pre scriptlets create identities directly with getent / groupadd / useradd. The sysusers.d file documents the contract; the scriptlet enforces it.

The form below is the upstream invocation that would materialise the recipe via systemd-sysusers, shown for reference only — it is not part of the install-time path:

# Reference only — not executed by NFTBan's package install path today:
systemd-sysusers /usr/lib/sysusers.d/nftban.conf

See Identity authority model for the full format-vs-mechanism explanation and the cautions that apply before any migration to systemd-sysusers execution.

Service Units

All installed to /usr/lib/systemd/system/ (or /lib/systemd/system/ on Debian). The canonical list (and per-unit description) lives in Systemd Units Overview; the table below is a curated subset of the most operator-relevant units. For the complete unit inventory, see install/systemd/ in the repo.

Unit Purpose
nftband.service Main daemon (single nftables writer; socket-activated by nftband.socket)
nftban-core-feeds.service Threat feed updater
nftban-core-geoip.service GeoIP database updater
nftban-health.service Periodic health check with auto-heal
nftban-health-fix.service On-demand privileged health fix (root, manual)
nftban-maintenance.service Maintenance tasks
nftban-watchdog.service Runtime monitoring
nftban-queue.service Queue processor
nftban-unified-exporter.service Unified metrics exporter
nftban-snapshot.service Stats snapshot
nftban-rollback.service Rollback service
nftban-suricata.service Suricata integration wrapper
nftban-suricata-update.service Suricata rule updater
nftban-firewall-init.service Firewall initialization
nftban-rebuild-recovery.service Rebuild recovery (post-failure)
nftban-soak.service Post-install soak validation
nftban-report-daily.service Daily report generator
nftban-community-stats.service Community-stats opt-in submitter
nftban-rbl-check.service RBL check
nftban-botscan.service Bot scanner
nftban-tunnel.service DNS-tunnel detector
nftban-update-check.service Update-availability check
nftban-update-apply.service Update apply
nftban-pro-inventory.service Pro-tier inventory (where applicable)
nftban-pro-license.service Pro-tier license validator
nftban-suricata-stats.service Suricata stats
nftban-alert@.service Alert dispatch (templated)

Timer Units

Timer Purpose
nftban-health.timer Periodic health check
nftban-maintenance.timer Periodic maintenance
nftban-watchdog.timer Periodic runtime monitoring
nftban-queue.timer Queue processing
nftban-unified-exporter.timer Metrics export
nftban-snapshot.timer Stats snapshot
nftban-rollback.timer Rollback cleanup
nftban-core-feeds.timer Threat feed update
nftban-core-geoip.timer GeoIP update
nftban-suricata-update.timer Suricata rule update
nftban-rebuild-recovery.timer Rebuild recovery
nftban-soak.timer Soak validation
nftban-report-daily.timer Daily report
nftban-community-stats.timer Community stats
nftban-rbl-check.timer RBL check
nftban-botscan.timer Bot scanner
nftban-tunnel.timer Tunnel detector
nftban-update-check.timer Update check
nftban-update-apply.timer Update apply
nftban-pro-inventory.timer Pro inventory
nftban-pro-license.timer Pro license

(Specific schedules, calendars, and deltas live in Systemd Units Overview and the unit files themselves; this page does not duplicate them to avoid drift.)


Permission Model

Ownership Rationale

Path Owner Reason
/etc/nftban/ root:nftban (0750) Config readable by daemon via group, not writable
/var/lib/nftban/ root:nftban (0750) Security boundary: root-owned top-level prevents privilege escalation
/var/lib/nftban/*/ nftban:nftban (0750) Subdirectories are daemon-writable
/var/lib/nftban/reports/auditors/ root:nftban-auditor (0770) Auditor group has access for compliance
/var/log/nftban/ nftban:nftban (0750) Daemon-written logs
/var/log/nftban/*.log runtime-created; no package-level per-file authority Directory layer (/var/log/nftban 0750 nftban:nftban) is authoritative. Individual log file owner/mode is not declared by any generated package authority. After first logrotate rotation, install/config/nftban.logrotate's create 0640 nftban nftban directive applies to listed files.
/usr/lib/nftban/ root:root (0755) Read-only libraries, executable by all

Security Hardening

Immutable files (chattr +i):

  • /etc/nftban/nftban.conf — prevent config tampering
  • /usr/lib/nftban/lib/nft_schema.sh — prevent nftables command injection

The immutable attribute is set by the package %post script and removed by %preun before upgrades.

Linux capabilities (setcap cap_net_admin+ep):

  • /usr/lib/nftban/bin/nftban-core
  • /usr/lib/nftban/bin/nftband

Both binaries receive CAP_NET_ADMIN so they can perform nftables operations without running as root. The capabilities are applied by the Go installer (internal/installer/fhs/permissions.go::SetCapabilities) when the system has setcap available; if setcap is missing the step is skipped with a debug log. The health check verifies the resulting state and reports drift.

Permission Enforcement

Permissions are enforced through three layers:

  1. tmpfiles.d (runtime) — Creates missing directories at boot or on explicit systemd-tmpfiles --create; it does not re-chown already-existing trees because the current generated file uses only d directives.
  2. Package scripts (installation) — RPM %post / DEB postinst set initial ownership and permissions.
  3. Health auto-heal (ongoing) — nftban-health.service periodically checks and fixes permissions. Runs as nftban user with CAP_NET_ADMIN; root-only operations (chown) are skipped gracefully.

For manual enforcement as root:

nftban health fix all

Polkit Authorization

Polkit rules control which systemd units the nftban group can manage without root. The install path differs by packager:

  • RPM (Fedora/RHEL/AlmaLinux/Rocky/CentOS Stream) ships rules at /etc/polkit-1/rules.d/.
  • DEB (Debian/Ubuntu) ships rules at /usr/share/polkit-1/rules.d/ (per the upstream Debian polkit packaging convention).

Both locations are picked up by polkitd at runtime; the difference is purely packaging convention.

Rule File Group Access Level
10-nftban-systemd.rules nftban Start/stop/restart/reload whitelisted units
20-nftban-auditor.rules nftban-auditor Read-only status queries
30-nftban-panel.rules (retired v1.137) Not shipped. Only 10-nftban-systemd.rules + 20-nftban-auditor.rules are installed

The operator rule (10-nftban-systemd.rules) uses explicit unit whitelisting only. No wildcards or prefix matching. See Polkit for the full allowlist.


Configuration Variables

/etc/nftban/nftban.conf defines canonical path variables. Scripts must source this file and reference variables rather than hardcoding paths.

NFTBAN_BIN="/usr/sbin/nftban"
NFTBAN_CORE_BIN="/usr/lib/nftban/bin/nftban-core"
NFTBAN_LIB_DIR="/usr/lib/nftban"
NFTBAN_CONFIG_DIR="/etc/nftban"
NFTBAN_DATA_DIR="/var/lib/nftban"
NFTBAN_LOG_DIR="/var/log/nftban"
NFTBAN_CACHE_DIR="/var/cache/nftban"
NFTBAN_RUN_DIR="/run/nftban"
NFTBAN_DISTRO_CONF_DIR="/etc/nftban/distros"

Validation Commands

# Check FHS compliance status
nftban fhs status

# Fix permissions (requires elevated privileges; members of the nftban group are authorized via PolicyKit/polkit)
nftban health fix permissions

# Fix all detected issues (requires elevated privileges; members of the nftban group are authorized via PolicyKit/polkit)
nftban health fix all

# Run health check with auto-heal (as nftban user or root)
nftban health check --auto-heal

Common Errors

Permission denied when running CLI commands

Cause: User is not in the nftban group.

sudo usermod -aG nftban $USER
# Log out and back in for group membership to take effect

/run/nftban/ owned by root:root after reboot

Cause: tmpfiles.d did not run, or it ran before the nftban system group existed (so the chown step silently fell through to root:root defaults).

# Re-run tmpfiles.d explicitly. Requires the nftban group to exist (it is
# created by the package postinst); on a freshly-imaged system you may
# need to run the postinst-equivalent identity creation first.
sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/nftban.conf

/run/nftban/ is created exclusively by tmpfiles.dnftband.socket does not declare a RuntimeDirectory= directive (this was removed to prevent a previously-observed ownership race). The current tmpfiles.d/nftban.conf uses only d (create) directives, so a directory that already exists with the wrong owner will not be silently re-chowned by tmpfiles; ownership convergence on an existing tree is the responsibility of the install scriptlet's chown loop or nftban permissions enforce.

run as root during health fix

Cause: Operations like chown require elevated privileges (members of the nftban group are authorized via PolicyKit/polkit rules).

nftban health fix all

Auto-heal (nftban-health.service) handles non-root operations automatically. Root-only operations are skipped with a warning.


References

See also: Logging, Rotation & Retention and Audit Reports & Compliance for path-specific operational detail.

Clone this wiki locally