People asking whether to install Hermes Agent with Docker or natively are often comparing three different architectures without realizing it. Hermes itself can run directly on the host. The whole Hermes runtime can run inside the official container. Or Hermes can stay native while only its terminal and file execution run in a Docker sandbox. Those choices have different update, persistence, browser, gateway, and permission behavior.
Quick answer#
For most first-time laptop and VPS installs, use the native Hermes installer first, prove one model turn and one gateway message, then enable the Docker terminal backend if you want command isolation. Run the whole Hermes Agent in Docker when containerized deployment, image-based rollback, and one mounted state directory are deliberate operating requirements—not because “Docker is safer” in the abstract.
Use this rule:
- Choose native Hermes for the shortest install path, host browser access, normal CLI credentials, and simpler debugging.
- Choose native Hermes plus the Docker terminal backend when the agent should stay easy to operate but shell/file/code tools need a container boundary.
- Choose Hermes fully in Docker when your team already operates containers and will correctly own volumes, UID/GID permissions, networking, image updates, health checks, and gateway supervision.
- Choose FlyHermes pricing and managed hosting when the real requirement is an always-available agent without owning the VPS, Docker, gateway, dashboard, and recovery stack.
This page owns the Hermes Agent Docker vs native install decision. Use the official Docker installation guide for full-container commands, the Docker troubleshooting guide for failures, and the terminal backend guide for execution-only isolation.
The two meanings of “Hermes in Docker”#
The current Hermes documentation makes an important distinction.
Option A: run the whole Hermes runtime in Docker#
The CLI or gateway process, Python environment, installed application code, and enabled platform adapters run inside the container. Persistent Hermes state is mounted from the host into /opt/data. For an always-on gateway, the official pattern uses a named container with a restart policy and the persistent data mount.
mkdir -p ~/.hermes
docker run -it --rm \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent setup
docker run -d \
--name hermes \
-v ~/.hermes:/opt/data \
-p 8642:8642 \
nousresearch/hermes-agent gateway run
This is a containerized application deployment. Container networking, the mounted state directory, the runtime user, published ports, and image lifecycle all matter.
Option B: run Hermes natively and use Docker as its terminal backend#
Hermes, the CLI, Desktop, gateway, provider credentials, and session logic stay on the host. Terminal, file, and code-execution calls are routed into a Docker container. This is an execution sandbox, not a containerized Hermes installation.
hermes config set terminal.backend docker
hermes config get terminal.backend
hermes doctor
By default, the Docker backend behaves like one persistent sandbox shared across tool calls and sessions according to the current configuration. Packages and files can persist inside that sandbox, but it is still separate from the host unless you mount or expose what the workflow needs. The Docker terminal backend setup explains images, mounts, networking, and lifecycle controls.
Confusing these two architectures causes many support failures. A running application container does not prove its gateway is healthy. A native gateway using a Docker terminal backend does not mean Telegram or the dashboard lives in that container.
Choose native installation when simplicity matters#
The current installer places a per-user source checkout under ~/.hermes/hermes-agent/, creates the launcher at ~/.local/bin/hermes, and keeps state under ~/.hermes/. The recommended command-line path is:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
source ~/.bashrc # or source ~/.zshrc
hermes setup
hermes doctor
Native installation is usually the better default when:
- you want the fastest path from installation to a verified chat;
- browser automation should use a real host Chrome profile;
- host tools such as
git,gh,ssh,npm, or cloud CLIs should see their normal user configuration; - Desktop should connect to the same local runtime without container networking;
- you are still learning which files, commands, credentials, and services the agent actually needs;
- one operator will troubleshoot the machine directly.
Native does not mean unprotected. Hermes still applies its approval and dangerous-command controls. If the agent should not execute commands on the host, keep the runtime native and move only execution into Docker. The work-machine security guide covers least privilege, profiles, secret handling, and approval boundaries.
The main native trade-off is operational ownership. The host's Python environment is isolated in the Hermes virtual environment, but the operator still owns OS updates, the gateway service, browser dependencies, storage, backups, and uptime. On a personal laptop, sleep and shutdown stop scheduled work. On a VPS, native Hermes can be reliable, but you still need service supervision and recovery. Use the VPS hosting guide before assuming “native” means “temporary.”
Choose whole-agent Docker when deployment repeatability matters#
Running the entire application in Docker can be the right production choice when your operating model is already container-first. It gives you an explicit image version, a clean application boundary, predictable rollback, and one state mount to back up. It can also fit platforms where containers are the standard deployment unit.
Whole-agent Docker is a strong fit when:
- image pinning and reproducible deployment are normal for your team;
- state is mounted, backed up, and restore-tested outside the container layer;
- the gateway must restart under a container supervisor;
- published ports are protected by a private network, authentication, or a reverse proxy;
- host services and sidecars have documented network names and health checks;
- UID/GID ownership is planned rather than repaired after every update;
- browser behavior is intentionally headless or remote instead of relying on a host desktop profile.
The key persistence rule is simple: container files are disposable; Hermes state is not. Preserve /opt/data, not merely the container name. Verify that config, auth state, profiles, memory, skills, sessions, cron definitions, and gateway setup survive container replacement. The backup and restore guide should be part of the deployment, not an afterthought.
Do not expose port 8642 to the public internet merely because a Docker example publishes it. A published port is a network decision. Bind privately, use an authenticated route, and test from the actual client path. The Hermes dashboard guide explains why a working page and a safe remote control plane are different acceptance tests.
Choose the Docker terminal backend when you want a practical middle path#
For many users, the best answer is not “Docker or native.” It is native Hermes with containerized execution.
This split keeps setup, Desktop, gateways, provider auth, and host browser access straightforward. At the same time, terminal, file, and code tools execute in a constrained container. That is useful for package installation, untrusted build steps, generated code, and project work that should not share the host's full filesystem.
A safe starting configuration is deliberately narrow:
terminal:
backend: docker
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
docker_forward_env: []
docker_network: true
container_persistent: true
Do not forward every host environment variable. Add only the credentials a containerized workflow genuinely needs, and prefer scoped tokens. If a task needs host source files, use an intentional workspace mount instead of assuming /workspace contains the host repository. If a task needs a local model or database on the host, define the network path explicitly and test it from inside the sandbox.
This middle path is especially useful on a work machine: the agent interface and browser remain local, while execution gets a clearer blast-radius boundary. It is not perfect isolation if you mount sensitive host directories or forward broad credentials. Isolation depends on what crosses the boundary.
Docker vs native by operational responsibility#
Install and update#
- Native: the installer manages the checkout, virtual environment, launcher, and dependencies.
hermes updatefollows the detected installation method. - Whole-agent Docker: pull and deploy a new image, preserve state, inspect release changes, and roll back by image tag if acceptance tests fail.
- Native plus Docker backend: update Hermes natively and manage the sandbox image separately. These are two lifecycles.
State and backups#
- Native: state normally lives under
~/.hermes/. - Whole-agent Docker: persistent state must be mounted to
/opt/data; files elsewhere in the container should be treated as disposable. - Docker backend: sandbox packages and workspace files follow the configured container lifecycle. They are not a substitute for backing up Hermes state.
Gateway and cron uptime#
- Native: install and supervise the gateway service on the host. Scheduled jobs stop when that host is asleep or down.
- Whole-agent Docker: use a restart policy and health checks, then verify the actual Telegram, Discord, or API destination after container replacement.
- Docker backend: the host gateway owns schedules and messaging; only tool execution happens in the sandbox.
Browser automation#
- Native: easiest path to a real local browser profile and host CDP session.
- Whole-agent Docker: usually requires a container browser, remote browser service, VNC/CDP design, or an external profile strategy.
- Docker backend: browser location depends on the enabled browser tool and configuration; do not assume the terminal sandbox also contains the authenticated browser.
Security boundary#
- Native: commands can run with the host user's permissions unless you choose a sandboxed backend and approval policy.
- Whole-agent Docker: the application is containerized, but mounted secrets, Docker socket access, broad host volumes, and public ports can erase much of the boundary.
- Docker backend: command execution is isolated, but host-side Hermes still holds the profile's configured provider and gateway access.
VPS does not decide Docker vs native for you#
A VPS answers where the runtime lives. Docker vs native answers how the runtime and its execution environment are packaged. You can run native Hermes on a VPS, whole-agent Docker on a VPS, or native Hermes on the VPS with a Docker terminal backend.
Choose native on a VPS when you want the documented installer, direct system service management, normal host networking, and simpler access to host tools. Choose Docker on a VPS when image deployment, rollback, and container operations are already reliable. Do not add Docker only to make an unfamiliar VPS feel safer; two unfamiliar layers produce harder incidents.
If the agent must remain available on phone, browser, or messaging channels and nobody wants to own either stack, compare the self-hosted vs hosted responsibility matrix. Managed hosting is not “Docker done for you”; it transfers supported uptime, deployment, and recovery work to an operator while you keep responsibility for business permissions and risky actions.
Common failure patterns and what they reveal#
The container is running, but Telegram does not reply#
docker ps proves a process container exists. It does not prove provider completion, gateway polling, chat allowlists, topic routing, or outbound delivery. Inspect container logs, gateway state, provider health, and the exact chat destination. Use the gateway troubleshooting guide before rebuilding the image.
hermes works on the host but not inside the container#
That usually means you are mixing the native launcher path with the application-container path, or entering a runtime image whose entry point and user differ from the host install. Decide which architecture owns the CLI; do not patch both until the ownership is clear.
Files disappear after container replacement#
The workflow wrote outside the persistent state or workspace mount. Recreate the container only after identifying which data is canonical. Back up the mounted state, pin the corrected path, replace the container, and prove restore.
Permission denied under /opt/data#
The host directory and container user disagree about ownership. Record the container UID/GID and host mount permissions, repair the narrow path, and retest setup plus gateway writes. Avoid running the whole application as root merely to hide a mount problem.
The native agent cannot reach a host service from its Docker backend#
Inside a container, localhost means that container. Use the documented host-gateway or service-network address, expose only the needed port, and run the health check from inside the sandbox. This commonly affects Ollama, databases, and local APIs.
Browser login exists on the host but not in Docker#
A host Chrome profile is not automatically available inside an application container or terminal sandbox. Decide whether the browser should run on the host, inside Docker, or through a remote browser service. Copying a live profile casually can create credential and file-lock risks; use the browser automation troubleshooting guide.
Migration checklist: change architecture without losing state#
Use this sequence when moving from native to Docker or back:
- Pause consequential cron jobs and gateway-triggered writes.
- Record the active profile, Hermes version, provider route, terminal backend, enabled channels, and public/private ports.
- Back up the canonical Hermes home and verify the backup contains config, profiles, memory, skills, sessions, and cron definitions.
- Build the target architecture with a separate test state path; do not let two gateways poll the same bot token.
- Run
hermes doctor, one exact provider smoke test, one harmless tool call, and one dashboard/auth check. - Send one inbound gateway message and one scheduled outbound result through the real production destination.
- Replace or reboot the runtime and repeat the tests to prove persistence and supervision.
- Switch traffic once, keep a time-boxed rollback, then stop the old gateway so duplicate polling cannot return.
The most dangerous migration result is two apparently healthy runtimes sharing credentials or state. Treat provider keys, bot tokens, mounted directories, and browser profiles as single-owner resources unless the product explicitly supports sharing.
Five-minute decision checklist#
Choose native Hermes if most answers are yes:
- Do you want the shortest path to a working CLI or Desktop?
- Do you need host browser identity or existing host CLIs?
- Are you still discovering workflow dependencies?
- Can one operator own host service recovery?
Choose whole-agent Docker if most answers are yes:
- Does your team already pin, deploy, monitor, and roll back images?
- Is
/opt/databacked up and restore-tested? - Are UID/GID, networking, ports, and browser strategy explicit?
- Will a container supervisor own the gateway lifecycle?
Choose native plus Docker terminal backend if most answers are yes:
- Do you want host-native setup and channels but isolated command execution?
- Can you keep forwarded secrets and mounted directories narrow?
- Are sandbox packages/workspaces expected to persist across runs?
- Can you test host-service networking from inside the sandbox?
Choose FlyHermes if the answer is no to the most important operator question: will someone reliably own updates, state, networking, gateway uptime, dashboard security, backups, and incident response?
Acceptance test before calling any install production-ready#
Run the same test pack regardless of architecture:
hermes doctor
hermes config get terminal.backend
Then verify behavior, not just status:
- Start a fresh session and request one exact short response.
- Run one harmless command and confirm whether it executed on the host or in Docker.
- Read and write a test file in the intended persistent workspace.
- Open the dashboard through the intended private/authenticated route.
- Send a message through the real Telegram, Discord, Slack, or other destination.
- Schedule one harmless result and confirm delivery.
- Restart or replace the runtime and prove state, gateway, and schedule recovery.
- Confirm no second gateway is polling the same bot credential.
A green container, healthy process, or open dashboard is only one layer of proof. The install is ready when the real workflow completes after a controlled restart.
Final recommendation#
Start native unless you already have a reason not to. It is the shortest route to understanding Hermes and proving the workflow. Add the Docker terminal backend when command isolation is the requirement. Containerize the whole application when repeatable image operations and mounted-state recovery are requirements your team already knows how to maintain.
If the requirement is simply “keep my agent available without becoming a Linux, Docker, gateway, and backup operator,” use the managed FlyHermes path. The right choice is the one whose failure modes you can test and whose operational owner is explicit.