Hermes on SolOS: per-customer Docker deployment guide
Hermes on SolOS: per-customer Docker deployment guide
Summary
- Recommended trust boundary: one dedicated Hermes Docker container and one unique persistent data volume per customer. Add that customer's Hermes profiles/agents inside the container; do not put mutually untrusted customers' profiles in one shared multiplexer.[1][3]4
- The official image includes setup, gateway mode, persistent
/opt/data, and s6 supervision. The Docker page documents multi-profile support and also describes cases where a separate container per profile is useful; verify process layout on the exact pinned image before production.1 - This note is a researched deployment plan, not a live SolOS host audit or deployment. No container, port, firewall, or service was changed.
Deployment model
SolOS control plane / reverse proxy
βββ tenant-a container + tenant-a volume + tenant-a secrets/network
β βββ Hermes profile: default
β βββ Hermes profiles: agent-1, agent-2, ...
βββ tenant-b container + tenant-b volume + tenant-b secrets/network
βββ Hermes profiles: default, agent-1, ...
- Use a separate container, data volume, secret scope, network identity, resource quota and ingress identity for every customer.[1]4
- Profiles separate Hermes state (config,
.env, sessions, memory, skills), but are not filesystem sandboxes; profiles inside one customer container share that customer's outer trust boundary.3 - If two agents belonging to the same customer must not access each other's files or tools, isolate them in separate containers too.[1]4
- The official Docker image supervises profile gateway services with s6 and persists the previously running state across container restarts. The current gateway docs also describe multiplexing; check
hermes gateway status/liston the selected image and don't assume profile != process or profile == tenant.[1]4
Step-by-step single-customer pilot
Run these on a dedicated SolOS deployment account over SSH, not a browser console. Replace sample tenant/container names; never commit .env or real credentials.
1. Pick and pin the image
The Docker docs define latest/stable as release-gated images, main as development, and versioned tags as stable; pin a tested image digest for production rollouts.1
docker pull nousresearch/hermes-agent:stable
2. Bootstrap one tenant's state
Docker volumes persist outside a container's writable layer and survive container removal. Create a unique volume per tenant.7
docker volume create hermes-tenant-a
docker run --rm -it \
--mount type=volume,src=hermes-tenant-a,dst=/opt/data \
nousresearch/hermes-agent:stable setup
The Hermes setup wizard writes the configuration and provider credentials into the mounted data home; the Docker guide documents /opt/data as the persistent state directory.1 Store bot tokens and provider keys only in that tenant's secret scope/volume, not in a shared Compose file or source repository.[1]5
3. Start the persistent gateway
A basic Compose service for Telegram/other polling channels needs no public port mapping. The volume is customer-specific; resource limits below follow the official image example and must be load-tested.1
services:
hermes:
image: nousresearch/hermes-agent:stable # pin tested digest for production
container_name: hermes-tenant-a
restart: unless-stopped
command: ["gateway", "run"]
volumes:
- hermes-tenant-a:/opt/data
deploy:
resources:
limits:
cpus: "2.0"
memory: 4G
# No published ports for chat-only operation.
volumes:
hermes-tenant-a:
external: true
docker compose up -d
docker compose logs -f hermes
4. Add agents for that customer
Create profiles inside the customer's container so the container supervisor can register their gateway slots.1
docker compose exec hermes hermes profile create agent-1
docker compose exec hermes hermes -p agent-1 setup
docker compose exec hermes hermes -p agent-1 gateway start
docker compose exec hermes hermes -p agent-1 gateway status
- Give each messaging profile its own platform bot credentials; duplicate bot tokens must not be polled by more than one profile.[3]4
- Keep each platform's allowed-user/channel list restrictive; profile routing selects a profile but is not a substitute for authorization.[4]5
5. Expose UI/API only if needed
For chat platforms alone, leave ports unpublished.1 Gateway API traffic is privileged: requests can invoke Hermes tools; API-server auth uses a bearer key, and the server should remain private unless a secured frontend needs it.8
If enabling dashboard or API access, put it behind a tenant-aware TLS reverse proxy and authentication; do not expose raw container ports publicly. The dashboard is a machine-level management surface for every profile inside its container, and a public bind requires an auth provider.[1]9
6. Operate, update, and restore
- Hermes' Docker guide gives a typical 1 GB RAM / 1 CPU / 500 MB data-volume minimum and recommends 2β4 GB RAM / 2 CPUs / 2+ GB; browser automation needs at least 2 GB RAM. These are guidance, not a multi-agent guaranteeβbenchmark each tenant.1
- Use one persistent volume per tenant and back it up off-host with deployment metadata. Test restores; don't treat a running SQLite/WAL directory as a casual file-copy target.[1]7
- On a Linux VPS, a local named volume on the host filesystem avoids Docker Desktop's virtiofs/9p cross-VM bind-mount limitation. Hermes detects those paths and selects rollback journaling for fresh databases; NFS/SMB/generic FUSE are not all detected, so validate or explicitly use
database.journal_mode: deletethere.1 - Update by pulling the approved image and recreating the container (
docker compose pull && docker compose up -d); the mounted data persists. Docker installs are updated by the image/package owner, not by mutating the source installation inside the container. Use staged/canary upgrade, backup, health check and rollback policy at the SolOS control plane.[1]2 - Rootless Docker can reduce daemon/runtime privilege: both daemon and containers run inside a user namespace. It needs
newuidmap,newgidmapand at least 65,536 subordinate UIDs/GIDs; test networking, storage, and boot supervision before adopting it.6
Security boundaries and cautions
- Container vs terminal sandbox: βHermes running inside Dockerβ and βHermes running on host with Docker as its terminal backendβ are distinct modes. The Hermes security page's Docker terminal restrictions do not automatically describe the outer service-container boundary.[1]5
- Keep customers away from the Docker socket/daemon API and from host bind mounts; a Docker administrator remains able to inspect/manage every tenant container and volume.[6]7
- Separate public ingress by tenant, authenticate before routing, rate-limit, and make tenant-unmatched traffic fail closed in the SolOS layer. Hermes profile routes can fall through to the default profile when nothing matches.4
- For high-sensitivity customers or workloads that cannot trust a shared kernel/host administrator, use a dedicated VM/host per customer instead of relying on containers alone.6
- Hostinger advertises managed container isolation, UI/CLI, Telegram pairing, updates and backups, but the public page does not specify its implementation; use it as a feature benchmark, not as a SolOS security design spec.10
What SolOS must build around Hermes
Tenant lifecycle/provisioning; container/volume/network ownership; secret delivery and rotation; authenticated ingress/domains; resource and usage accounting; backup retention and verified restore; image canary/rollback; health/alerting; deletion/offboarding; abuse handling and support. Hermes provides the agent runtime, profiles, gateway and image supervision, not this full tenant control plane.[1][3]4
Readiness checks before production
- Audit the chosen SolOS host's Docker/Compose versions, CPU/RAM/disk, firewall and persistent storage; this study did not inspect or modify a server.
- Pilot with two synthetic tenants and distinct volumes/secrets/bots; test that neither can read the other's files, state, credentials or dashboard/API routes.
- Exercise restart, image upgrade, backup/restore, resource exhaustion, network-egress policy, and ingress/auth failure. Confirm the actual profile gateway process/s6 behavior on the pinned image.
- Add customers only after those isolation and recovery tests pass.
Sources
1 https://hermes-agent.nousresearch.com/docs/user-guide/docker2 https://hermes-agent.nousresearch.com/docs/getting-started/installation3 https://hermes-agent.nousresearch.com/docs/user-guide/profiles4 https://hermes-agent.nousresearch.com/docs/user-guide/multi-profile-gateways5 https://hermes-agent.nousresearch.com/docs/user-guide/security6 https://docs.docker.com/engine/security/rootless7 https://docs.docker.com/engine/storage/volumes8 https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server9 https://hermes-agent.nousresearch.com/docs/user-guide/features/web-dashboard10 https://www.hostinger.com/au/managed-hermes-agent

