Files
chat/_archive-ttyd/README.md
T
2026-05-29 13:47:34 +02:00

3.0 KiB

chat-saiden

Web terminal for BT on the MARAUDER mesh. chat.saiden.dev lands a browser-native xterm.js session on claude CLI (bt7274 cart) running on junkpile, gated by Cloudflare Access with Google OAuth.

Architecture

User browser
  │  HTTPS
  ▼
chat.saiden.dev  ──┐ Cloudflare edge
  │                │
  │ CF Access      │  Google IdP challenge
  │ (whitelist)    │  → reject if not on list
  │                │
  ▼                │
Cloudflare Tunnel  │  Zero-trust ingress
  │                │
  ▼
junkpile:7681      │  ttyd (localhost-only, no public bind)
  │                │
  ▼
claude (bt7274)    │  marauder MCP gives BT identity + memory + tools

Properties

  • No frontend code. ttyd ships xterm.js + WS + theming. Custom Saiden palette via CLI flags.
  • No auth code. CF Access does Google OAuth + whitelist enforcement before the request ever reaches the tunnel.
  • ttyd binds 127.0.0.1 only — the public path is exclusively through the Tunnel + Access.
  • Real BT. Not an API impersonation. Full marauder MCP toolkit available in-session.

Components

Path Purpose
junkpile/ttyd-wrapper.sh Launches claude with bt7274 cart, with Saiden banner
junkpile/ttyd-chat.service systemd unit for ttyd (localhost-only bind, Saiden palette)
junkpile/cloudflared-chat-saiden.service systemd unit for tunnel (token-mode, reads /etc/cloudflared/chat-saiden.env)
cloudflare/dashboard-setup.md Step-by-step: create tunnel + public hostname + Access app + Google IdP + whitelist
install.sh Junkpile-side installer (ttyd + units + token env stub)
deploy.md End-to-end deploy walkthrough

Tunnel mode: token-based, matches existing junkpile pattern (cloudflared-mesh, cloudflared-tensors-art). Tunnel ingress lives in the CF dashboard, not in a local config file. Token sits in /etc/cloudflared/chat-saiden.env (mode 0640, root:chi).

Threat model (read before deploying)

ttyd-over-claude exposes shell-equivalent power on junkpile. The defense is the CF Access whitelist. Treat the whitelist as the security boundary:

  • Never open the Access policy to "any Google account" or "any domain".
  • Always keep cloudflared-chat-saiden and ttyd-chat localhost-bound.
  • If the whitelist is ever modified, auth_verify the change with the Pilot first.

Status

  • ttyd installed on junkpile (1.7.7_11)
  • ttyd wrapper installed → ~/.local/bin/ttyd-wrapper.sh
  • systemd units installed (ttyd-chat, cloudflared-chat-saiden)
  • Tunnel created in CF dashboard → token in /etc/cloudflared/chat-saiden.env
  • Public hostname chat.saiden.dev → http://localhost:7681
  • CF Access app + Google IdP + whitelist configured
  • WebSocket support enabled on Access app
  • sudo systemctl enable --now ttyd-chat cloudflared-chat-saiden
  • First successful login as adam.ladachowski@gmail.com
  • Whitelist denial verified from second Google account