Skip to content

Terminal Backends

Hermes runs wherever you put it. The terminal backend determines where shell commands actually execute, your local machine, a Docker container, a remote server over SSH, or a serverless environment that hibernates when idle. This lesson covers all six backends and when to reach for each one.

Owl mascot

What you'll learn

  • Six backends: local, Docker, SSH, Daytona, Singularity, Modal, each with different isolation, cost, and persistence tradeoffs
  • Docker is the sweet spot for most production deployments: strong isolation, simple configuration, shared kernel
  • Daytona and Modal offer serverless persistence, your environment hibernates when idle, costing nearly nothing

The problem

Running Hermes on your laptop works until you close the lid. Running it on a VPS works until a script escapes and touches something it shouldn't. The terminal backend determines the boundary between Hermes and the host system. Pick the wrong one and you're either paying for isolation you don't need, or running without isolation you do.

Options & when to use each

BackendIsolationCostPersistenceWhen to use
localNone, shares host filesystem and processesFreeFullDevelopment, trusted tasks, quick one-shots
DockerStrong, container filesystem, resource limits, network isolationContainer overhead (~50MB RAM)Ephemeral (unless volumes mounted)Production pipelines, untrusted code execution, reproducible environments
SSHHost-level, runs commands on a remote machineRemote server costFull (on remote)Delegating work to a specific server, running on a machine with different hardware/OS
DaytonaContainer-level + serverless persistenceFree tier availableHibernates when idleLong-running agents that need to survive laptop sleep, zero-cost idle
SingularityContainer-level, HPC-focusedCluster costEphemeralHPC environments, GPU clusters, scientific computing
ModalServerless, scales to zeroPay-per-secondHibernates when idleBursty workloads, GPU-accelerated tasks, zero-cost idle

For most people deploying Hermes in production, Docker is the right answer. It's the simplest to configure, the most widely documented, and provides enough isolation for the vast majority of use cases. Reach for Daytona or Modal when you specifically need serverless persistence (the agent hibernates instead of running 24/7 on a VPS). Reach for SSH when the work needs to happen on a specific machine.

Build it: Docker backend

Step 1: Configure the Docker backend

Point the terminal executor at Docker and specify your base image. This ensures all subsequent commands land securely inside an isolated container.

bash
hermes config set terminal.backend docker
hermes config set terminal.docker.image "python:3.11-slim"

Hermes will now run all shell commands inside a Docker container based on the specified image. The container is created on first use and reused across the session.

Step 2: Add resource limits and volume mounts

Define runtime boundaries and data sharing in your configuration file. Capping memory and CPU prevents a runaway script from crashing the host machine.

yaml
# In ~/.hermes/config.yaml
terminal:
  backend: docker
  docker:
    image: "python:3.11-slim"
    memory: "2g"
    cpus: "1.0"
    volumes:
      - "/home/deploy/incoming:/workspace/incoming:rw"
    network: "none"  # isolate from network unless needed
    user: "1000:1000"  # run as non-root

Key settings:

  • memory: "2g" , prevents a runaway agent script from consuming host RAM
  • network: "none" , blocks all outbound network access. Use "bridge" if the agent needs to call APIs
  • user: "1000:1000" , runs as non-root inside the container. Match the host user's UID to avoid permission issues on mounted volumes
  • volumes , only mount the directories the agent actually needs. Never mount / or /home

Step 3: Verify the backend

Probe the environment through a chat prompt to confirm the agent operates within the new container. The output must reflect the isolated filesystem instead of your host machine.

bash
hermes chat -q "What OS am I running on? Print the contents of /etc/os-release."

If the output shows the container's OS (not your host's), the Docker backend is active. The agent's commands are now sandboxed.

Build it: Daytona backend (serverless)

Switch to a Daytona workspace for persistent, suspendable environments. This setup saves compute resources when the agent is idle.

bash
# Install Daytona CLI first, then:
hermes config set terminal.backend daytona
hermes config set terminal.daytona.workspace "hermes-agent"

Daytona creates a persistent workspace that hibernates when idle. Hermes connects to it on demand. You pay nothing while it's hibernating. This is ideal for an agent you want always available but don't want running 24/7 on a VPS.

Build it: Modal backend (serverless: GPU-capable)

Enable the Modal backend to access remote compute scaling, particularly useful for heavy lifting like image generation or model inference.

bash
hermes config set terminal.backend modal
hermes config set terminal.modal.gpu "A10G"

Modal is serverless with GPU access. Use it when Hermes needs to run GPU-accelerated tasks (model inference, image processing) without provisioning a dedicated GPU server.

What goes wrong

MistakeHow you notice itThe fix
Docker volume permission deniedPermissionError: [Errno 13] when writing to mounted volumeHost directory UID doesn't match container user UID. Run chown -R 1000:1000 on the host directory, or set user to match the host user's UID
Docker OOM killCommand failed with exit code 137The agent tried to load too much data into memory. Increase memory limit, or write agent instructions enforcing chunked processing (e.g., pandas with chunksize)
Network isolation blocks API callsConnectionTimeout when the agent tries to call an APIThe container was started with network: "none" but the agent needs API access. Switch to network: "bridge" or configure a custom network that only allows specific domains
Daytona workspace won't starthermes chat hangs waiting for the workspaceThe workspace may have been stopped or corrupted. Run daytona list to check workspace status, then daytona start hermes-agent to manually start it

Confirm it worked

Verify the execution context by asking the agent to inspect its host environment. If it cannot read the underlying server's paths, the isolation is solid.

bash
# 1. Check the active backend
hermes config | grep "backend:"

# 2. Run a command that reveals the execution environment
hermes chat -q "Run 'hostname' and 'whoami'. Tell me what container/runtime you're in."

# 3. Verify isolation: try to read a host file that's not mounted
hermes chat -q "Try to read /etc/hostname. If it fails, tell me why."

If step 3 fails (the file isn't accessible from the container), the backend isolation is working correctly.

Next: Security , command approval, secret redaction, and locking down what Hermes can do.