✦
Hermes Agent

terminal

Hermes Docker vs Podman vs Terminal Sandbox

·Hermes Docker vs Podmanterminaldockersshmodalconfiguration

Choose Docker, Podman, local, SSH, cloud, or HPC execution for Hermes Agent. Separate whole-agent hosting from tool sandboxing and verify the real boundary.

A Hermes terminal backend selects where terminal-tool work and its associated file and code operations run. It does not move every Hermes process or Python dependency into that environment. The effective backend may be your Mac or Linux host, a Docker sandbox, an SSH server, Modal, Daytona, or a Singularity/Apptainer environment. Choosing the wrong one can make a healthy agent look broken because it sees the wrong files, network, credentials, or runtime.

This guide owns one job: choose the right Hermes terminal backend, prove which backend is active, and diagnose cases where Hermes appears to use Docker even though config.yaml says local.

Quick answer#

Use local for trusted work on the machine where Hermes runs, docker when commands need a disposable boundary, ssh when the code or service lives on another server, and a cloud/HPC backend only when the workload genuinely needs it. Set the backend with hermes config set terminal.backend local, start a new session, and verify the effective runtime with a harmless command such as pwd plus uname -a. If hermes config get terminal.backend says local but tools still enter Docker, update Hermes, inspect TERMINAL_ENV in every environment source used by the running gateway, and fully reload the long-running process.

The backend is a security and data boundary, not a cosmetic preference. Before changing it, back up durable state with the Hermes backup guide, confirm the active profile, and keep secrets in the profile environment rather than copying them into prompts. For an always-on server, pair this guide with VPS deployment, Docker Compose setup, and gateway troubleshooting. If maintaining that stack is not the job you want, compare the managed path on FlyHermes pricing.

The six backend choices#

Local#

local runs commands directly on the Hermes host. It is the fastest choice for a trusted personal machine and the easiest way to work on an existing local repository. It also has the broadest blast radius: the agent can touch files and commands available to the Hermes user. Use OS permissions, a dedicated profile, tool approvals, and a clean Git worktree when the task is risky.

hermes config set terminal.backend local
hermes config get terminal.backend

Docker#

docker runs tool work in a container boundary. Choose it for dependency isolation, disposable builds, or tasks that should not run directly on the host. Docker must be installed and reachable by the user that actually runs Hermes. A gateway service account without Docker socket access will fail even when Docker works in your interactive shell. Continue with the Docker terminal backend guide and the Docker troubleshooting checklist.

SSH#

ssh sends tool execution to a remote machine. It is useful when the repository, GPU, database, or deployment runtime lives elsewhere. Verify host-key trust, least-privilege credentials, remote working directory, and non-interactive PATH before giving the agent a real task. Use the SSH terminal backend setup for the exact connection checklist.

Modal and Daytona are remote execution backends for workloads that benefit from disposable cloud compute or managed workspaces. They add provider authentication, remote lifecycle, network, and persistence boundaries. Do not choose them merely because they sound more scalable; use them when a local or SSH runtime cannot satisfy the workload. See the Modal setup guide or Daytona setup guide.

Singularity / Apptainer#

Singularity is the HPC-oriented option for environments where Docker is unavailable or inappropriate. It is useful on research clusters with scheduler, image, mount, and GPU policies. Follow the Singularity backend guide and verify the exact cluster rules before enabling unattended jobs.

Docker vs Podman vs a jail: what Hermes actually supports#

These names describe different layers, so do not treat them as interchangeable settings:

  • Docker terminal backend: a documented Hermes backend. Hermes stays on the host while terminal, file, and code-execution work runs in a persistent or ephemeral container.
  • Whole-agent Docker: the Hermes process, gateway, and optional Dashboard run in the official container. This is a deployment choice, not terminal.backend: docker. Use the Docker vs native installation guide before choosing it.
  • Podman: a container engine with a Docker-compatible command/API surface, but it is not a separate terminal.backend value. Do not set terminal.backend: podman. Treat Podman as an advanced compatibility path only after proving the exact Hermes image, socket, mounts, networking, persistence, and restart behavior on your host.
  • OS jail or sandbox: FreeBSD jail, macOS sandboxing, systemd hardening, and similar controls constrain the host process. They are not Hermes terminal backends. If you build one, it is an operator-owned security layer around local, not a supported config shortcut.
  • Singularity/Apptainer: the documented HPC-oriented backend for clusters where Docker is unavailable or forbidden. It is not a general Podman replacement.

