How To Install Hermes Agent on Ubuntu 26.04 LTS

Install Hermes Agent on Ubuntu 26.04

Every few months a new AI agent framework shows up promising to “run itself” on your infrastructure, and most of them fall apart the second you try to put them on a real server instead of a laptop. Hermes Agent, the open-source autonomous agent framework from Nous Research, is one of the rare exceptions that actually behaves like production software once you know where the sharp edges are.

If you’ve landed here, you’re probably trying to get Hermes running on a fresh Ubuntu 26.04 LTS “Resolute Raccoon” box, either for personal automation, a client project, or as a persistent assistant reachable from Telegram or Slack around the clock. That’s a reasonable goal. Hermes is designed exactly for that: a long-running process with persistent memory that grows its own skill set over time, rather than a stateless chatbot you open and close.

The problem is that most install guides floating around treat this like a five-minute hobbyist task. Pipe a curl script into bash, run hermes setup, done. That works fine on a personal machine you reboot every night. It does not work fine when you’re the person on-call at 3 a.m. because the agent process died silently, or when a client asks why an unauthenticated port is open on their VPS, or when a compliance audit flags a root-owned Python environment nobody can explain.

This guide walks through installing Hermes Agent on Ubuntu 26.04 LTS the way you’d actually want it configured on a server you’re responsible for: proper user isolation, systemd supervision with automatic restarts, Docker-based sandboxing for tool execution, firewall rules, and a troubleshooting section built from the kinds of errors that actually show up in the wild. Ubuntu 26.04 shipped with Linux kernel 7.0, GNOME 50 on the desktop side, a Wayland-only session, and the new sudo-rs implementation replacing the classic sudo binary, all of which have small but real implications for how you should set this up.

What Hermes Agent Actually Is (and Why That Matters for Installation)

Before touching a terminal, it’s worth being precise about what you’re installing, because the architecture dictates the install decisions later.

Hermes Agent is not a single binary or a Docker image you just pull. It’s a self-hosted runtime, MIT-licensed, built around a Python 3.11 environment, that combines an LLM of your choosing with persistent memory, a skill-creation loop, and roughly 70 built-in tools ranging from terminal access to browser automation. It was released in February 2026 and picked up traction fast, crossing 140,000 GitHub stars within about twelve weeks, largely because of that self-improving skill system nobody else shipped at the time.

Two architectural facts matter immediately for a sysadmin:

The agent runs continuously as a background process, not on-demand. That means it needs proper process supervision (systemd, not a screen session someone forgot about), log rotation, and restart policies, exactly like you’d treat any long-running daemon such as nginx or postgresql.

The agent executes arbitrary commands and tools on whatever “terminal backend” you point it at. Hermes supports six of these: local execution, Docker, SSH, Daytona, Modal, and Singularity. Running an autonomous agent with local terminal access directly on a production host, with no sandbox, is asking for trouble. This is the single most important decision in the entire setup, and we’ll come back to it in the security section.

Pre-Installation Checklist for Ubuntu 26.04 LTS

Don’t skip this part just because the installer looks simple. A five-minute checklist here saves an hour of debugging later.

Minimum System Requirements

For a lightweight setup using cloud model providers (OpenRouter, Anthropic, OpenAI, or the Nous Portal), a 2 GB RAM VPS is technically sufficient. In practice, treat 2 GB as the absolute floor and only acceptable if Hermes is the only meaningful workload on that box. If you plan to run local models through Ollama, budget at least 8 GB of RAM, and more if you’re loading anything beyond small quantized models. Disk-wise, allow at least 10 GB free beyond your base OS footprint; the installer pulls its own Python runtime, Node.js, and supporting tools, and memory/skill logs accumulate over time.

Access and Account Setup

You’ll need SSH access with sudo privileges, and ideally a dedicated non-root user rather than deploying everything under root. Ubuntu 26.04’s move to sudo-rs doesn’t change command syntax for everyday use, but if you’ve written automation scripts that parse legacy sudo’s stderr output for specific error strings, test those against the new implementation before relying on them in production.

You’ll also need an API key from your chosen model provider, or a plan to run fully local inference through Ollama if data residency or cost is a concern.

Update the Base System First

Never install a new service stack on top of a stale system. Run this before anything else:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git build-essential

On a freshly provisioned 26.04 image this usually pulls in kernel and security patches Canonical has shipped since the ISO was baked. Reboot afterward if the kernel was updated:

sudo reboot

