Hardening patterns for running an AI agent stack (Hermes Agent + Honcho) on company servers without exposing production.
Code companion to Hermes Agent Deployment: Secure AI Agent Infrastructure for Private Automation — the blog post walks through the why behind every choice in these files. The files are what it looks like once applied.
| File | What it shows |
|---|---|
sandbox/compose.yml |
Hardened single-purpose execution container — rootless Docker, cap_drop:[ALL] with narrow add-backs, no-new-privileges, pids_limit, mem_limit, cpus, tmpfs for /tmp and /run, bind-mounted /workspace. Plus a headless Chrome over CDP bound to a private interface only (CDP has zero authentication — network layer is the only gate). |
sandbox/sandbox-entry.sh |
SSH ForceCommand target that pipes the gateway → sandbox session into docker exec, with explicit env var allowlisting. No full env forwarding; only vars listed in PASSTHROUGH_VARS and AcceptEnv (sshd) get through. |
gateway/honcho-stack/compose.yml |
Hardened Honcho self-hosted stack (API + Postgres/pgvector + Redis + deriver worker). Internal-only networks, bind-mounted data dirs with explicit UID ownership, strict per-service resource and capability limits. |
Tip
Webnestify designs, deploys, hardens, and monitors private AI agent infrastructure on your own servers — gateway/sandbox split, rootless Docker, Docker Hardened Images, scoped tokens, tested backups, off-site encrypted snapshots.
Read them alongside the blog post. Each file is heavily commented, and every hardening choice is there for a reason that maps back to a specific threat the post discusses:
cap_drop:[ALL]+ narrowcap_add→ blast-radius reduction if the container is compromisedno-new-privileges:true→ blocks SUID escalation pathspids_limit,mem_limit,cpus→ resource exhaustion containmenttmpfsfor/tmpand/run→ no on-disk persistence of agent scratch state; survives a--force-recreate- Internal-only network for the database → DB never reachable from outside the compose stack, even if a host port leaks
- Bind mounts with explicit chown/chmod → no Docker-managed named volumes (auditable on the host filesystem)
- CDP bound to a private interface only → Chrome DevTools Protocol is unauthenticated by design; network restriction is the only control
- SSH
ForceCommand+ env allowlist → the gateway can run agent commands in the sandbox but cannot exfiltrate arbitrary env to the host
- Real values. Compose files reference
POSTGRES_PASSWORD, LLM API keys, JWT secrets, etc. via env. Supply them from a secrets manager (Bitwarden, 1Password, Doppler, Vault) — never commit them. - The agent itself. Install Hermes and Honcho from upstream:
- The rest of the architecture. Tailscale ACLs, sshd hardening, sysctl tuning, restic backup machinery, n8n heartbeat/failure webhooks. The blog post covers them at the design level; the implementation specifics are deployment-dependent.
The Honcho stack ships with public images by default (pgvector/pgvector:0.8.2-pg18, redis:8.6.1-alpine). If you have a paid Docker subscription with Docker Hardened Images access, swap them for the DHI equivalents — same hardening pattern around them, just with provenance-signed, SLSA-attested, minimally-built base images:
# database service
image: dhi.io/pgvector:0.8.2-pg18
# redis service
image: dhi.io/redis:8.6.1Run docker login dhi.io first (with a Docker Personal Access Token scoped to public-repo-read). DHI buys you a smaller attack surface in the base layer; everything else in this compose stays the same.
Two placeholders to replace before bringing the sandbox stack up:
sandbox/compose.yml— the CDP port binding (127.0.0.1:9222:9222) and DNS resolver IP (10.0.0.53) are placeholders. Replace with your tailnet/WireGuard interface IP and your internal DNS resolver respectively.sandbox/sandbox-entry.sh— assumes rootless Docker is installed at~/bin/docker(the default fordockerd-rootless-setuptool.sh install). Adjust if your install path differs.
No license file shipped. Treat these patterns as reference material for the blog post — copy, adapt, and harden for your environment. If you publish derivative work, a link back to the blog post or this repo is appreciated but not required.
