Thank you for your interest in contributing to NFTBan! This document provides guidelines for contributing.
NFTBan enforces correctness through:
- STATUS.md — CI/CD audit surface (build, security, contract gates)
- docs/DESIGN_PRINCIPLES.md — engineering contract
- docs/RUNTIME_MODE_AUTHORITY_CONTRACT.md — runtime mode authority and evidence standard (ADR-0001, mode admission ledger)
All contributions must preserve:
- Kernel-first authority
- Validator-derived truth
- Evidence-based protection
- CI-enforced invariants
A feature is not merely code that exists. A feature is a complete production path that is reachable, observable, enforceable, testable and recoverable.
DEFINED ≠ REACHABLE
CONFIGURED ≠ EFFECTIVE
ENABLED ≠ DETECTING
RUNNING ≠ RECEIVING INPUT
DETECTED ≠ ENFORCED
SET MEMBERSHIP ≠ FIREWALL BLOCK
PASS ≠ INJECTION PROVEN
PRs touching modules, modes, Suricata, detection, banning, health or status must complete the mode-authority section of the pull request template. An unanswered field blocks merge.
Changes that violate these principles must not be merged.
NFTBan is an open-source Linux Intrusion Prevention System (IPS) and firewall manager built on nftables, designed to integrate cleanly with modern Linux security stacks. The name stands for NFTables BAN actions, emphasizing the system's foundation on native nftables technology for kernel-level packet filtering.
When writing documentation or code:
- NFTBAN (all caps) — Project name in formal contexts, marketing materials, and when emphasizing the acronym
- NFTBan (title case) — Stylized form for README headers and user-facing documentation
- nftban (lowercase) — Command name, binary name, file paths, and code references
- nftables — Always lowercase (the underlying Linux kernel technology)
Example usage:
- ✅ "NFTBAN is built on nftables technology"
- ✅ "Run the
nftbancommand to manage firewall rules" - ✅ "See the NFTBan documentation for details"
Please read our Code of Conduct before contributing.
- Check existing issues first
- Use the bug report template
- Include:
- NFTBan version (
nftban version) - OS and version (
cat /etc/os-release) - Steps to reproduce
- Expected vs actual behavior
- Relevant logs (
/var/log/nftban/)
- NFTBan version (
- Check existing issues and discussions
- Use the feature request template
- Explain the use case and benefit
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes
- Run smoke tests:
nftban smoke(non-destructive) ornftban selftest(lab/deep validation) - Commit with clear messages
- Push and create a PR
- Go 1.24+
- Bash 4.4+
- nftables
- Linux (Rocky/Alma/Ubuntu/Debian)
# Clone repository
git clone https://github.com/itcmsgr/nftban.git
cd nftban
# Build Go binaries
./build.sh
# Install for testing
sudo ./install.shnftban/
├── cli/ # Bash CLI
│ └── lib/nftban/
│ ├── core/ # Core functionality
│ ├── cli/ # Command handlers
│ ├── helpers/ # Utility functions
│ └── setup/ # Installation helpers
├── cmd/ # Go binaries
│ └── nftban-core/ # Main Go binary
├── internal/ # Go internal packages
├── pkg/ # Go public packages (ipc, version)
├── install/ # Installation scripts
├── packaging/ # RPM/DEB specs
└── docs/ # Documentation
All contributors, automation, and AI assistants must comply with this engineering contract. If a change violates this document, it must not be merged.
NFTBan supports platforms by tier. Only Tier 0 platforms define correctness.
Tier 0 — Focus (CI-required)
- Ubuntu 24.04 LTS
- Ubuntu 26.04 LTS
- Debian 12
- Rocky Linux 9.x
A change is correct only if it builds, installs, and passes receipt-based audit on all Tier 0 platforms.
Tier 1 — Future Planning (Limited CI)
- Rocky Linux 10.x
- Debian 13
Rules: Architecture must accommodate. No hardcoded assumptions. Failures do not block Tier 0 releases.
Tier 2 — Legacy (Best-Effort Only)
- Rocky/RHEL 8.x
- Ubuntu 22.04 LTS
- Debian 11
Rules: Must not break catastrophically. No new features or design decisions for these platforms.
This rule is mandatory.
| Package | Build Host | Result |
|---|---|---|
| RPM | Rocky Linux 9 | Ensures binaries run on Rocky 10+ |
| DEB | Debian 12 or Ubuntu 22.04 | Ensures binaries run on Ubuntu 26.04+ |
Violating this rule risks GLIBC incompatibility and is not allowed.
build/fhs-spec.yamlis the single source of truth- All directories, ownership, and modes are generated
- No hardcoded mkdir, chmod, or chown outside generated outputs
Forbidden patterns:
chmod -Rchown -R- Hardcoded
/etc/nftban,/var/lib/nftban,/run/nftbancreation - Runtime writes to
/etcby non-root services
Violations are rejected by CI and pre-commit hooks.
All distro-specific paths live in:
/etc/nftban/distros/*.conf
Rules:
- Installers, services, and validators must not guess paths
- Resolved values are written to the installation receipt
- Validation checks the receipt, not the OS
Required keys:
[paths]
nft =
systemctl =
polkit_rules_dir =
journalctl =- nftables only — iptables legacy is not supported
- Always use the
inetfamily - Example:
nft add rule inet filter input tcp dport 22 accept
- Use systemd sandboxing (ProtectSystem, NoNewPrivileges, etc.)
- Use sysusers.d and tmpfiles.d (generated)
- Services must not escalate privileges silently
- Cron is forbidden — use systemd timers only
- Every install produces a receipt
- Receipt defines: paths, permissions, distro resolution
- Audit compares system → receipt
- If receipt says it's wrong, it is wrong
Any AI or automated contributor must obey:
- README "Official Supported Platforms & Build Contract"
- This CONTRIBUTING.md
- No exceptions
All contributions must comply with these authoritative standards:
Every source file must have a compliant header with:
- SPDX-License-Identifier: MPL-2.0 (exactly one per file)
- All
meta:tags with quoted values:meta:key="value" - All inventory keys present (even if empty):
meta:inventory.files="" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges=""
This section is the authoritative header spec. CI enforces it via tools/validate-headers.sh.
Full standards available at: https://nftban.com/coding-standards.html
- Required:
set -Eeuo pipefailat the top of every script - Quote all variables:
"$var" - Use
[[for conditionals - Add comments for complex logic
- Follow existing naming conventions
- Avoid:
((counter++))patterns in conditionals underset -e(arithmetic integrity rule)
- Run
go fmtbefore committing - Run
go vetand fix warnings - Run
staticcheckand address issues - Use meaningful variable names
- Add tests for new functionality
Headers and coding standards are enforced via pre-commit hook:
# Install pre-commit framework (recommended)
pip install pre-commit
pre-commit install
# Or use the Makefile
make lint-headers
make lintThe hook validates:
- SPDX license identifier (exactly one, must be MPL-2.0)
- All meta: lines are quoted
- All inventory keys are present
- Bash scripts have
set -Eeuo pipefail - No free-text header lines (From:, Called by:, etc.)
- Use conventional commits:
feat:New featurefix:Bug fixdocs:Documentationrefactor:Code refactoringtest:Adding testschore:Maintenance
# Good commit messages
feat(cli): Add IP search across all sets
fix(geoban): Handle empty country list gracefully
docs: Update installation guide for Rocky 9
# Bad commit messages
fixed stuff
update
wip# Non-destructive smoke (safe for CI, routine checks)
nftban smoke
# Extended system validation (includes controlled state changes — ban/unban lifecycle, whitelist tests)
nftban selftest
# Full test suite
./tests/test_all_commands.sh
# ShellCheck (bash linting)
shellcheck cli/lib/nftban/**/*.sh
# Go tests
go test ./...- Smoke tests pass:
nftban smoke(non-destructive, CI-safe) - ShellCheck passes (warnings OK)
- Go builds without errors
- No regressions in existing functionality
- Open a discussion
- Check documentation
- Review support guide
By contributing, you agree that your contributions will be licensed under the MPL-2.0 License.