Skipping the reboot after a kernel upgrade is a classic shortcut that comes back to bite you during troubleshooting three weeks later when you’re chasing a bug that was already fixed upstream.

Step-by-Step: Installing Hermes Agent

Step 1: Create a Dedicated Service User

Resist the urge to install Hermes under your personal admin account or, worse, root. A dedicated user with limited privileges is standard practice for any long-running service and keeps the agent’s file access scoped to its own home directory.

sudo adduser --disabled-password --gecos "" hermes
sudo su - hermes

Everything from this point until the systemd step happens as the hermes user.

Step 2: Run the Installer

Hermes ships a single-command installer that works identically across Linux distributions:

curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash

An older mirror of the same script also works if the primary domain is unreachable from your network:

curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

A quick professional habit worth mentioning: piping curl straight into bash is convenient, but on anything touching production, download and read the script first.

curl -fsSLO https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh
less install.sh
bash install.sh

This isn’t paranoia for its own sake. It takes thirty seconds and it’s the difference between knowingly running a script and blindly trusting a domain you don’t control the DNS for.

The installer sets up its own isolated Python 3.11 environment using uv, along with Node.js, ripgrep, and ffmpeg, and stores everything under ~/.hermes/ without requiring root access. That isolation is a genuinely good design decision; it means a broken system Python or a distro-managed package conflict won’t take Hermes down with it, and vice versa.

Step 3: Reload Your Shell

source ~/.bashrc

If you’re on zsh instead of bash, source the equivalent file:

source ~/.zshrc

Step 4: Confirm the Installation

hermes --version

If this returns a version string, the binary is on your PATH and the install completed. If it doesn’t, jump ahead to the troubleshooting section, this is the single most common failure point.

Step 5: Run the Setup Wizard

hermes setup

This interactive wizard walks through:

  1. Choosing a model provider: Nous Portal, OpenRouter, Anthropic, OpenAI, local Ollama, or any OpenAI-compatible endpoint
  2. Entering an API key (Nous Portal’s Quick Setup skips this using a device-code login flow instead)
  3. Selecting a default model
  4. Choosing which of the built-in tools to enable
  5. Picking a terminal backend (local, Docker, SSH, and others)
  6. Optionally connecting a messaging platform

For anything beyond a personal sandbox, choose Docker as the terminal backend here. We’ll set that up properly in the next section.

Step 6: First Interactive Run

hermes

This drops you into an interactive chat session so you can confirm the model responds and tools execute correctly before wiring anything into systemd. Test a low-stakes command, something like asking it to list files in a scratch directory, before trusting it with anything real.

Sandboxing with Docker: The Step Most Guides Skip

Here’s a scenario worth sitting with. You give Hermes local terminal access on your production web server because it’s faster to set up, and it works fine for weeks. Then, during a routine skill-creation cycle, the agent writes and executes a script that assumes it has write access to /var/www, because nothing told it otherwise. Nothing malicious happened; the agent just didn’t know the boundary existed. That’s the actual risk profile of autonomous agents with local execution, not science-fiction rogue AI, but ordinary permission scope creep.

Docker-based sandboxing solves this cleanly by giving the agent an isolated container to operate in in place of your host filesystem.

Install Docker:

sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker hermes

Log the hermes user out and back in, or apply the group change immediately without a full logout:

newgrp docker

Verify Docker is usable without sudo:

docker run hello-world

Then point Hermes at Docker as its terminal backend, either during hermes setup or by reconfiguring afterward:

hermes config set terminal-backend docker

Ubuntu 26.04 ships Docker Engine 29 in its repositories by default, which brings meaningfully better container startup times and improved cgroup v2 handling compared to what shipped alongside 24.04, something worth knowing if you’re benchmarking agent response latency.

Running Hermes as a systemd Service

An interactive hermes session dies the moment your SSH connection drops unless you’re running it inside tmux or screen, which is a fragile way to run anything you actually depend on. systemd is the correct tool here, and it’s the difference between “usually running” and “always running.”

Create the unit file:

sudo nano /etc/systemd/system/hermes.service

Paste the following, adjusting the path to match your installation:

[Unit]
Description=Hermes Agent Gateway
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service

[Service]
Type=simple
User=hermes
Group=hermes
WorkingDirectory=/home/hermes
ExecStart=/home/hermes/.local/bin/hermes gateway
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/hermes/.hermes
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Confirm the actual path to the hermes binary before saving, since installer versions have varied this slightly:

which hermes

Then enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now hermes
sudo systemctl status hermes

