# Deploy walkthrough — chat.saiden.dev (token-based) End-to-end, in order. Each step has a verification. ## 1 — Sync repo to junkpile From fuji: ```bash rsync -avz --exclude='.git' ~/Projects/chat-saiden/ junkpile:~/chat-saiden/ ``` ## 2 — Install on junkpile ```bash ssh junkpile 'bash ~/chat-saiden/install.sh' ``` What it does: - Installs `ttyd` via brew (idempotent, robust to caveats exit codes) - Drops the wrapper to `~/.local/bin/ttyd-wrapper.sh` - Installs both systemd units to `/etc/systemd/system/` - Stages `/etc/cloudflared/chat-saiden.env` with a PLACEHOLDER token (mode 0640 root:chi) **Verify:** ```bash ssh junkpile 'ttyd --version; ls -l ~/.local/bin/ttyd-wrapper.sh /etc/systemd/system/ttyd-chat.service /etc/systemd/system/cloudflared-chat-saiden.service /etc/cloudflared/chat-saiden.env' ``` ## 3 — Create tunnel + Access app in CF Zero Trust dashboard Browser-only. Follow **`cloudflare/dashboard-setup.md`** end-to-end: - Part A: create `chat-saiden` tunnel, copy token, add public hostname `chat.saiden.dev → http://localhost:7681` - Part B: create Access application `chat-saiden`, bind to Google IdP, add whitelist policy with `adam.ladachowski@gmail.com` - Part B step 3: **enable WebSocket support** (mandatory) - Part C: skip if Google IdP already configured ## 4 — Paste token ```bash ssh junkpile 'sudo $EDITOR /etc/cloudflared/chat-saiden.env' # Replace PLACEHOLDER_REPLACE_ME with the long token from the wizard ``` **Verify:** ```bash ssh junkpile 'sudo grep -c "PLACEHOLDER" /etc/cloudflared/chat-saiden.env' # Should print 0 (no placeholder left) ``` ## 5 — Start ttyd locally and smoke-test ```bash ssh junkpile 'sudo systemctl enable --now ttyd-chat && systemctl status ttyd-chat --no-pager | head -10 && curl -sI http://localhost:7681 | head -3' ``` Look for: `Active: active (running)` and `HTTP/1.1 200 OK`. ## 6 — Start tunnel ```bash ssh junkpile 'sudo systemctl enable --now cloudflared-chat-saiden && journalctl -u cloudflared-chat-saiden -n 20 --no-pager' ``` Look for "Registered tunnel connection" lines (typically 4 connections to different CF colos). ## 7 — End-to-end live test ⚠ **Pilot verification gate.** From your laptop, fresh incognito: 1. Visit `https://chat.saiden.dev` 2. CF Access wall → Google → `adam.ladachowski@gmail.com` 3. Land on BT banner + `claude` prompt ⚠ **Whitelist verification.** Second incognito, non-whitelisted Google account: - Must be **denied** at Access wall. - If you land on the terminal, the policy is wrong — **kill the units immediately**: ```bash ssh junkpile 'sudo systemctl stop cloudflared-chat-saiden ttyd-chat' ``` Then recheck the policy in the dashboard. ## Rollback ```bash ssh junkpile 'sudo systemctl disable --now cloudflared-chat-saiden ttyd-chat' ``` Tunnel + DNS stay (managed in dashboard) — to fully remove, delete the tunnel in the CF Zero Trust dashboard (Networks → Tunnels → chat-saiden → Delete). ## Operational notes - **Per-tab sessions.** Each browser tab spawns a fresh `claude` process — no shared in-process state. EEMS-stored memories are visible to all sessions. - **5-min idle disconnect default.** Closing the tab kills `claude`. Add `-t reconnect=10` to the ttyd unit if you want browser-side reconnect attempts (note: a fresh `claude` process spawns — conversation context is lost). - **Token rotation.** Dashboard → tunnel → Refresh token. Edit env file, restart unit.