Hermes Agent Production Deployment Guide 2026: From Local Experiment to Always-On Service

TL;DR: Deploy Hermes Agent in production with Docker for isolation, systemd for auto-restart, environment config files for secrets, nginx as a reverse proxy, health checks for monitoring, automated backups of the SQLite database, and unattended security updates. This guide covers the full production-hardened setup.

Why Production Deployment Matters

Running Hermes Agent locally for development is straightforward. Running it as a production service โ€” always on, always available, recoverable from failures โ€” requires a different approach. This guide covers the seven pillars of production deployment: containerization, process management, configuration, networking, monitoring, updates, and backups.

1. Docker Deployment

Docker provides consistent environments across machines and simplifies dependency management. Here's the production Docker setup:

class="language-dockerfile">FROM python:3.11-slim

WORKDIR /app
RUN pip install hermes-agent

COPY config.yaml /app/config.yaml
COPY .env /app/.env

EXPOSE 8443
CMD ["hermes", "run"]
class="language-bash"># Build and run
docker build -t hermes-agent:latest .
docker run -d \
 --name hermes \
 --restart unless-stopped \
 -v hermes_data:/home/hermes/.hermes \
 -p 127.0.0.1:8443:8443 \
 hermes-agent:latest

Key choices: bind to 127.0.0.1 (not 0.0.0.0) so the agent only listens locally โ€” the reverse proxy handles external traffic. Mount a named volume for .hermes to persist the SQLite database, skills, and conversation history across container restarts.

2. systemd Service (Without Docker)

If you prefer running Hermes directly on the host instead of Docker, systemd handles automatic restarts:

class="language-ini">[Unit]
Description=Hermes Agent
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=hermes
WorkingDirectory=/home/hermes/.hermes
EnvironmentFile=/home/hermes/.hermes/.env
ExecStart=/home/hermes/.local/bin/hermes run
Restart=always
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
class="language-bash">sudo systemctl enable hermes
sudo systemctl start hermes
sudo systemctl status hermes

The Restart=always directive ensures Hermes restarts after crashes or server reboots. The RestartSec=10 pause prevents rapid restart loops.

3. Environment Configuration

Never store secrets in config.yaml. Use a separate .env file with restricted permissions:

class="language-bash">chmod 600 /home/hermes/.hermes/.env
class="language-env"># ~/.hermes/.env
OPENAI_API_KEY=sk-proj-abc123
ANTHROPIC_API_KEY=sk-ant-xyz789
TELEGRAM_BOT_TOKEN=123456:ABC-DEF
HERMES_WEBHOOK_SECRET=whsec_yoursecret

Hermes reads the .env file automatically at startup. For Docker deployments, pass secrets via Docker secrets or a secrets manager like HashiCorp Vault.

4. Reverse Proxy (Nginx)

Expose Hermes's webhook endpoint securely behind nginx with TLS termination:

class="language-nginx">server {
 listen 443 ssl;
 server_name agent.yourdomain.com;

 ssl_certificate /etc/letsencrypt/live/agent.yourdomain.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/agent.yourdomain.com/privkey.pem;

 location /webhook/ {
 proxy_pass http://127.0.0.1:8443;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 }

 # Health check endpoint
 location /health {
 proxy_pass http://127.0.0.1:8443/health;
 access_log off;
 }
}

Use Certbot for automatic Let's Encrypt certificate renewal. The /health endpoint is used by monitoring tools to verify the agent is responding.

5. Monitoring

Set up basic health checking to detect when the agent stops responding:

class="language-bash">#!/bin/bash
# /usr/local/bin/check-hermes.sh
if ! curl -sf http://127.0.0.1:8443/health; then
 systemctl restart hermes
 echo "Hermes restarted at $(date)" >> /var/log/hermes-restarts.log
fi
class="language-bash"># Run every 5 minutes via cron
*/5 * * * * /usr/local/bin/check-hermes.sh

For more comprehensive monitoring, forward Hermes logs to a centralized system:

class="language-bash">hermes config set logging.format json
hermes config set logging.webhook_url "https://logs.example.com/ingest"

Monitor these key metrics: cache hit rate, average response time, error rate, and memory usage.

6. Auto-Updates

Keep Hermes updated with unattended security updates and a scheduled update check:

class="language-bash"># Unattended upgrades for the OS
apt install unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades

# Weekly Hermes update check via cron
0 3 * * 0 hermes update --check >> /var/log/hermes-updates.log 2>&1

For Docker deployments, set up a Watchtower container to automatically pull and restart updated images:

class="language-bash">docker run -d \
 --name watchtower \
 -v /var/run/docker.sock:/var/run/docker.sock \
 containrrr/watchtower \
 --interval 86400

7. Backup Strategy

Hermes stores everything in a SQLite database at ~/.hermes/data/memory.db. Back this up daily:

class="language-bash">#!/bin/bash
# /usr/local/bin/backup-hermes.sh
BACKUP_DIR="/backups/hermes"
mkdir -p "$BACKUP_DIR"
DATE=$(date +%Y%m%d-%H%M%S)

# Backup the SQLite database
sqlite3 ~/.hermes/data/memory.db ".backup '$BACKUP_DIR/memory-$DATE.db'"

# Keep only last 30 days of backups
find "$BACKUP_DIR" -name "memory-*.db" -mtime +30 -delete

# Optional: sync to remote storage
# rclone sync "$BACKUP_DIR" s3://hermes-backups/
class="language-bash"># Run daily at 2 AM
0 2 * * * /usr/local/bin/backup-hermes.sh

Test backups regularly by restoring to a staging environment. SQLite backups are consistent and can be restored by simply replacing the memory.db file.

Deployed Hermes in production? Share your setup in the comments or tag us on X. For more on automation, see our automation workflows guide and security best practices.

Tags: Hermes, Agents, Guides, Deployment

Tool: Hermes Agent / Docker / systemd / nginx / Caddy

โ† Back to all posts