Witen

Host protection

Warden operator guide

Warden tails host logs, classifies security events, maintains durable local state, and enforces individual-address bans at the firewall. Collector connectivity adds shared intelligence and fleet visibility, but local parsing and enforcement continue during an outage.

Choose the right build

Native packages

Use DEB on Debian or Ubuntu; RPM on AlmaLinux, Rocky Linux, RHEL, or Fedora; and APK on Alpine. Native packages install the service account, configuration, init definition, manual, state directories, and lifecycle hooks.

Portable builds

Use the glibc archive on Gentoo and other glibc systems, or the musl archive on non-Alpine musl systems. Both systemd and OpenRC are supported. The 386 glibc archive is for legacy 32-bit x86 only.

Use the Downloads page or the public package URLs below. Warden downloads do not require an account. Verify the published SHA-256 checksum before installation and never substitute a glibc binary into an Alpine package.

Public downloads for package managers

These HTTPS endpoints work without cookies, tokens, or a signed-in browser. The latest version is 0.1.19. Enrollment remains a separate step after installation.

curl -fsS https://www.witenlabs.com/api/releases/warden/version
curl -fsS https://www.witenlabs.com/api/releases/warden
curl -fLO https://www.witenlabs.com/api/releases/warden/artifacts/witen-warden-0.1.19-linux-amd64-glibc.tar.gz

Versioned artifact URLs retain their original bytes when a newer release is published. Versions 0.1.11 and 0.1.12 are available in all six package formats. Compare the downloaded file with its manifest checksum before installing it.

Gentoo overlay

For an amd64 glibc ebuild, use this versioned source URL. A musl build uses the linux-amd64-musl.tar.gz suffix. Point a plain-text update checker at the version endpoint above.

SRC_URI="https://www.witenlabs.com/api/releases/warden/artifacts/witen-warden-${PV}-linux-amd64-glibc.tar.gz"

Automatic fetching needs no Witen credential or manual DISTDIR preparation. This changes download access; the license bundled with Warden still applies. See Gentoo’s SRC_URI documentation for architecture and libc conditionals.

Install Warden

Debian package

sha256sum ./witen-warden_*.deb
sudo apt install ./witen-warden_*.deb
warden --version
man 8 warden

RPM package

sha256sum ./witen-warden-*.x86_64.rpm
sudo dnf install ./witen-warden-*.x86_64.rpm
warden --version
man 8 warden

Alpine package

sha256sum ./witen-warden_*.apk
sudo apk add --allow-untrusted ./witen-warden_*.apk
warden --version

The downloaded APK is currently a directly distributed package rather than a configured Alpine repository package, so install it from the verified local file.

Portable archive

sha256sum ./witen-warden-*-linux-amd64-glibc.tar.gz
tar -xzf ./witen-warden-*-linux-amd64-glibc.tar.gz
cd ./witen-warden-*-linux-amd64-glibc
sudo ./install.sh
sudo warden validate --config /etc/witen/warden.toml

The portable installer does not enable or start a service. On OpenRC it installs the service files; otherwise install the included init definition appropriate to the host.

Let an agent install Warden

Give your coding or operations agent SSH access to one host, a Warden artifact, its published SHA-256 checksum, and a fresh enrollment token. Do not paste a fleet recovery credential into an agent session.

Install and enroll Witen Warden on [SSH HOST] as [SSH USER].

Inputs:
- Local Warden artifact: [LOCAL PATH]
- Expected SHA-256: [SHA256]
- Asset name: [UNIQUE HOST NAME]
- Single-use enrollment token: [PROVIDE PRIVATELY]
- Management address/CIDR that must never be blocked: [IP OR CIDR]

