# Hermes Dashboard Setup (LFCS VPS)

## Current state (as of 2026-06-12)

- Dashboard: `hermes-dashboard.service` → bound to `100.116.48.82:9119`
- Gateway: `hermes-gateway.service` → running, PID 4030819
- Auth: basic auth enabled, login at `http://100.116.48.82:9119`
- Creds in `~/.hermes/.env` (chmod 600)

## Restarting after a gateway update

When `hermes update` restarts the gateway, the dashboard process dies (independent process). To restart:

```bash
systemctl restart hermes-dashboard
# Verify
ss -tlnp | grep 9119
curl -s -I http://100.116.48.82:9119
```

## Checking both services

```bash
systemctl status hermes-dashboard hermes-gateway --no-pager
```

## If the dashboard fails to bind

The dashboard refuses to start if `HERMES_DASHBOARD_BASIC_AUTH_SECRET` is not set in `.env` and the bind is non-loopback. Error will be logged to journal. Fix auth vars first, then `systemctl start hermes-dashboard`.

## hermes-health-snapshot.sh — stuck process investigation

**Symptom:** Process from `/usr/local/bin/hermes-health-snapshot.sh` running for days, health logs root-owned and small (2519 bytes vs normal ~5758 bytes).

**Root cause pattern:** The script uses `set -a` (export all sourced vars) + `set -u` (exit on undefined) + a MiniMax API probe to wrong endpoint (`api.minimaxi.chat` instead of `api.minimax.io`). When the probe times out or `.env` vars with special chars (base64 `=`, `+`) cause malformed assignments, `set -u` fires mid-heredoc block. The heredoc `} > "$OUT"` never closes, output file is empty/partial, chown at end never runs → file stays root-owned.

**Diagnostic:**
```bash
# Find stuck processes
ps aux | grep hermes-health | grep -v grep
ps -o pid,etime,cmd --pid $(pgrep -f hermes-health)

# Check health log file sizes (small = stuck mid-run)
ls -la /home/ccuser/opsman-work/health-log/

# Check if .env has base64 secrets with special chars (causes `set -a` corruption)
grep SECRET ~/.hermes/.env

# Check which cron fired it
journalctl -u cron --since "1 hour ago" | grep health-snapshot
```

**Fix:** Kill stuck process, fix the `.env` secret or the script's `set -u` boundary. The health probe curl uses wrong host — `https://api.minimaxi.chat` (should be `api.minimax.io`).