Young's Mind
Architecture

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/list on 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: delete there.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, newgidmap and 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

  1. 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.
  2. 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.
  3. 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.
  4. 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

Copyright Β© 2026