fail2zig-client queries and controls the running fail2zig daemon over its
Unix domain socket. It is a separate binary that does not require root — it
requires either uid=0 or membership in the fail2zig group.
Synopsis
fail2zig-client [GLOBAL FLAGS] <COMMAND> [COMMAND ARGS]Global flags
Global flags may appear before or after the command name.
--socket <path>
Unix socket path. Default: /run/fail2zig/fail2zig.sock.
Override when the daemon is configured with a non-default global.socket_path,
or when testing against a non-production instance.
--output <format>
Output format. One of: table (default), json, plain.
table renders box-drawing borders with ANSI color on a terminal. plain emits
tab-separated values with no borders or color, suitable for scripting. json
emits compact JSON.
--no-color
Disable ANSI color output unconditionally.
--timeout <ms>
Command timeout in milliseconds. Default: 5000. If the daemon does not respond
within this window, the client exits with code 3 and prints a diagnostic.
--version / -V
Print the client version and exit. Does not contact the daemon.
fail2zig-client --version
# fail2zig-client 0.2.2--help / -h
Print usage information and exit.
Commands
status
Show a summary of daemon health.
sudo fail2zig-client status+------------------------------------------+
| fail2zig 0.2.2 — running |
+------------------------------------------+
| Uptime: 3d 4h 12m 06s |
| Memory: 21.4 / 64.0 MB (33%) |
| Parse rate: 1284 lines/sec |
| Active bans: 7 |
| Total bans: 152 |
| Protection: active |
| Backend: nftables |
| Jails: 2 |
+------------------------------------------+Total bans is a persisted lifetime counter (it survives restarts and is always
>= Active bans), and Jails is the count of jails currently active.
Protection is one of active, log-only, mixed, or degraded — the last
when a jail’s log source has stopped reading. See
jails for the per-jail source and read-health.
As JSON:
sudo fail2zig-client status --output json{
"version": "0.2.2",
"uptime_seconds": 273126,
"memory_bytes_used": 22413312,
"parse_rate": 1284,
"active_bans": 7,
"total_bans": 152,
"jail_count": 2,
"jails_active": 2,
"protection": "active",
"backend": "nftables"
}ban <ip> [--jail <name>] [--duration <seconds>]
Manually ban an IP address.
sudo fail2zig-client ban 45.227.253.98 --jail sshd--jail names the jail the ban is attributed to. If omitted, the ban is
attributed to an internal “manual” category. --duration sets the ban duration
in seconds; if omitted, the jail’s configured bantime is used.
Note:
--durationis accepted but the daemon currently uses the jail’s configuredbantime. Per-command duration override will be honored in a future release.
unban <ip> [--jail <name>]
Remove a ban.
sudo fail2zig-client unban 45.227.253.98 --jail sshdIf --jail is specified, only the ban in that jail is removed. If omitted,
the ban is removed from all jails.
list [--jail <name>]
List active bans.
sudo fail2zig-client listIP JAIL BANNED AT TIME LEFT
------------------------------------------------------------
45.227.253.98 sshd 2026-04-21 12:03:10 57m 43sFilter to a specific jail:
sudo fail2zig-client list --jail sshd --output plainjails
List configured jails and their current state.
sudo fail2zig-client jailsJAIL STATE ACTIVE MAX RETRY FIND TIME BAN TIME ACTION ENFORCING SOURCE HEALTH
----------------------------------------------------------------------------------------------------------------------------------
sshd enabled 5 3 10m 10m nftables true journald (sshd) ok
nginx-http-auth enabled 2 3 10m 10m nftables true /var/log/nginx/error.log ok
Total: 2 jailsThe ACTION / ENFORCING columns show how each jail acts (an enforcing=false
row watches but never bans — e.g. a log-only jail). SOURCE is the log source
the jail actually reads after resolution (a journald unit or a file path, never
a path it doesn’t read), and HEALTH is ok, broken, or unknown — a
broken source is what drives the daemon’s degraded protection state.
reload
Signal the daemon to reload its configuration.
Note: The
reloadcommand is implemented at the IPC level but the daemon-side handler is currently a stub. The daemon logs the request and acknowledges it, but does not reload the config. A service restart is required to pick up configuration changes.
sudo fail2zig-client reloadversion
Print the daemon version (requires a live daemon connection, unlike --version).
sudo fail2zig-client versioncompletions <bash|zsh|fish>
Print a shell completion script to stdout.
# Bash (system-wide)
sudo fail2zig-client completions bash > /etc/bash_completion.d/fail2zig-client
# Zsh (per-user)
fail2zig-client completions zsh > ~/.zsh/completions/_fail2zig-client
# Fish
fail2zig-client completions fish > ~/.config/fish/completions/fail2zig-client.fishhelp [<command>]
Print general help or help for a specific command.
Exit codes
| Code | Meaning |
|---|---|
0 | Success. |
1 | Daemon returned an error response (e.g., unknown jail name, IP not found). |
2 | Bad arguments or invalid input (unknown command, missing required argument, unrecognized IP address). |
3 | Connection failed: daemon is not running, permission denied, or command timed out. |
Prometheus and HTTP alternatives
The daemon also exposes a read-only HTTP server on 127.0.0.1:9100 by default:
| Endpoint | Description |
|---|---|
GET /metrics | Prometheus text exposition with per-jail {jail="..."} labels. |
GET /api/status | JSON — same payload as status --output json. |
GET /events | WebSocket upgrade; broadcasts ip_banned, ip_unbanned, attack_detected, metrics events. |
curl -s http://127.0.0.1:9100/api/status
# {"version":"0.2.2","uptime_seconds":273126,...}
curl -s http://127.0.0.1:9100/metrics | grep fail2zig_active_bans
# fail2zig_active_bans 0
# fail2zig_active_bans{jail="sshd"} 0See also
- fail2zig daemon CLI reference
- Configuration reference
- Man page:
man fail2zig-client(after installation)