# Hermes Remote Gateway

> Set up Hermes Desktop to connect to a remote Hermes gateway. Covers Dashboard vs API Server distinction, authentication, firewall, and common pitfalls.

- Skill: `tyrantlucifer/hermes-remote-gateway` (Agent Skill)
- Install (CLI): `npx skillmds@latest add tyrantlucifer/hermes-remote-gateway`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tyrantlucifer/hermes-remote-gateway/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: TyrantLucifer (https://skillmd.com/u/tyrantlucifer)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tyrantlucifer/hermes-remote-gateway

---


# Hermes Remote Gateway Setup

Connect **Hermes Desktop** (thin local GUI) to a remote Hermes instance running on a VPS/server.

## ⚠️ Critical Distinction: Dashboard vs API Server

**Hermes has TWO separate HTTP surfaces. Desktop connects to the Dashboard, NOT the API Server.**

| Surface | Default Port | Endpoint Desktop Probes | Purpose |
|---------|-------------|------------------------|---------|
| **Dashboard** | 9119 | `/api/status` | Web admin UI + Desktop connection endpoint |
| **API Server** | 8642 | `/health`, `/v1/models` | OpenAI-compatible API for programmatic access |

**Desktop's connection flow:**
1. User enters URL in Desktop settings
2. Desktop probes `GET /api/status` on that URL
3. If reachable → reads `auth_required` + `auth_providers` from response
4. Shows auth UI (basic auth username/password, or OAuth login button)
5. Connects via WebSocket at `/api/ws`

**If you enable only the API Server (port 8642) and point Desktop at it, you'll see:**
> "Could not reach this gateway yet. Check the URL — the auth method will appear once it responds."

This is because `/api/status` returns 404 on the API Server — it only exists on the Dashboard.

## Architecture

```
[Mac/Desktop]  ──HTTP──▶  [VPS:9119]  ──▶  [Hermes Dashboard]
  Hermes Desktop            Dashboard         ├─ /api/status (probe)
   (Electron)                (Web UI)         ├─ /api/ws (WebSocket)
                                              └─ serves web admin panel

[Mac/Scripts]  ──HTTP──▶  [VPS:8642]  ──▶  [Hermes API Server]
  curl / Codex / etc.       API Server        ├─ /v1/chat/completions
   (OpenAI-compatible)      (platform)        ├─ /v1/models
                                              └─ /health
```

## Step-by-Step Setup

### 1. Start the Dashboard on the remote host

```bash
# Start dashboard bound to all interfaces (for remote access)
hermes dashboard --host 0.0.0.0 --port 9119
```

For persistent operation, run in background or via systemd:
```bash
# Background (inside tmux/screen)
hermes dashboard --host 0.0.0.0 --port 9119 &

# Or use terminal tool with background=true in Hermes
```

**Note:** The first launch builds the web UI (`vite build`), which takes ~30-60 seconds. Subsequent starts are instant.

### 2. Configure authentication

Dashboard uses **basic auth** by default. Check your config:

```bash
grep -A5 "basic_auth" ~/.hermes/config.yaml
```

You should see:
```yaml
basic_auth:
  username: <your-username>
  password_hash: scrypt$...
  secret: <random-string>
```

If not configured, run `hermes setup` or manually set in `config.yaml`.

### 3. Open firewall

Ensure port 9119 is open for TCP inbound:

```bash
# UFW
sudo ufw allow 9119/tcp

# iptables
sudo iptables -A INPUT -p tcp --dport 9119 -j ACCEPT

# Cloud provider security groups — add inbound rule for TCP 9119
```

### 4. Verify

```bash
# On the server — check port is listening
ss -tln | grep 9119

# Test the endpoint Desktop will probe
curl -s http://localhost:9119/api/status | python3 -m json.tool
```

Expected response:
```json
{
  "version": "0.17.0",
  "gateway_running": true,
  "gateway_state": "running",
  "auth_required": true,
  "auth_providers": ["basic"],
  ...
}
```

### 5. Connect Desktop

On your local machine:

```bash
# If npm registry is wrong (corporate env), override:
npm_config_registry=https://registry.npmjs.org hermes desktop

# Or fix permanently for Hermes builds:
npm config set registry https://registry.npmjs.org
hermes desktop
```

In Desktop Gateway Connection settings:
1. Select **"Remote gateway"**
2. **Remote URL:** `http://<VPS_IP>:9119`
3. Click **"Test remote"** — should show green/checkmark
4. Enter **username** and **password** (from your basic_auth config)
5. Click **"Save and reconnect"**

## Optional: Also Enable API Server

If you also want programmatic OpenAI-compatible access (for scripts, Codex, etc.):

```bash
# Add to ~/.hermes/.env
API_SERVER_ENABLED=true
API_SERVER_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
API_SERVER_HOST=0.0.0.0
API_SERVER_PORT=8642
```

Then restart gateway from a separate SSH session:
```bash
hermes gateway restart
```

**This is separate from Desktop connectivity.** Desktop does NOT use the API Server for its connection.

## Pitfalls

### Desktop says "Could not reach this gateway yet"

**Cause:** You're pointing at the API Server (port 8642) instead of the Dashboard (port 9119).

**Fix:** Use `http://<host>:9119` — the Dashboard serves `/api/status` which Desktop needs.

### Gateway/Dashboard can't restart from inside itself

`hermes gateway restart` and `systemctl --user restart hermes-gateway` are **blocked when called from inside the gateway process** (SIGTERM propagates to child). Open a **separate SSH session** to restart.

### Dashboard not running after server reboot

The dashboard is NOT a systemd service by default. It's a one-shot process. To make it persistent:

```bash
# Option 1: tmux session
tmux new-session -d -s dashboard 'hermes dashboard --host 0.0.0.0 --port 9119'

# Option 2: Create a systemd user service
# (see hermes-migration skill or docs for service template)
```

### Corporate npm registry blocks Electron build

If `hermes desktop` fails with `E404` on packages like `@codemirror/autocomplete`, your npm registry is pointed at an internal/corporate registry. Fix with:

```bash
npm_config_registry=https://registry.npmjs.org hermes desktop
```

Common in enterprise networks that require an internal npm mirror. Replace the registry URL with the one provided by your organization.

### API Server not listening after enabling

If `ss -tln | grep 8642` shows nothing after restart:
1. Check `.env` has `API_SERVER_ENABLED=true` (not just `API_SERVER_KEY`)
2. Check gateway logs: `journalctl --user -u hermes-gateway --no-pager -n 30`
3. The API Server only starts if either `API_SERVER_ENABLED=true` OR `API_SERVER_KEY` is set

### Security considerations

- Dashboard with basic auth = anyone with credentials can control your Hermes agent
- API Server with a key = anyone with the key can run tools on your server
- Use strong random keys (32+ bytes, urlsafe)
- Consider SSH tunnel instead of opening ports publicly:
  ```bash
  ssh -L 9119:localhost:9119 -L 8642:localhost:8642 user@vps
  ```
- Then connect Desktop to `http://localhost:9119`

## Config Reference

### Dashboard env vars

| Env Var | Default | Description |
|---------|---------|-------------|
| (none special) | — | Dashboard reads from `config.yaml` for auth |

Dashboard CLI flags: `--host`, `--port`, `--insecure` (deprecated), `--skip-build`, `--isolated`, `--stop`, `--status`.

### API Server env vars (from `gateway/config.py`)

| Env Var | Default | Description |
|---------|---------|-------------|
| `API_SERVER_ENABLED` | false | Enable the API Server platform |
| `API_SERVER_KEY` | (empty) | Auth key (also enables the server if set) |
| `API_SERVER_HOST` | 127.0.0.1 | Listen address |
| `API_SERVER_PORT` | 8642 | Listen port |
| `API_SERVER_CORS_ORIGINS` | (empty) | Comma-separated allowed origins |
| `API_SERVER_MODEL_NAME` | (empty) | Override model name in /v1/models |

