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.
If you are weighing Hermes Agent against the alternatives, our comparison database keeps a live scorecard of how the leading AI Agent tools stack up.
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.
Docker resource limits keep a runaway agent from starving the host. Add --memory 2g --cpus 2 to the docker run command to cap memory and CPU usage. If the agent exceeds the memory limit, Docker kills the container and the --restart unless-stopped policy brings it right back — a cheap guardrail that turns worst-case behavior into a recoverable restart instead of an outage.
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.
Beyond TLS, harden the proxy with rate limiting and security headers. A limit_req_zone directive throttles repeated requests to the webhook endpoint, which helps blunt brute-force or replay attempts. Adding headers like X-Content-Type-Options: nosniff is cheap defense-in-depth for a service that is reachable from the public internet. None of this replaces authentication — the webhook secret in .env is the real gate — but it raises the cost of probing the endpoint and slows down scripted attacks.
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
Dig deeper: Hermes Agent review · Copy.ai review.
📖 Related Reads
- Hermes Tutorials — Hermes Agent setup, configuration, and advanced workflows
- NoCode Insider — AI workflow automation with no-code tools, agents, and APIs
- ToolBrain — tool reviews, LLM comparisons, and AI workflow guides
- NiteAgent — AI agent development, frameworks, and production patterns
Cross-links automatically generated from None.
Back to all posts