Commit8fcfd61
docs(claude): record real operator topology — Tailscale access, docker layout, GitHub reality
docs(claude): record real operator topology — Tailscale access, docker layout, GitHub reality Session 2026-07-12 burned hours rediscovering facts no doc recorded: the box is reachable via Tailscale SSH as jarvis (100.109.131.122); the app runs under docker-compose.standalone.yml with a LOCAL postgres container (not Neon); bare repos live in the gluecron_git-repos docker volume (the host /data/repos dir is a decoy); deploys stop silently when gluecron-update.timer is disabled; and GitHub was never actually frozen — it remains the emergency deploy source until offsite backups pass a restore drill. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed+39−88fcfd61979cd2fc4031a7c42bee1313daa62681c
1 changed file+39−8
ModifiedCLAUDE.md+39−8View fileUnifiedSplit
@@ -42,9 +42,33 @@ and `src/hooks/post-receive.ts` fires `scripts/self-deploy.sh` directly.
4242The live site reflects the push in ~25 seconds. Watch `/admin/deploys`
4343for the live step stream.
4444
45**Server:** `gluecron.com` → `66.42.121.161` (VPS, not Fly.io or Hetzner —
45**Server:** `gluecron.com` → `66.42.121.161` (Vultr VPS, not Fly.io or Hetzner —
4646both are decommissioned). Working tree lives at `/opt/gluecron` on that box.
4747
48**Operator access (AI sessions included):** the box is on the owner's
49Tailscale tailnet as `jarvis` (`100.109.131.122`) with **Tailscale SSH
50enabled** — from an owner machine, `ssh root@100.109.131.122` just works
51(no key setup). Public-internet SSH (port 22) is password-only and the git
52SSH server port (2222) is not exposed; always go via Tailscale.
53
54**Runtime layout on the box (verified 2026-07-12):**
55- App runs via `docker compose -f docker-compose.standalone.yml` in
56 `/opt/gluecron` (services: `gluecron`, `postgres`, `autoheal`).
57- **Database is the local `postgres` container (pgvector/pg16)** — NOT Neon.
58 Any doc claiming Neon in production is stale.
59- Bare repos live in the docker volume `gluecron_git-repos`
60 (host path `/var/lib/docker/volumes/gluecron_git-repos/_data`), mounted
61 into the container at `/data/repos`. The host-side `/data/repos` dir is
62 NOT the live store — always go through the volume path.
63- Auto-deploy: `gluecron-update.timer` (60s) runs `scripts/auto-update.sh`
64 — fetches `origin main` in `/opt/gluecron` and rebuilds on change.
65 `origin` = the canonical Gluecron repo. If the timer is disabled, deploys
66 silently stop — check `systemctl list-timers 'gluecron-*'` first when the
67 live build looks stale (compare `/api/version` builtAt vs latest commit).
68- Manual deploy: `cd /opt/gluecron && git fetch <src> main && git reset
69 --hard FETCH_HEAD && docker compose -f docker-compose.standalone.yml up
70 -d --build`, then `... exec -T gluecron bun run db:migrate`.
71
4872**To deploy:**
4973```bash
5074git push gluecron main
@@ -52,10 +76,17 @@ git push gluecron main
5276git remote add gluecron https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git
5377```
5478
55**Do NOT use Vercel** — it has been disconnected. The old GitHub repo
56(`ccantynz-alt/Gluecron.com`) is being retired: frozen read-only now, deleted
57after a 30-day safety window. It is NOT a mirror and pushing there does nothing
58— use the canonical Gluecron remote only.
79**Do NOT use Vercel** — it has been disconnected.
80
81**GitHub reality check (2026-07-12):** the old GitHub repo
82(`ccantynz-alt/Gluecron.com`) is NOT frozen and is still writable — the
83cutover runbook (docs/CUTOVER_RUNBOOK.md) was designed but its operator
84phases were never fully executed. GitHub remains the emergency deploy
85source (`git fetch https://github.com/ccantynz-alt/Gluecron.com.git main`
86on the box) until offsite backups are armed and a restore drill has
87passed. Do not delete or archive the GitHub repo before that. Prefer the
88canonical Gluecron remote for normal work; keep GitHub in sync until the
89runbook's Phase 4 criteria are actually met.
5990
6091## READ FIRST — every session
6192
@@ -74,7 +105,7 @@ Do not skip it. Do not refactor locked files. Do not stop mid-block.
74105
75106- **Runtime:** Bun
76107- **Framework:** Hono (with JSX for server-rendered views)
77- **Database:** Drizzle ORM + Neon (PostgreSQL)
108- **Database:** Drizzle ORM + PostgreSQL (local pgvector/pg16 container in prod; Neon works for dev)
78109- **Git:** Smart HTTP protocol via git CLI subprocesses
79110
80111## Development
@@ -159,7 +190,7 @@ src/
159190## Environment Variables
160191
161192See `.env.example` for required variables. Key ones:
162- `DATABASE_URL` — Neon PostgreSQL connection string
193- `DATABASE_URL` — PostgreSQL connection string (prod: local postgres container)
163194- `GIT_REPOS_PATH` — directory for bare git repos (default: `./repos`)
164195- `PORT` — HTTP port (default: 3000)
165196
@@ -169,7 +200,7 @@ See `.env.example` for required variables. Key ones:
169200- **Deploy trigger:** `git push gluecron main` → `post-receive.ts` → `scripts/self-deploy.sh` → systemd reload.
170201- **Fly.io:** decommissioned (fly.toml kept for reference, not active).
171202- **Vercel:** disconnected — do not reconnect.
172- **Database:** Neon PostgreSQL (direct connection via `DATABASE_URL`).
203- **Database:** PostgreSQL via `DATABASE_URL` (prod: pgvector/pg16 container on the box).
173204- **Logs:** `/var/log/gluecron-self-deploy.log` on the server; live stream at `/admin/deploys`.
174205
175206## Skills available for this project
176207