Requirements:
1. Inspect the remote OS, architecture, libc, init system, firewall manager, and available SSH/web/Cockpit log sources before changing anything.
2. Select only the matching supported DEB, RPM, APK, glibc portable, musl portable, or legacy 386 build. Verify the artifact with sha256sum before installing it. Stop on any mismatch.
3. Do not print, log, commit, or leave the enrollment token in shell history. Do not expose any resulting sensor credential.
4. Preserve /var/lib/witen. Back up an existing /etc/witen/warden.toml before editing it, and do not alter unrelated services or firewall policy.
5. Configure server_name, the single-use enrollment token, credential_file = "/var/lib/witen/sensor-credential", detected log sources, and never_block for my management address. Warden defaults to https://collector.witenlabs.com; set collector_url only if I explicitly provide a different collector.
6. Run sudo warden validate --config /etc/witen/warden.toml before starting or restarting. On firewalld hosts, also run sudo firewall-cmd --check-config. Treat firewall_manager_compatibility as unresolved until a separately approved maintenance-window reload test proves Warden's objects are reconciled. Stop and ask before any change that could interrupt SSH, DNS, the active firewall manager, or another production service.
7. Enable and start the appropriate systemd or OpenRC service. Confirm its version, service health, source health, firewall backend, enrollment, and reporting in Witen. Remove the consumed enrollment token from the configuration after the sensor credential exists, then validate again.
8. Report the exact package version, checksum, files changed, tests performed, and rollback steps without revealing secrets. If a check fails, preserve evidence and restore the prior configuration rather than improvising a destructive fix.
  • Use a short-lived enrollment token generated for this one asset.
  • Keep your current management IP or network in never_block before enforcement starts.
  • Require checksum, configuration validation, service, source, firewall, and website reporting checks.
  • Keep /var/lib/witen during upgrades and rollback because it contains durable state and the sensor credential.

Enroll the host

  1. In the customer website, open Add Protected Asset and choose Server or VPS.
  2. Give the asset a stable, unique name. Do not reuse a hostname for two concurrently enrolled installations.
  3. Generate the short-lived, single-use setup token.
  4. Place the supplied values in /etc/witen/warden.toml, keeping the file readable only by root and the Warden service group.
  5. Start Warden once. It exchanges the token for an installation-specific sensor credential stored in the configured credential file.
  6. Remove the consumed enrollment token from configuration and confirm the asset reports under Protected Assets.
[server]
server_name = "edge-1"

[warden]
enrollment_token = "wte-single-use-token"
credential_file = "/var/lib/witen/sensor-credential"

The production collector defaults to https://collector.witenlabs.com. Set collector_url only when using a different collector.

Configure collection and enforcement

Discover supported sources

sudo warden discover
sudo warden discover --toml

Discovery is read-only. It finds non-empty supported log files and journal services without adding them or changing the host.

Local SSH protection

[ssh]
enabled = true
timezone = "auto"

[journal]
enabled = "true"
cursor_path = "/var/lib/witen/journal-cursors.json"

[jail]
backend = "nft"
max_ssh_failures = 3
max_http_probes = 20
window_duration_sec = 300
ban_duration_sec = 3600
firewall_reconcile_interval_sec = 300

On OpenRC or file-based logging, set ssh.log_file to the authentication log and grant the service account the narrowest group or ACL needed to read it.

Web access logs

[[logs]]
path = "/var/log/caddy/access.log"
type = "caddy"

[[logs]]
path = "/var/log/nginx/access.log"
type = "nginx"

Supported access-log families include nginx, Apache, Caddy, lighttpd, Traefik, Envoy, HAProxy, Varnish, and Pound. Caddy should emit native JSON with trusted-proxy-aware client IP fields.

Register local plugins

Warden 0.1.19 authenticates each plugin with its own credential and the Unix user making the connection. Upgrade to WordPress 0.6.45 or Matomo 0.2.19 and provision credentials before restarting Warden. Hosted sensor credentials are separate.

Plugins persist reports before background delivery. A socket timeout or rejected credential leaves them queued for retry, without switching to the collector API. Warden takes responsibility once it acknowledges durable storage. Queues and diagnostic storage are bounded; check the plugin dashboard for delivery errors, rejected records, and dropped counts.

sudo install -d -m 0700 -o apache -g apache /var/lib/witen-wordpress
sudo warden --config /etc/witen/warden.toml callers add   --id EXISTING_SITE_ID --type wordpress --uid "$(id -u apache)"   --token-file /var/lib/witen-wordpress/caller.token
sudo warden --config /etc/witen/warden.toml callers list

Use the installation's existing reporting ID, not a display label. New packages create the witen-plugins socket group. When upgrading an existing configuration, set ingest_socket_group to witen-plugins and grant each PHP user membership in that group; keep PHP users out of the Warden service group. Restart PHP workers after changing groups. Credentials belong outside web roots, with mode 0600 and ownership matching the PHP user. Configure WITEN_WARDEN_CREDENTIAL_FILE in WordPress or Warden credential file in Matomo. Web and cron workers need the same configuration. These settings do not enable event sharing.

