GWR Delay Repay — Viewer Setup (Mac / Linux)

How to connect a VNC viewer from a workstation (Mac, pomelo) to the ephemeral GWR browser host over stunnel (mutual-TLS). Parent: delayrepay. The host itself is provisioned from kelp via Ansible.

Runnable version (execute the enrol/connect steps from the note): delayrepay/viewer-setup/run.

How it works

Each browser host is its own CA: its self-signed server cert doubles as the CA that signs your pre-registered client CSR, so every provision mints you a fresh per-host cert. The host publishes your cert + the CA to WebDAV; the client downloads them (once — the client cert is deleted from WebDAV after fetch), configures stunnel, and connects. Your private key never leaves your machine.

Transport: your stunnel client (localhost:5902) → host:15901 (mTLS, verify=2) → the host's VNC on :1. The SG opens 15901 to the world — safe, because mTLS rejects anyone without a CA-signed client cert.

One-time enrolment (per machine)

Do this once on each workstation (Mac, pomelo). It installs stunnel, makes a key + CSR (CN and SAN = the short hostname), and registers the CSR on kelp. The private key stays local; only the CSR travels.

# 1. install stunnel
brew install stunnel            # macOS
sudo apt install stunnel4       # Debian / pomelo

# 2. generate key + CSR (CN + subjectAltName = short hostname, no domain)
H=$(hostname -s)
mkdir -p ~/.gwr-viewer
openssl req -newkey rsa:2048 -nodes \
  -keyout ~/.gwr-viewer/"$H".key -out ~/.gwr-viewer/"$H".csr \
  -subj "/CN=$H" -addext "subjectAltName=DNS:$H"
chmod 600 ~/.gwr-viewer/"$H".key

# 3. send ONLY the CSR to kelp (the key never leaves this machine)
scp ~/.gwr-viewer/"$H".csr john@kelp.critchley.biz:/home/john/aws/viewer-csrs/

That's it — from then on, every provisioned host automatically signs your CSR. (If macOS openssl complains about -addext, it's an old LibreSSL; a config-file variant can be used instead.)

Connect (each time a host is provisioned)

# download + run the helper
curl -n -o ~/.gwr-viewer/gwr-view https://webdav.critchley.biz/delayrepay/gwr-view
chmod +x ~/.gwr-viewer/gwr-view
~/.gwr-viewer/gwr-view

gwr-view reads delayrepay/current-host.env (the current host's IP/CN/port), fetches your cert + the CA (or reuses cached ones), writes an stunnel client config, and starts stunnel on a free local port (prefers 5902).

Then open RealVNC Viewer → new connection → localhost:5902. No password (the server is SecurityTypes=None).

Notes / gotchas

Multiple hosts at once (pomelo) — gwr-enroll-host.sh

gwr-view (above) caches only ONE host's cert at a time — enrolling a new host overwrites the previous one's. On pomelo, use ~/.gwr-viewer/gwr-enroll-host.sh instead: it gives each host its own directory (~/.gwr-viewer/hosts/<host>/) and its own named stunnel section ([<host>-vnc]), so several hosts can have live tunnels from one stunnel process simultaneously. It backs up stunnel.conf before rewriting it, auto-picks a free local port, restarts stunnel, and prints the vncviewer command — it doesn't launch the viewer itself. Also on WebDAV: delayrepay/gwr-enroll-host.sh.

Where things live

version 2  ·  updated 2026-09-15  ·  tags delayrepay, vnc, stunnel, viewer, mac, pomelo