Log Levels
TCP Warden uses a single log_level setting to control the verbosity of both its logging subsystems simultaneously.
global: # Accepted values (case-insensitive): # debug | info | warn | error | off log_level: "warn" # defaultTwo Independent Log Streams
TCP Warden produces two distinct categories of log output, both gated by log_level:
| Stream | Format | Destination | Purpose |
|---|---|---|---|
| Operational logs | Human-readable text | stderr | Startup banners, plugin status, API listener confirmations, daemon warnings |
| Security events | Structured JSONL | stdout + log_file | Per-connection audit records consumed by CrowdSec, dashboards, and SIEMs |
Both streams respect log_level independently: operational messages below the threshold are dropped from stderr, and security events with actions below the threshold are never written to stdout or log_file.
Level Reference
| Level | Operational logs | Security events written | Typical use case |
|---|---|---|---|
debug | All messages including internal trace | All events (allowed, auth_failure, blocked) | Local development, troubleshooting |
info | Operational status, plugin status, API listeners | All events (allowed, auth_failure, blocked) | Detailed traffic auditing |
warn | Default. Warnings and errors only (plugin failures, sync errors) | auth_failure and blocked events only | Standard production deployments & CrowdSec |
error | Errors only | blocked and banned events only | High-traffic servers; minimal log volume |
off | Nothing | Nothing | Test harnesses; external log management |
Security Event Action Mapping
The action field in each JSONL SecurityEvent determines the minimum level required for that event to be written:
action value | Written when log_level is | Suppressed when |
|---|---|---|
allowed | debug or info | warn, error, or off |
auth_failure | debug, info, or warn | error or off |
blocked / banned | debug, info, warn, or error | off only |
Why this design?
allowed events are the highest volume by far — every successful legitimate connection generates one. Suppressing them at warn and above keeps log files compact and ensures CrowdSec and SIEMs only process meaningful security signals, not routine traffic.
Examples by Level
global: log_level: "debug" log_file: "/var/log/routewarden/tcp-warden.jsonl"Security Event Format
Each JSONL line is a single SecurityEvent object. Here are real examples for each action type:
{"type":"security_event","timestamp":"2026-09-30T09:42:11.320Z","plugin":"tcp-warden","service":"ssh_bastion","protocol":"ssh","client_ip":"10.0.0.5","country_code":"LAN","flag_emoji":"🏠","action":"allowed","reason":"session_complete","bytes_in":2048,"bytes_out":1024,"duration_ms":3201}Event Fields
| Field | Type | Description |
|---|---|---|
type | string | Always "security_event" |
timestamp | string | RFC 3339 UTC timestamp |
plugin | string | Always "tcp-warden" |
service | string | Service name from configuration |
protocol | string | Protocol handler (ssh, tcp, smtp, etc.) |
client_ip | string | Source IP address |
country_code | string | ISO 3166-1 alpha-2 code ("US", "LAN" for private ranges) |
country_name | string | Country name (omitted for private ranges) |
flag_emoji | string | Country flag emoji (🏠 for LAN) |
action | string | allowed, auth_failure, blocked, or banned |
reason | string | Specific reason string (e.g. "ip_denied", "crowdsec_ban: ...") |
bytes_in | int64 | Bytes received from client (omitted when 0) |
bytes_out | int64 | Bytes sent to client (omitted when 0) |
duration_ms | int64 | Connection duration in milliseconds |
Environment Variable Override
log_level can also be set via the ROUTEWARDEN_LOG_LEVEL environment variable, which takes precedence over the YAML value. This is convenient for container deployments:
services: tcp-warden: image: ghcr.io/routewarden/tcp-warden:latest environment: - ROUTEWARDEN_LOG_LEVEL=warn # overrides log_level in tcp-warden.yamlStartup Banner
TCP Warden prints the active log level at startup so you can confirm the setting at a glance:
🛡️ Starting TCP Warden... Config: /etc/routewarden/tcp-warden.yaml Services (3): • ssh_bastion [ssh] :2222 -> 127.0.0.1:22 (enabled) • db_proxy [postgres] :5432 -> 10.0.0.15:5432 (enabled) • cache [redis] :6380 -> 127.0.0.1:6379 (enabled) Log file: /var/log/routewarden/tcp-warden.jsonl Log level: warnCrowdSec & Log Levels
When running TCP Warden alongside CrowdSec, set log_level: "warn". This keeps the JSONL audit file focused on auth_failure and blocked events — the exact signals CrowdSec scenarios are built to detect — without flooding the file with allowed records from legitimate traffic. See the CrowdSec Integration Guide for full setup details.