From 7aa81c4e7c9bfef88b0e7d5186b64a4ec652bfa7 Mon Sep 17 00:00:00 2001 From: Ryan Moon Date: Sat, 4 Apr 2026 10:30:40 -0500 Subject: [PATCH] docs: add infrastructure, build pipeline, and dev box sections to CLAUDE.md --- CLAUDE.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index e4d1d80..044b563 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -63,3 +63,115 @@ - API routes are thin — validate with Zod, call a service, return result - All financial events must be auditable (append-only audit records) - JSON structured logging with request IDs on every log line + +--- + +## Infrastructure + +### Overview +LunarFront runs on DigitalOcean Kubernetes (DOKS). Each customer gets an isolated namespace, database, and Helm release managed by ArgoCD. + +### Key Services +- **Cluster:** `lunarfront` DOKS cluster, region NYC +- **Registry:** `registry.digitalocean.com/lunarfront` (DOCR) — stores Docker images and Helm charts +- **Git:** `git.lunarfront.tech` — self-hosted Gitea, source of truth for code and charts +- **CI:** Gitea Actions — builds Docker images and Helm charts on push to `main` +- **CD:** ArgoCD at `argocd.lunarfront.tech` — deploys from `lunarfront-charts` repo +- **Database:** DO Managed PostgreSQL — one database per customer, plus manager DB +- **Cache/Queue:** DO Managed Valkey — shared across all customers (key-prefixed per customer) +- **Ingress:** nginx ingress controller with Cloudflare proxy in front +- **TLS:** cert-manager with Let's Encrypt (letsencrypt-prod cluster issuer) +- **DNS:** Cloudflare — wildcard `*.lunarfront.tech` → cluster LB IP `167.99.21.170` + +### Node Pools +- `system` — 2x s-2vcpu-4gb, runs ingress, ArgoCD, manager, pgbouncer +- `customers` — autoscales 0→N, s-4vcpu-8gb, runs customer app pods (tainted `role=customer`) +- `dev` — autoscales 0→1, s-4vcpu-8gb, runs dev pod only (tainted `dedicated=dev:NoSchedule`) + +### Repos +- `lunarfront-app` — main application code (this repo) +- `lunarfront-charts` — Helm charts and ArgoCD app definitions +- `lunarfront-infra` — Terraform for DO infrastructure (DOKS, managed DBs, registry, DNS) +- `lunarfront-manager` — internal ops tool for provisioning/deprovisioning customers + +--- + +## Build & Deploy Pipeline + +### How it works +1. Push code to `main` on `lunarfront-app` +2. Gitea Actions runs `.gitea/workflows/build.yml`: + - Builds `lunarfront-app` Docker image → pushes as `0.1.{run_number}`, `{sha}`, `latest` + - Builds `lunarfront-frontend` Docker image → same tags + - Packages Helm chart → pushes as `0.1.{run_number}` to DOCR OCI registry +3. ArgoCD image updater detects new image digests → updates customer deployments +4. New customer provisions always get the latest chart version (queried from DOCR at provision time) +5. Existing customers upgraded via `POST /customers/:slug/upgrade` or `POST /customers/upgrade-all` in the manager + +### Versioning +- Version format: `0.1.{gitea_run_number}` — always incrementing, no git commit-back needed +- No version stored in git — source of truth is DOCR tags +- Chart version and app version are kept in sync + +### Key files +- `Dockerfile` — backend image (bun runtime, runs `packages/backend/src/main.ts` directly) +- `Dockerfile.frontend` — frontend nginx image +- `chart/` — Helm chart for customer app deployments +- `.gitea/workflows/build.yml` — CI pipeline +- `.gitea/workflows/build-devpod.yml` — builds dev box image on Dockerfile.devpod changes + +--- + +## Dev Box + +### What it is +A persistent development pod running in the `dev` namespace on the cluster. Provides a full remote dev environment accessible from anywhere. + +- **VS Code in browser:** `dev.lunarfront.tech` (Cloudflare Access protected, OTP to email) +- **SSH:** `ssh -p 2222 root@dev-ssh.lunarfront.tech` +- **Storage:** 100GB DO block storage PVC mounted at `/root` — everything in home dir persists +- **Image:** `registry.digitalocean.com/lunarfront/manager:devpod-latest` +- **Tools:** bun, Claude Code CLI, code-server, kubectl, helm, k9s, doctl, psql, redis-cli, git + +### Managing the dev pod +```bash +# Scale up (provisions node automatically) +kubectl scale deployment dev -n dev --replicas=1 + +# Scale down (node auto-terminates after ~15 min) +kubectl scale deployment dev -n dev --replicas=0 +``` + +### Running the app locally on the dev box (no containers) +The dev box runs the app as plain Bun processes, connecting to the same DO managed services as production. + +**Required env vars** (create a `.env` file in the repo root or export in `.bashrc`): +```bash +DATABASE_URL=postgresql://... # DO managed postgres, lunarfront database +REDIS_URL=rediss://... # DO managed valkey +JWT_SECRET=... # any random hex string for local dev +PORT=8000 +``` + +**Start the app:** +```bash +cd ~/lunarfront-app +bun run dev +``` + +Access the running backend at `dev.lunarfront.tech/proxy/8000/` in the browser (code-server proxy), or via SSH port forward: +```bash +ssh -p 2222 -L 8000:localhost:8000 root@dev-ssh.lunarfront.tech +``` + +**Run migrations against the dev database:** +```bash +bunx drizzle-kit migrate +``` + +### Workflow +1. Edit code in VS Code at `dev.lunarfront.tech` or via SSH +2. Run and test locally with `bun run dev` — app connects to DO managed postgres/valkey +3. Push to `main` → Gitea Actions builds and pushes new Docker image + Helm chart +4. ArgoCD deploys to the cluster automatically +5. Use manager at `manager.lunarfront.tech` to upgrade customer instances if needed