diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4df8e72 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,40 @@ +# Agent Instructions + +## Project Context + +This is the server-stack repository for deploying tessavb.com, jamesvanboxtel.com, and git.jamesvanboxtel.com. It runs on a GCP e2-micro VM (Debian 12) at 35.230.59.34. + +## Stack + +- **Caddy** (lucaslorentz/caddy-docker-proxy) - reverse proxy with auto-SSL via Docker labels +- **Gitea** - self-hosted git at git.jamesvanboxtel.com +- **Node/Express apps** - each site runs on port 8080 internally +- **Docker Compose** - orchestrates everything (use `docker-compose` not `docker compose` on the server, the v2 plugin isn't installed) +- **SQLite** - database files go in `apps//data/` + +## Key Conventions + +- Caddy routing is configured via Docker labels on each service (e.g., `caddy: tessavb.com`, `caddy.reverse_proxy: "{{upstreams 8080}}"`) +- The Docker network is named `server-stack_server-network` (docker-compose prefixes the project name) +- The `CADDY_INGRESS_NETWORKS` env var must match this exact network name +- Data directories (`caddy_data/`, `gitea_data/`, `apps/*/data/`) are gitignored and must never be deleted on the server +- Each app has its own Dockerfile, package.json, and server.js in `apps//` + +## Adding a New Site + +1. Create `apps//` with Dockerfile, package.json, server.js +2. Add a service block to docker-compose.yml with appropriate `caddy` labels +3. Add DNS A record pointing the domain to 35.230.59.34 +4. Push and rebuild: `docker-compose up -d --build` + +## Deployment + +Currently manual: push to Gitea, SSH in, `git pull && docker-compose up -d --build`. +Auto-deploy via webhook is planned but not yet configured. + +## Testing + +No test suite yet. Verify changes by: +1. Building locally: `docker-compose build ` +2. Checking the site loads after deploying +3. Checking logs: `docker logs ` diff --git a/README.md b/README.md new file mode 100644 index 0000000..bd21cc5 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# Server Stack + +Production infrastructure for **tessavb.com**, **jamesvanboxtel.com**, and developer services. + +## Architecture + +Runs on a GCP `e2-micro` (Debian 12, Always Free Tier) at `35.230.59.34`. + +| Service | Container | Domain | Port | +|---------|-----------|--------|------| +| Reverse Proxy / SSL | `caddy` | — | 80, 443 | +| Git Hosting | `gitea` | git.jamesvanboxtel.com | 3000 (internal) | +| Tessa's Site | `tessavb-app` | tessavb.com | 8080 (internal) | +| James's Site | `jamesvanboxtel-app` | jamesvanboxtel.com | 8080 (internal) | + +**Caddy** auto-provisions Let's Encrypt SSL certificates and routes traffic to containers via Docker labels. **Gitea** provides private git hosting. Both apps are Node/Express placeholder sites. + +## Directory Structure + +``` +server-stack/ + docker-compose.yml # All service definitions + deploy.sh # Auto-deploy script (git pull + rebuild) + hooks.json # Webhook daemon config + .gitignore # Excludes data dirs from git + apps/ + tessavb/ # tessavb.com source code + Dockerfile + server.js + package.json + data/ # SQLite/persistent data (gitignored) + jamesvanboxtel/ # jamesvanboxtel.com source code + Dockerfile + server.js + package.json + data/ # SQLite/persistent data (gitignored) + caddy_data/ # Caddy SSL certs + config (gitignored) + gitea_data/ # Gitea database + repos (gitignored) +``` + +## Manual Deploy + +From your Mac: +```bash +cd /Users/jamesvanboxtel/Programming/websites/server-stack +git add -A && git commit -m "description" && git push +``` + +On the server (SSH): +```bash +cd ~/server-stack && git pull origin main && docker-compose up -d --build +``` + +## Auto Deploy (Not Yet Configured) + +Once the webhook daemon is set up, pushing to Gitea will automatically trigger `deploy.sh`, which pulls and rebuilds containers. See TASKS.md for setup steps. + +## Useful Commands + +```bash +# View running containers +docker ps + +# View logs for a service +docker logs caddy +docker logs gitea +docker logs tessavb-app + +# Restart everything +docker-compose down && docker-compose up -d + +# Rebuild a single app after code changes +docker-compose up -d --build tessavb-app +``` + +## DNS Records + +**jamesvanboxtel.com** (Namecheap): +- `@` A `35.230.59.34` +- `git` A `35.230.59.34` + +**tessavb.com** (Namecheap): +- `@` A `35.230.59.34` + +## GCP Firewall + +Ingress rule `allow-http` permits TCP ports 80, 443 from `0.0.0.0/0`. diff --git a/TASKS.md b/TASKS.md new file mode 100644 index 0000000..61f843f --- /dev/null +++ b/TASKS.md @@ -0,0 +1,15 @@ +# Tasks + +## Auto-Deploy Webhook Setup +- [ ] Fix `hooks.json` paths (currently hardcoded to `/home/james/`, should be `/home/jamesvanboxtel/`) +- [ ] Fix `deploy.sh` to use `docker-compose` instead of `docker compose` (v2 plugin not installed on server) +- [ ] Start the webhook daemon on the server: `webhook -hooks ~/server-stack/hooks.json -verbose &` +- [ ] Add GCP firewall rule to allow TCP port 9000 ingress +- [ ] Create a Gitea webhook on the server-stack repo pointing to `http://35.230.59.34:9000/hooks/redeploy-apps` +- [ ] Make the webhook daemon start on boot (systemd service) +- [ ] Add a webhook secret so only Gitea can trigger deploys + +## Infrastructure +- [ ] Set up `gcloud` CLI on Mac for SSH access without browser console +- [ ] Add www subdomain redirects (www.tessavb.com -> tessavb.com, etc.) +- [ ] Add backup strategy for gitea_data and app data directories diff --git a/deploy.sh b/deploy.sh index 92b8131..df8b904 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ #!/bin/bash cd /home/$USER/server-stack git pull origin main -docker compose up -d --build +docker-compose up -d --build diff --git a/hooks.json b/hooks.json index ab30e38..225dbd9 100644 --- a/hooks.json +++ b/hooks.json @@ -1,7 +1,17 @@ [ { "id": "redeploy-apps", - "execute-command": "/home/james/server-stack/deploy.sh", - "command-working-directory": "/home/james/server-stack" + "execute-command": "{{getenv \"HOME\"}}/server-stack/deploy.sh", + "command-working-directory": "{{getenv \"HOME\"}}/server-stack", + "trigger-rule": { + "match": { + "type": "payload-hmac-sha256", + "secret": "{{getenv \"WEBHOOK_SECRET\"}}", + "parameter": { + "source": "header", + "name": "X-Gitea-Signature" + } + } + } } ] diff --git a/webhook.service b/webhook.service new file mode 100644 index 0000000..0fdaf1c --- /dev/null +++ b/webhook.service @@ -0,0 +1,14 @@ +[Unit] +Description=Webhook auto-deploy daemon +After=network.target + +[Service] +Type=simple +User=jamesvanboxtel +EnvironmentFile=/home/jamesvanboxtel/.webhook-env +ExecStart=/usr/bin/webhook -hooks /home/jamesvanboxtel/server-stack/hooks.json -verbose +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target