Skip to content

Install Guide: Hermes + Tailscale on VPS

Setting Up Hermes Agent with Tailscale on Hetzner

Architecture: Hermes Agent runs on Hetzner VPS under dedicated user hermes, accessible only via Tailscale WireGuard tunnel (UDP 41641). Public SSH (TCP 22) is blocked at Hetzner Firewall level.

Your Laptop (Tailscale) ---- Tailnet (WireGuard) ----> Hetzner VPS (Tailscale)
                                                           ├── Hermes Agent (user 'hermes')
                                                           └── Gateway (Telegram/Discord/etc.)
Hetzner Firewall: ✅ UDP 41641 (Tailscale) | ❌ TCP 22 (SSH blocked publicly)

Prerequisites

Make sure you have these before you start:

Phase 1: VPS Creation

Settings to choose:

SettingRecommendation
ImageUbuntu 24.04 or Debian 12
TypeCX22 (2 vCPU, 4GB RAM, €4/mo) or ARM64 CAX11 (€4/mo)
SSH KeyAdd during creation — critical for initial access
NetworkingDefault public IPv4/IPv6 enabled

Note the public IP — you’ll need it for initial setup.

Phase 2: Initial System Setup (as root)

SSH in as root using the public IP Hetzner gave you:

# Update system
apt update && apt upgrade -y

# Create dedicated user
adduser hermes
usermod -aG sudo hermes

# Copy SSH key to new user
mkdir -p /home/hermes/.ssh
cp /root/.ssh/authorized_keys /home/hermes/.ssh/authorized_keys
chown -R hermes:hermes /home/hermes/.ssh
chmod 700 /home/hermes/.ssh
chmod 600 /home/hermes/.ssh/authorized_keys

⚠️ Critical: Keep this root session open. Test the new user in a second terminal before closing it.

Verify access in your second terminal:

ssh hermes@<public-ip>
sudo whoami  # Should output: root

Harden SSH (back in root session)

nano /etc/ssh/sshd_config

Set these values:

PermRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Restart SSH:

systemctl restart sshd

Verify hermes user still works, then close root session.

Phase 3: Install Tailscale (BEFORE Firewall)

🚨 CRITICAL: Install and verify Tailscale BEFORE applying Hetzner firewall or you’ll be locked out of your own server.

As hermes user:

# Install
curl -fsSL https://tailscale.com/install.sh | sh

# Authenticate
sudo tailscale up
# Visit the printed URL to authorize your device

# Get Tailscale IP
tailscale ip -4
# Returns: 100.x.y.z  (remember this)

Verify SSH over Tailscale

From your local machine:

ssh hermes@100.x.y.z

Do not proceed until this works. If you can’t SSH via Tailscale IP, do not apply the firewall rules yet.

Phase 4: Lock Down Firewall

In Hetzner Console

Go to Firewalls, then Create Firewall.

  1. Delete all default rules (remove pre-populated SSH/ICMP rules)
  2. Add this single inbound rule:
ProtocolPortSourcePurpose
UDP416410.0.0.0/0, ::/0Tailscale WireGuard direct connections

Apply to server (hermes-vps).

Verification

From local machine — public SSH should now fail:

# This should timeout or refuse
ssh -o ConnectTimeout=5 hermes@<public-ip>

Tailscale SSH should still work:

# This should connect instantly
ssh hermes@100.x.y.z

Phase 5: Install Hermes Agent

As hermes user over Tailscale SSH:

# Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
source ~/.bashrc

# Configure LLM provider
hermes setup
# Options: OpenRouter (200+ models, free tier), Nous Portal (OAuth), OpenAI/Anthropic

# Test
hermes
hermes doctor  # Run diagnostics

Management Commands

hermes model    # Switch provider/model
hermes tools    # Enable/disable tools
hermes update   # Update agent (preserves config/memory/skills)

Phase 6: Messaging Gateway (Optional)

For Telegram/Discord/Slack integration:

# Configure platforms
hermes gateway setup
# For Telegram: need Bot Token from @BotFather

# Install as systemd user service
hermes gateway install

# Enable persistent boot (run even when not logged in)
sudo loginctl enable-linger hermes

# Manage service
systemctl --user start hermes-gateway
systemctl --user enable hermes-gateway
journalctl --user -u hermes-gateway -f  # View logs

Phase 7: Automatic Security Updates

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades  # Select Yes

Optional auto-restart for kernel updates:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Uncomment:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

Quick Reference

TaskCommand
SSH Accessssh hermes@100.x.y.z (Tailscale IP only)
Start Hermes CLIhermes
Change Modelhermes model
Configure Toolshermes tools
Start Gatewayhermes gateway
Gateway Logsjournalctl --user -u hermes-gateway -f
Diagnosticshermes doctor
Update Hermeshermes update
Tailscale Statustailscale status

Security Layers

LayerProtectionImplementation
NetworkSSH accessHetzner Firewall blocks TCP 22; only UDP 41641 allowed
TunnelWireGuard encryptionTailscale handles key rotation, NAT traversal
OSDedicated unprivileged userhermes user with sudo for specific commands
ApplicationLeast-privilege API tokensRead-only Calendar, no admin GitHub scopes

Back to the blog post