Which one should you choose?#

Use Docker when you want the supported container boundary with the least ambiguity. Use Podman only when an organizational or rootless-container requirement justifies owning compatibility testing. Use an OS-level jail only when your platform team already operates that control and can prove filesystem, process, network, and secret boundaries. If the real goal is simply a 24/7 agent without container, gateway, update, and backup ownership, compare the managed FlyHermes path instead of adding another runtime layer.

Podman compatibility acceptance test#

Before unattended use, require all of these checks to pass from the same user and service process that runs Hermes:

  1. The Docker-compatible client and socket are reachable without interactive shell setup.
  2. The configured image starts and reports the expected architecture, Python, Node, and working directory.
  3. Required project mounts are present; host secrets and unrelated home directories are absent.
  4. Container networking reaches only the services the job needs, including any host alias used for local APIs.
  5. Persistent mode survives a Hermes/gateway restart; ephemeral mode actually removes prior task state.
  6. Memory/CPU limits and termination behavior work under a deliberately bounded test.
  7. A harmless CLI turn and a turn sent through the real gateway produce the same backend evidence.

If any check fails, return to the supported Docker backend or use local with explicit host controls. Do not advertise a Podman experiment as equivalent to the documented Docker path merely because one podman run command succeeded.

Decision checklist#

Choose the narrowest backend that can complete the job:

  • Need the current machine and repository? Use local.
  • Need dependency isolation or a disposable build? Use Docker.
  • Need an existing remote server or GPU box? Use SSH.
  • Need temporary managed cloud compute? Evaluate Modal or Daytona.
  • Need an HPC-compatible container runtime? Use Singularity/Apptainer.
  • Need a 24/7 agent but do not want to operate servers, providers, gateways, and dashboard security? Compare self-hosted vs hosted Hermes.

Verify the effective backend#

Do not stop at the value written in config.yaml. Prove the complete path used by the active profile and process.

hermes config path
hermes config get terminal.backend
hermes doctor
hermes chat -q 'Run pwd and uname -a, then report the execution environment.'

Check five facts in the result: active profile, working directory, operating system, expected files, and expected network/runtime access. Then test one representative operation such as reading a repository file or running its smallest test. A successful config write does not prove that an old gateway process, another profile, or an environment override is not still selecting a different backend.

Why Hermes can appear stuck on Docker#

A fresh August 2026 Discord support case captured the confusing symptom precisely: hermes config get terminal.backend returned local, but terminal, execute_code, and file operations later behaved as Docker-bound. The final diagnosis was not memory injection and not an agent secretly changing infrastructure. A stale TERMINAL_ENV value was entering the long-running gateway environment during reload. The gateway reload path was fixed upstream, but the case provides a durable troubleshooting order.

  1. Update first. Run hermes update, then start a new session on the updated process.
  2. Confirm the active profile and config path. A correct value in one profile does not control another profile.
  3. Read the configured value. Run hermes config get terminal.backend.
  4. Look for environment overrides. Check the profile .env, machine-managed environment files, the service definition, and the live process environment for TERMINAL_ENV. Do not print unrelated secrets.
  5. Remove duplicate sources. Prefer terminal.backend in config.yaml as the single user-level source unless an environment override is intentionally required.
  6. Reload the long-running runtime. CLI sessions, dashboard/backend processes, and messaging gateways can retain old in-memory configuration.
  7. Run an end-to-end proof from the same channel and profile that failed. A local shell test does not prove a Matrix, Telegram, Discord, or Desktop-backed turn uses the same environment.
  8. Capture diagnostics before changing more variables. On current Hermes, hermes debug share --nous can provide a redacted diagnostics report for support.

