
nousresearch/hermes-agent:latest) so there’s no Dockerfile to maintain and no remote builder to wait on. Fly pulls the image straight from Docker Hub.
Create the app and volume
Hermes keeps all its state in/opt/data inside the container. That includes config, API keys, sessions, skills, and memories. You’ll back that with a Fly volume so it persists across deploys and restarts.
Pick an app name (must be globally unique on Fly) and a region close to you, then:
Write fly.toml
Create a directory for the deployment config and drop afly.toml in it:
machine_config.json in our example):
- No
[build.dockerfile]. Fly pulls the image directly. Deploys take seconds, not minutes. - **Hermes images published from
v2026.5.28onward uses6-overlayas the in-container supervisor. s6-overlay’s/initcallss6-overlay-suexecwhich checksgetpid() == 1before doing anything else and aborts otherwise. So we use multi-container machines (via the machine_config.json) to get our own namespace. - No
[[services]]block. The gateway talks outbound to chat platforms, so you don’t need a public port. The dashboard exposes API keys and shouldn’t be public; you’ll reach it through a Fly proxy tunnel below. - 4 GB / 2 CPU is the recommended size when browser tools (Playwright/Chromium) are active. If you don’t use browser tools you can drop to
shared-cpu-1xand 1–2 GB.
Deploy
--ha=false keeps it to a single machine; Hermes is stateful and you don’t want two gateway processes writing to the same volume.
When the deploy finishes, the machine boots, the entrypoint bootstraps /opt/data (creating .env, config.yaml, SOUL.md, sessions/, skills/, etc.), and hermes gateway run starts. It’ll keep running but it has no API key yet, so it can’t talk to a model.
Confirm it’s alive:
Configure Hermes
SSH into the machine. Thehermes binary lives at /opt/hermes/.venv/bin/hermes inside the image, but fly ssh console opens a login shell that resets PATH and won’t find it there. Add a symlink into /usr/local/bin (which is always on PATH) so hermes works as a bare command:
<machine-id> from fly machine list -a <your-hermes-app>.
Web dashboard
Hermes has a web dashboard on port 9119 for managing sessions, skills, and config. The dashboard reads your API keys, so the upstream guidance is to never expose it on a public port. Tunnel to it instead: In one terminal, start the dashboard inside the machine:http://localhost:9119 in your browser. Traffic goes over your authenticated WireGuard tunnel; the dashboard isn’t published to the public internet, though it is reachable from other Machines on your organization’s private network
When you’re done, Ctrl+C both commands. The gateway keeps running on the machine.
Upgrading
The image is stateless; your data lives on the volume. To pull the latest Hermes:nousresearch/hermes-agent:latest again. The second command re-creates the /usr/local/bin/hermes symlink; it lives on the container’s filesystem, not the data volume, so each new container starts without it.
VM sizing
If you’re running heavy tool use or multiple concurrent sessions, scale up:Useful commands
Troubleshooting
Gateway won’t start Checkhermes doctor for missing API keys or other diagnostics: