# Remote Gateway — pointing Hermes Desktop at the VPS backend

Session-verified detail from configuring the Surface tablet's Desktop app (2026-07-19). The main task: repoint a Windows Desktop install from its default **local gateway** (its own bundled backend on 127.0.0.1:91xx) to the VPS backend at `https://2.25.172.164`.

## The verified working topology (Connie, working)

```
Desktop app (Remote gateway mode)
  → https://2.25.172.164            (bare URL, no path — this exact string goes in the field)
  → nginx :443                       (site: /etc/nginx/sites-enabled/robblake.cloud, self-signed cert for the raw IP)
  → proxy_pass http://127.0.0.1:9119 (hermes dashboard process — PID from `ss -tlnp | grep 9119`)
```

So the "remote gateway" the Desktop app talks to **is the dashboard's backend** (`hermes dashboard --port 9119` on the VPS), NOT the messaging gateway (`hermes gateway run`) and NOT a separately-enabled API server. Auth is a **dashboard session token** (the settings screen shows the saved token masked, e.g. `...AXXY`, once the URL responds).

Do not confuse with the **API server** feature (`API_SERVER_ENABLED`, port 8642, OpenAI-compatible `/v1/*`) — that is a *different* client surface for Open WebUI-style frontends. The Desktop app's Remote gateway field does not use it. Enabling 8642 is NOT required for Desktop remote mode and was correctly abandoned mid-task once the nginx/dashboard path was identified.

## The settings screen (what the user sees)

Settings → Gateway Connection → two cards: **Local gateway** (default, "works offline") / **Remote gateway** ("control an already-running Hermes backend"). Remote gateway selected reveals:

- **Remote URL** — "Base URL for the remote dashboard backend. Path prefixes are supported, for example /hermes."
- **Session token** — "The dashboard session token used for REST and WebSocket access. Leave blank to keep the saved token." The field only appears AFTER the URL responds to the app's probe ("auth method will appear once it responds").
- Buttons: **Test remote** / **Save for next restart** / **Save and reconnect**.
- Diagnostics section → **Open logs** (reveals desktop.log in Explorer).

## Diagnostic map — what failed vs what it meant

| Symptom | Real cause | Fix |
|---|---|---|
| Browser on new device: `NET::ERR_CERT_AUTHORITY_INVALID` loading `https://2.25.172.164` | Device doesn't trust the Hermes VPS root cert (self-signed for raw IP) | Copy `C:\ProgramData\Hermes\hermes-vps-root.crt` from Connie → new device → `Import-Certificate -FilePath ... -CertStoreLocation Cert:\LocalMachine\Root` (ADMIN). Browser then loads clean. |
| App: "could not reach gateway yet, Check the url — auth method will appear once it responds" — AFTER cert installed and browser loads the UI | **App version too old.** Surface was Desktop 0.16.0; Connie (working) was 0.18.2. The remote-gateway probe logic in 0.16.0 fails against this dashboard. (Also note: the failing version's UI has only Local/Remote cards; current versions add a third **Hermes Cloud** card — Nous-hosted, not for VPS-SSOT setups.) | Settings → Updates → Update now (in-app updater; 1200-change batch is normal Electron backlog). After update + restart, redo the remote setup. If versions ALREADY match and it still fails: get the RENDERER error — focus app window → Ctrl+Shift+I (devtools) → Console tab → click "Test remote" → read the red error. desktop.log alone is a dead end for this class of failure. |

## Diagnostic lessons (the durable ones)

1. **desktop.log only shows backend events.** Every line in a remote-mode failure tail was still `[boot] Starting Hermes backend ... 127.0.0.1:912x` — local boot cycles. Absence of remote evidence ≠ remote not attempted; the probe lives in the renderer. Go to devtools Console early, not as a last resort.
2. **Check the user's working device FIRST.** Asking "what does Connie's Remote URL field say, character-for-character?" short-circuited the entire wrong path (API server on 8642). If one client works, diff against it before building anything new.
3. **Verify the server side answers client probes:** `for p in /api/health /api/status /health /api/auth/methods; do curl -sk -o /dev/null -w "%{http_code} $p\n" https://127.0.0.1$p; done` — 401s mean "reachable, auth-gated" = good; the VPS was answering correctly the whole time.
4. **Cert transport across devices:** the Syncthing vault is the bridge (drop .crt in `Personal/`, appears on the other Windows device in seconds). Delete from the vault after install. Never paste tokens/keys in chat — same vault-drop pattern with immediate cleanup for the session token.
5. **Renderer devtools on Windows Electron:** Ctrl+Shift+I with the app focused. Console tab. If the app locks devtools, fall back to asking the user for the exact on-screen error text verbatim.

## New-device checklist (Desktop app → VPS remote)

0. **Version check FIRST**: Settings → About. Must match the working device's major.minor (0.18.x verified working; 0.16.0 verified FAILING the probe). Update via Settings → Updates → Update now before anything else.
1. Browser test: `https://2.25.172.164` → if cert error, install root cert to LocalMachine\Root (ADMIN), retest.
2. Settings → Gateway Connection → Remote gateway (NOT Hermes Cloud — that's the Nous-hosted option added in newer versions) → URL `https://2.25.172.164` (bare).
3. Token: same dashboard session token as the working device — transferred out-of-band (vault temp file, deleted after), never via chat.
4. **Test remote** → green → **Save and reconnect**.
5. If "could not reach gateway yet" with matching versions + clean browser test: devtools Console for the renderer error.