Do not let the agent diagnose its own backend from conversational memory alone. The effective config, process environment, and real tool output are the evidence.

Local shell vs gateway service: prove both#

A common trap is testing only the interactive shell. A user service can inherit a different PATH, home directory, profile, Docker socket permission, or environment than the shell where hermes config get was run. Test the runtime from the same entry point that failed:

  • CLI failure: start a new CLI session and run the proof command.
  • Telegram, Discord, Matrix, or Slack failure: send the proof task through that channel after the gateway reload.
  • Dashboard/Desktop failure: reconnect to the intended backend and verify the active profile before testing.
  • Scheduled job failure: inspect the job's profile, provider/model pinning, last status, and delivery result as well as the terminal backend.

For Linux user services, compare the service definition and live process environment without dumping the whole environment. Filter specifically for TERMINAL_, Hermes home/profile, PATH, and the service command. Credentials should remain redacted.

A cron dependency error may be outside the terminal backend#

A package installed inside the task's Docker sandbox does not become available to the Python process running the gateway. The same applies to an SSH backend: a successful import on the remote host tells you nothing about packages on the scheduler host.

For the managed systemd path, current cron documentation says the external worker uses the gateway's interpreter and checkout. Separate that startup stage from a tool command executed later:

  1. If the worker exits before acknowledging ownership and stderr names an import error, inspect the gateway interpreter and dependency selection. The terminal sandbox may never have started.
  2. If the agent starts but a terminal command cannot import a project dependency, inspect the interpreter inside the selected terminal backend and its project environment.
  3. If both run but the expected file is absent, compare the actual working directory and mounts. Reinstalling Python packages cannot expose an unmounted host directory.

Record the interpreter path and package origin on the failing side before making changes. The cron startup diagnostic includes a small probe that reports those paths without dumping credentials. Avoid a generic pip install repair until you know which interpreter would receive it.

PM-managed Hermes dependencies, project dependencies and a container image have different owners. Follow the package-management diagnostics for the application runtime; use the project's declared environment for its own code. After changing a managed Python generation, restart the affected Hermes process before testing again. Keep the Docker sandbox enabled if its isolation is required: switching to local merely to hide a dependency error changes the security boundary.

Backend failure matrix#

Config says local, tools use Docker#

Update Hermes, remove unintended TERMINAL_ENV overrides, reload the actual long-running process, start a new session, and test from the original channel/profile. If it persists, capture a redacted diagnostics report before editing more files.

Docker exits before any command runs#

Confirm the effective backend is really Docker. Then verify Docker is installed, the daemon is healthy, and the Hermes user can access it. If Docker was never intended, set terminal.backend to local instead of trying to repair an unnecessary container dependency.

SSH works manually but Hermes cannot connect#

Check the non-interactive user, key path, host key, remote PATH, working directory, and whether the profile running Hermes can read the credential. A successful connection from another shell or user does not prove the Hermes process can connect.

Commands run but files are missing#

Print pwd, list the expected project root, and identify the backend before modifying mount or path config. In Docker, confirm the host path is mounted. In SSH/cloud backends, confirm the repository exists on the remote runtime.

Backend changed after an update or setup wizard#

Run hermes config get terminal.backend, inspect the config path for the active profile, and check environment overrides. Do not infer backend state from old chat history or memory. Tool/config changes may require a new session; long-running gateway or dashboard processes require a full reload.

Safe first task after switching#

Use a read-only proof before package installs or writes:

Report the current working directory, operating system, active user, and whether the expected project directory exists. Do not change files or install anything.

Then run one tiny project-specific command, such as a version check or the smallest unit test. Only after both checks pass should you allow broad package installs, deployment commands, or scheduled execution.

Self-hosted ownership vs managed outcome#