The hardening directives in that unit file (ProtectSystem=strict, ProtectHome=read-only, NoNewPrivileges=true) aren’t decoration. They tell the kernel to deny the Hermes process write access to most of the filesystem except the paths you explicitly allow, which is a meaningful second layer of defense on top of Docker sandboxing, not a replacement for it.

Watch the logs in real time the same way you’d watch any other systemd-managed service:

sudo journalctl -u hermes -f

Connecting a Messaging Gateway

If the goal is reaching Hermes from Telegram, Discord, Slack, WhatsApp, or Signal instead of a bare terminal, enable the gateway:

hermes gateway

This is what the systemd unit above actually launches as its ExecStart command, so once the service is running under systemd, the gateway comes up automatically on every boot without manual intervention.

Security Hardening Beyond the Basics

Firewall Configuration

Hermes doesn’t need any inbound ports open by default for the messaging-gateway model, since it’s making outbound connections to Telegram, Slack, or your model provider’s API rather than listening for inbound traffic. Lock the firewall down accordingly:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable
sudo ufw status verbose

If you’re also running a local web dashboard or exposing an API for custom integrations, only open that specific port and restrict it to trusted IP ranges rather than opening it to the world.

API Key Storage

Never commit API keys to a git repo, and don’t rely on shell history for them either. Hermes stores provider credentials in its configuration under ~/.hermes/; lock that directory down:

chmod 700 ~/.hermes
chmod 600 ~/.hermes/config.yaml

Rotate keys periodically, and if you’re running Hermes for a client, use separate API keys per deployment so a compromised key on one server doesn’t expose usage across every environment you manage.

Keep the System Patched

Autonomous agents that execute code are a bigger blast radius than most services if the underlying OS has an unpatched privilege escalation bug. Set up unattended security upgrades:

sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Review Hermes updates too. New skill-execution features occasionally ship with expanded default permissions, so read release notes before blindly upgrading a production deployment.

Performance Tuning Notes

For CPU-bound workloads, particularly if you’re running local models via Ollama alongside Hermes, check whether the CPU governor is set to performance rather than powersave, since many cloud VPS images default to the latter:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
sudo cpupower frequency-set -g performance

For memory, Hermes’s persistent memory store grows over time as it accumulates skills and conversation history. Monitor it:

du -sh ~/.hermes/memory

If it balloons unexpectedly, that’s usually a sign the agent is logging excessive tool output rather than summarizing it, worth checking in the config.

For disk I/O, if you’re running multiple isolated agents via Docker on the same host, put the Docker data root on a separate volume from your OS disk where possible, since container image layers and volumes can generate surprising I/O contention under concurrent agent workloads.

On the network side, if the agent is calling out to a cloud LLM provider on every message, latency is dominated by that round trip, not your local infrastructure. Running a local model through Ollama trades network latency for CPU/GPU load, which is the right tradeoff on data-sensitive workloads but the wrong one if raw response speed matters more.

Troubleshooting Common Installation Errors

hermes: command not found after installation. This almost always means your shell’s PATH wasn’t updated. Confirm the binary exists and manually add it:

ls -la ~/.local/bin/hermes
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Installer fails partway through with a Python or uv error. This is typically a stale or conflicting Python installation interfering with the isolated environment the installer tries to build. Clear the partial install and retry:

rm -rf ~/.hermes ~/.local/share/hermes
bash install.sh

hermes setup hangs on the Nous Portal device-code login. This is a network egress issue nine times out of ten. Confirm outbound HTTPS isn’t blocked:

curl -I https://portal.nousresearch.com

If that times out, check your ufw outbound rules or, on a cloud VPS, the provider’s security group settings.

Docker terminal backend fails with a permission denied error. This means the group membership change from usermod -aG docker hasn’t taken effect in the current session. Log out completely and back in rather than relying on newgrp inside a script, since some shells don’t propagate the group change to subprocesses correctly.

systemd service starts then immediately exits. Check the exit code and logs together:

sudo systemctl status hermes
sudo journalctl -u hermes -n 50 --no-pager

The most common cause is an incorrect WorkingDirectory or ExecStart path in the unit file after an update changed where the binary lives. Re-run which hermes as the hermes user and update the unit file accordingly.

Agent runs but ignores messaging gateway input. Double check the gateway process is actually the one systemd launched and not a leftover manual session competing for the same webhook or polling connection. Kill any stray manual hermes gateway processes:

ps aux | grep hermes
r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.

Related Posts