# Hermes Dashboard — Tailscale-Bound Deployment

**Last updated:** 2026-06-12 by Hermes (session: dashboard access from laptop)

## How Rocky accesses it from his laptop

URL: **http://100.116.48.82:9119**
- Laptop (100.108.207.15) and server (100.116.48.82) are both on Tailscale — traffic is encrypted peer-to-peer, no port forwarding needed
- Auth: username `admin`, password stored in `~/.hermes/.env` as `HERMES_DASHBOARD_BASIC_AUTH_PASSWORD`
  - Run `grep DASHBOARD /root/.hermes/.env` on the server to retrieve it, or ask Hermes
- Browser will redirect to `/login` — enter admin credentials there

## The right way to start the dashboard

**Never** `hermes dashboard --host 0.0.0.0` — exposes the UI on every interface.

**Correct pattern:**
```bash
# 1. Set auth via env vars BEFORE starting
# In ~/.hermes/.env:
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=<strong-password>
HERMES_DASHBOARD_BASIC_AUTH_SECRET=<openssl rand -base64 32>

# 2. Start bound to Tailscale IP only
hermes dashboard --host <tailscale-ip> --port 9119 --no-open
```
- `--no-open` — don't try to open a browser on the server
- Auth is mandatory — non-loopback bind fails closed without it
- Tailscale encrypts all traffic end-to-end, so binding to the Tailscale IP only is the right surface area

## Systemd unit (current — already deployed)
Location: `/etc/systemd/system/hermes-dashboard.service`

```ini
[Unit]
Description=Hermes Agent Web Dashboard
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/bin/hermes dashboard --host 100.116.48.82 --port 9119 --no-open
WorkingDirectory=/root
EnvironmentFile=/root/.hermes/.env
Environment="HERMES_HOME=/root/.hermes"
Restart=on-failure
RestartSec=30
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=90
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

Key points:
- `EnvironmentFile=/root/.hermes/.env` — picks up the basic auth vars
- `Restart=on-failure` — survives crashes
- `Enabled at boot` — `systemctl enable hermes-dashboard`

## Commands

```bash
# Restart after config change
systemctl restart hermes-dashboard

# Check status
systemctl status hermes-dashboard

# Follow logs
journalctl -u hermes-dashboard -f

# Enable at boot
systemctl enable hermes-dashboard
```

## Verify auth is engaging
```bash
curl -I http://100.116.48.82:9119
# Expected: HTTP/1.1 302 Found + location: /login?next=%2F
# If HTTP 200: auth is NOT enabled — check HERMES_DASHBOARD_BASIC_AUTH_* vars in .env
```

## Common failure modes
| Symptom | Cause | Fix |
|---|---|---|
| Dashboard won't start | Auth not set | Set the three HERMES_DASHBOARD_BASIC_AUTH_* vars in .env |
| `0.0.0.0` bind refused | Non-loopback bind without auth | Auth vars must be set before bind |
| Dashboard dies on reboot | Not enabled | `systemctl enable hermes-dashboard` |
| Port not listening | PID different than expected | `ss -tlnp \| grep 9119` to confirm bind |
| Browser shows "site can't be reached" from laptop | Laptop not on Tailscale, or wrong IP | Ensure laptop is on Tailscale; check server Tailscale IP with `tailscale ip -4` |