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: --duration is accepted but the daemon currently uses the jail’s configured bantime. 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 sshd

If --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 list
IP                 JAIL    BANNED AT             TIME LEFT
------------------------------------------------------------
45.227.253.98      sshd    2026-04-21 12:03:10   57m 43s

Filter to a specific jail:

sudo fail2zig-client list --jail sshd --output plain

jails

List configured jails and their current state.

sudo fail2zig-client jails
JAIL                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 jails

The 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 reload command 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 reload

version

Print the daemon version (requires a live daemon connection, unlike --version).

sudo fail2zig-client version

completions <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.fish

help [<command>]

Print general help or help for a specific command.

Exit codes

CodeMeaning
0Success.
1Daemon returned an error response (e.g., unknown jail name, IP not found).
2Bad arguments or invalid input (unknown command, missing required argument, unrecognized IP address).
3Connection 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:

EndpointDescription
GET /metricsPrometheus text exposition with per-jail {jail="..."} labels.
GET /api/statusJSON — same payload as status --output json.
GET /eventsWebSocket 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"} 0

See also

Edit on GitHub →