Server (harnessd)
Hardening checklist
A checklist for running harnessd in production, from the VM and network to accounts, secrets and sandboxes.
Use this list when you first deploy harnessd and when you review it. harnessd check enforces the items marked enforced; the rest are up to you.
The host#
- A dedicated VM for SI Fabrik. Nothing else runs there.
- Rootless Docker for the
harnessuser (DOCKER_HOST=unix:///run/user/<uid>/docker.sock). Membership in thedockergroup is root-equivalent. - The hardened systemd unit from
deploy/harnessd.service:ProtectSystem=strict,NoNewPrivileges, an empty capability set, a system-call filter,UMask=0077, and/etc/harnessread-only. Keep itsSystemCallFilter=setpriorityandSystemCallErrorNumber=EPERMlines; without them the server is killed withSIGSYS. ExecStartPre=harnessd check, so a failing configuration never serves.- OS and Docker updates applied; agent images rebuilt regularly.
- A current
harnessd. Before per-task sandbox networks, every sandbox shared one network on which the server's bridge address was reachable, includingsshd.
The network#
listenon loopback (127.0.0.1:8443), reached through an SSH tunnel. See Connect the app to a server. Enforced: no0.0.0.0withoutallow_all_interfaces.tools_listenon the Docker bridge on Linux (for example172.17.0.1:7879), never every interface (enforced). On Linux, harnessd warns if it's loopback, because containers can't reach it there. On a Mac with Docker Desktop,127.0.0.1is right. Sandboxes themselves can't reach the server's addresses: their task networks have no address for the host, and only the egress proxy forwards to the tools listener.- A cloud firewall or security group that opens only SSH (22), restricted to the admins' addresses (
/32) or your VPN. - The API port isn't reachable from the internet. If
8443is open anyway, its source is restricted to specific IPs.
TLS#
- TLS 1.3. Enforced, unless loopback behind a proxy. A self-signed certificate is fine through the SSH tunnel.
tls.keyat mode0600. Enforced.- The fingerprint (
harnessd fingerprint) handed to users over a trusted channel, and again after every certificate renewal.
Accounts#
- At least one admin. Enforced.
auth.require_totp_for_admins: true, and TOTP for every admin. Enforced when on.- TOTP for operators too.
- Least privilege:
viewerfor people who only watch,operatorfor people who run tasks, few admins. session.absolute_hoursof 12 or less;harnessd checkwarns above 24.- Departing users disabled or removed (
harnessd user disable <name>).
Secrets#
secrets.envand everyprojects[].secrets_fileat mode0600, owned byharness. Enforced.- A fine-grained
HARNESS_GITHUB_TOKENlimited to the project repositories, with Contents and Pull requests read/write only. - A LiteLLM virtual key with a budget as
HARNESS_GATEWAY_API_KEY, or per-project keys. - Deploy keys per repository rather than a personal SSH key.
- No secret values in any
WORKFLOW.md.
Projects and sandboxes#
- Every project sandboxed (Docker or Cloudflare), with no host hooks,
docker.extra_args,docker.networkor writable root. Enforced by the sandbox floor: such a project pauses withsandbox_policy. sandbox.network.mode: allowlist(the default) everywhere; shortallowlists.linked_tasks_stateleft atBacklog, so people approve tasks filed by other projects' agents.- Host-wide
limits:set:max_concurrent_agentsanddaily_budget_usd. - Per-project
limits:with a cost cap per task.
Monitoring#
harnessd audit verifyrun regularly, and the audit log shipped off the host.- The journal watched for
level=errorlines, such ascredentials_rejectedand failed preflights. - Failed-login spikes (
bad_credentials,locked_out) alerted on.