The SSH Terminal Backend: Shell Access Across Your Lab
- Configure the SSH terminal backend in config.yaml and .env with host, user, port, and key credentials
- Explain what the persistent shell model means and why it matters for multi-command homelab workflows
- Set up a profile-per-host pattern to reach multiple machines from a single Hermes installation
- Enable the terminal and file toolsets and verify SSH connectivity with a test command
Terminal Backends: A Quick Map
Hermes can execute shell commands in six different environments, called backends. The default is local -- commands run directly on the machine where Hermes is installed. For homelab use, you almost always want something else:
- local -- runs on the Hermes host itself. Useful for managing the host machine, but not your whole lab.
- docker -- runs inside a persistent hardened container. Good for untrusted code and skill experiments.
- ssh -- runs on a remote server over SSH. This is what lets your agent reach your NAS, your router, your workstation, or any other machine in the lab.
- modal / daytona / singularity -- cloud or HPC backends, outside the scope of this track.
The terminal and file toolsets both route through whichever backend is active. When you switch to the SSH backend, commands you ask the agent to run -- and files the agent reads or writes -- happen on the remote host, not the Hermes machine.
Configuring the SSH Backend
Open ~/.hermes/config.yaml (on your Hermes host) and add or update the terminal section:
terminal:
backend: ssh
persistent_shell: true
timeout: 180
Then add your SSH credentials to ~/.hermes/.env:
TERMINAL_SSH_HOST=192.168.1.100
TERMINAL_SSH_USER=hermes
TERMINAL_SSH_PORT=22
TERMINAL_SSH_KEY=~/.ssh/id_ed25519
If TERMINAL_SSH_KEY is omitted, Hermes uses ssh-agent if one is running. On a homelab machine you will usually want to point it at a specific key.
Every terminal: config key has a corresponding TERMINAL_<KEY_UPPERCASE> env-var override. This means you can set all SSH config in .env and keep config.yaml clean and version-control safe.
The Persistent Shell
With persistent_shell: true (the default for the SSH backend), Hermes keeps a single bash -l process alive on the remote host using SSH ControlMaster with a 5-minute idle keepalive. This has two practical implications:
- State survives between commands. If you
cd /var/login one command and then list files in the next, the working directory is still/var/log. Environment variables youexportalso persist. - Connection overhead happens once. The SSH handshake and login happen at session start, not before every command. Long sequences of commands are fast.
You can turn this off with persistent_shell: false if you want each command to start a fresh connection, but for homelab use the persistent model is almost always what you want.
Multiple Machines: The Profile-per-Host Pattern
Hermes does not support multiple named SSH remotes in a single profile's config. Instead, use a separate Hermes profile for each machine you want to reach directly:
# Profile pointed at the NAS
hermes -p nas chat
# Profile pointed at the router
hermes -p router chat
# Default profile (local or wherever you set it)
hermes chat
Each profile has its own ~/.hermes/profiles/<name>/config.yaml and .env. Set terminal.backend: ssh and the appropriate host credentials in each profile's files. Create a new profile with:
hermes profile create nas
This creates the profile directory structure. Then edit ~/.hermes/profiles/nas/.env with the SSH credentials for that host.
For a homelab with three or four machines, four profiles (one per host) is perfectly manageable. For a larger fleet, the SSH backend also supports running ad-hoc commands against arbitrary hosts using ssh user@host command syntax in the terminal tool -- so you can reach machines beyond the configured backend host within a single session by just SSHing from there.
Enabling the Right Toolsets
The SSH backend is a transport layer -- it changes where commands run, not which tools are available. You still need to explicitly enable the toolsets the agent will use. For homelab infrastructure work, enable terminal and file at minimum:
hermes chat --toolsets terminal,file,web
To avoid passing the flag every session, use the interactive toolset configurator:
hermes tools
This opens a per-platform tool configuration UI where you can set which toolsets are active by default for CLI sessions. Changes are saved to your profile's config automatically. You can also globally suppress a toolset across all platforms via config.yaml:
agent:
disabled_toolsets:
- browser # example: disable browser everywhere
Note: the --toolsets flag on hermes chat always overrides saved defaults for that session.
Testing the Connection
After configuring the SSH backend, start a chat session and ask the agent to run a simple command:
hermes chat --toolsets terminal
> run "hostname && uptime" on the remote host
If the backend is configured correctly, you will see the hostname and uptime of the remote machine in the response. If you get an error, check that TERMINAL_SSH_HOST is set in .env, that the key file is readable, and that the remote host has the Hermes user's public key in authorized_keys.
- The SSH backend routes all terminal and file tool calls to a remote machine over SSH -- this is the core capability that makes Hermes a lab-wide tool, not just a local assistant
- Persistent shell (default: true) keeps a single bash process alive on the remote host via SSH ControlMaster, so cwd and env vars survive across commands within a session
- Multiple SSH targets require multiple Hermes profiles (hermes -p nas chat) -- there is no multi-remote config within a single profile
- SSH credentials belong in ~/.hermes/.env (TERMINAL_SSH_HOST, TERMINAL_SSH_USER, TERMINAL_SSH_KEY), not in config.yaml, so config stays safe to share or version control
- Enable terminal,file,web toolsets explicitly or set defaults per-platform in config.yaml under platforms.cli.toolsets