Use callers rotate with a new --token-file path to replace a credential, or callers revoke --id ID to disable access immediately. Rotation preserves attribution. Mutually untrusted sites need separate Unix users; a shared UID can access its own applications' credentials. Registered plugins can supply observations to the host's shared firewall policy. Collector retains the parent Warden as the account boundary and receives each installation ID with its events.

Validate and start

sudo warden validate --config /etc/witen/warden.toml
sudo systemctl enable --now witen-warden
sudo systemctl status witen-warden
sudo journalctl -u witen-warden -f
sudo warden sources
sudo warden stats --resources

Validation checks parsed configuration, paths, log readability, selected firewall tools, daemon sockets, XDP or JA4 prerequisites, and live sources without installing rules or changing state. On OpenRC, use rc-update add witen-warden default and rc-service witen-warden start.

  • The service is active and reports the expected embedded version.
  • Every required source is healthy and advancing.
  • The configured backend initialized; Warden fails startup instead of silently pretending to enforce.
  • The customer website shows a recent report for the enrolled asset.
  • warden blocked and warden stats can reach the running daemon through the admin socket.

Daily operations

TaskCommandMeaning
Overviewwarden tuiInteractive candidates, bans, events, sources, trends, and alerts.
Inspect pressurewarden candidatesAddresses approaching a threshold; they are not yet blocked.
Inspect evidencewarden candidate IPPolicy, score, threshold, and contributing evidence for one address.
List enforcementwarden blocked --source allLocal bans plus downloaded collector-managed entries.
Audit changeswarden actionsDurable lifecycle, enforcement, and coalescence actions.
Tune safelywarden recommend --window 7dBounded recommendations; configuration is never changed automatically.
sudo warden ban 192.0.2.10 3600
sudo warden unban 192.0.2.10
sudo warden reload --config /etc/witen/warden.toml
sudo warden events --limit 100 --json

Understand firewall behavior

  • nft is the recommended Linux backend; iptables, experimental PF, XDP, and observation-only null are also available.
  • Warden owns isolated tables, sets, or chains and does not flush the host INPUT policy.
  • With UFW using iptables-nft, Warden’s native nftables objects may not appear in iptables -L. Inspect them with nft list table inet filter.
  • Temporary bans are durable across restart, expire locally, and can renew when blocked traffic continues.
  • never_block exact addresses and CIDRs override automatic, manual, blocklist, and immediate policy bans.
sudo nft list table inet filter
sudo nft list set inet filter witen
sudo warden blocked --source local
sudo warden stats

Upgrade safely

  1. Download the build matching the host architecture and libc, then verify its checksum.
  2. Record warden --version, warden stats, and the current service state.
  3. Install the package or run the new portable installer. Existing configuration and durable state are preserved.
  4. Run warden validate before restarting.
  5. Restart the service, confirm the new version, source positions, active bans, and collector reporting.
warden --version
sudo warden validate --config /etc/witen/warden.toml
sudo systemctl restart witen-warden
warden --version
sudo warden sources
sudo warden blocked --source all

Troubleshooting

Service will not start

  • Run warden validate --json and inspect the first failing check.
  • Check that configured logs exist and the service account can read them.
  • Confirm the selected firewall binary and kernel support are present.
  • Do not start a foreground daemon while the service owns the runtime lock or admin socket.

Inspect decision receipts

  • Run warden decisions to list durable local enforcement outcomes.
  • Run warden explain RECEIPT_ID for the subject, reason, evidence count, actuator, timing, and lifecycle state.
  • Add --json when attaching structured output to automation or a support request.
  • Use warden unban IP for a manual rollback; successful rollback is recorded as rolled_back.

Optional outbound protection

Outbound enforcement is off unless outbound_protection_enabled is set. Enabling it requires a firewall backend that supports direction-specific rules. Confirm both outbound_configured=true and outbound_enforced=true in Warden status before treating the feed as active protection.

Events are missing

  • Use warden sources to verify the selected backend, offset, last event, and collection error.
  • Check log format and client-IP fields, especially behind trusted proxies.
  • Use warden backfill --since 1h to import history without enforcement. Add --enforce only after reviewing the implications.

Collector is unreachable

Local detection and enforcement continue. Events remain in the bounded durable outbox and drain in order after connectivity returns. Check upload counters in warden stats, DNS/TLS reachability, and the sensor credential file; do not replace the credential merely because the collector is temporarily unavailable.

More detail

The installed package includes the exhaustive offline manual at man 8 warden and info warden, including XDP, JA4, backfill, policy-rule, socket, and TUI details.