Terminal backends are one of the real operating costs of self-hosting. A local machine can sleep, Docker needs images and permissions, SSH needs credential and host maintenance, and cloud/HPC backends need provider-specific lifecycle controls. The Hermes cost calculator helps count those costs. Self-host when that control is valuable; choose FlyHermes when browser/mobile access and managed uptime matter more than owning each execution boundary.

Update failures can be backend failures#

When a Hermes update appears to break terminal tools, verify whether the selected backend is local, Docker, SSH, or Modal before blaming the model. Recent Docker-image and install/update threads show this exact confusion. Pair this guide with Hermes update command hangs, Docker install, and security hardening so backend changes are deliberate.

The browser and terminal can fail in different namespaces#

A local, Docker, or SSH terminal backend does not automatically place Chrome in the same network namespace. Record where Hermes, the browser daemon, and the CDP endpoint run, then test from that boundary. The Hermes browser automation troubleshooting guide explains stale ports, localhost mistakes, named-session isolation, and safe recovery.

Do not confuse the Docker backend with Docker installation#

The Docker terminal backend keeps Hermes and its gateways on the host while execution runs in a sandbox. Running the whole application in the official image is a separate architecture. The Docker vs native installation guide shows when each boundary is the better choice.

Frequently Asked Questions

Which Hermes terminal backend should I use?

Use local for trusted work on the Hermes host, Docker for disposable isolation, SSH for an existing remote machine, Modal or Daytona for managed cloud compute, and Singularity/Apptainer for HPC environments.

How do I change the Hermes terminal backend to local?

Run `hermes config set terminal.backend local`, confirm it with `hermes config get terminal.backend`, reload any long-running Hermes process, start a new session, and prove the runtime with `pwd` and `uname -a`.

Why does Hermes use Docker when terminal.backend is local?

The active process may be using another profile, retaining old in-memory config, or receiving a `TERMINAL_ENV` override from an environment source. Update Hermes, inspect only terminal-related environment values, remove duplicate overrides, reload the actual gateway/dashboard process, and test from the original channel.

Do Hermes tool changes apply to an existing session?

Not always. Tool and backend configuration should be verified in a new session, while long-running dashboard or messaging gateway processes may need a full reload to drop stale in-memory state.

Is the Docker backend safer than local?

Docker adds an isolation boundary, but it is not automatically safe. Review mounts, network access, secrets, Docker socket permissions, image provenance, and the commands the Hermes user can execute.

How can I prove which backend a gateway message used?

Send a read-only proof task through the same platform and profile: report `pwd`, operating system, active user, and whether the expected project directory exists. A shell test outside that gateway does not prove the gateway inherited the same environment.

When is a managed Hermes agent better than choosing a terminal backend?

Choose FlyHermes when the desired result is browser/mobile access and managed uptime without operating local, Docker, SSH, provider, gateway, dashboard-security, and recovery infrastructure yourself.

Can Hermes use Podman as a terminal backend?

Podman is not a separate terminal.backend value. Advanced operators may test its Docker-compatible interface, but they must verify sockets, images, mounts, networking, persistence, limits, and gateway service behavior. Use the documented Docker backend when compatibility certainty matters.

Is an OS jail the same as the Hermes Docker backend?

No. A jail, macOS sandbox, or systemd restriction is an operator-managed control around the Hermes host process. The Docker terminal backend is a Hermes execution mode that moves tool work into a container boundary.

Why can a package work in the Docker terminal but fail in a cron worker?

They can use different Python environments. A task dependency belongs in the selected terminal backend; a startup import in the managed systemd worker belongs to the gateway runtime. Identify the failing interpreter before installing or repairing anything.

FlyHermes (Managed Cloud)

Deploy in 60 seconds. API costs included. Cancel anytime.

Deploy faster with FlyHermes →

Self-Host (Open Source)

Full control. MIT licensed. Run on your own infrastructure.

View install guide →

Keep reading

Related Hermes Agent guides