# CLAUDE.md Quick context for Claude Code. See README.md for full details, ARCHITECTURE.md for technical deep-dives, USECASES.md for expected behaviors. ## Key files - `scripts/bootstrap.sh` -- First-time server setup (manual, uses Bitwarden) - `scripts/configure.sh` -- Idempotent server config (firewall, certbot, start services; CI-safe) - `scripts/deploy.sh` -- SSH-triggered deploy + cert issuance + provision (deploy-*, cert-*, provision commands) - `tools/new-app.sh` -- Single-command new static site (DNS + Gitea repo + cert + bucket + deploy + verify) - `tools/new-service.sh` -- Scaffold a new Docker Compose service (compose + workflow) - `tools/remove-app.sh` -- Remove a static site (local files + Gitea repo) - `docker/nginx/conf.d/` -- Per-app nginx server blocks - `docker//compose.yml` -- Per-app compose files - `docker/garage/` -- Garage S3 object storage (Dockerfile, garage.toml, .env.keys) - `.gitea/workflows/` -- Per-app deploy workflows + provision.yml ## Conventions - **App name = domain** (e.g., `example.com`) - **Container name** = dots → underscores (e.g., `example_com`) - **One domain per conf file** -- deploy.sh derives cert name from filename - All HTTP → HTTPS; bare domain → `www.` - All shell scripts use `set -euo pipefail` and must be idempotent - The `shared` Docker network is created by nginx compose and used by all apps - Secrets are in Bitwarden Secrets Manager (see README.md for full list) - Service secrets use `.env.keys` files (see README.md) ## Deploy flow - App repo push → `build.yml` → build/push image → SSH `deploy-` → deploy.sh - This repo push → `deploy-.yml` (path match) → SSH `deploy-` → deploy.sh - Setup change → `provision.yml` → SSH `provision` → configure.sh ## Build and test No build step. No tests. Verify changes by: 1. Reading scripts and checking idempotency 2. Walking through each use case in USECASES.md 3. Cross-checking docs against scripts ## Commit style - Short, lowercase commit messages (e.g., "add example.com", "fix deploy command") - Do NOT include "Co-Authored-By" lines - Commit only when explicitly asked