# Hatch API — Deployment Guide ## Overview The Hatch API (`hatch.surf`) is a **Go backend** deployed via **Docker Compose** on the production server. **Key principle**: All changes MUST go through the git repository and automated deployment. Never edit files directly on the server. --- ## Repository **Location**: `/home/nara/apps/web/` **Git Remotes**: - `github` → `el-foundation/hatch-surf` (Gitea, source of truth) - `origin` → `el-foundation/hatch-surf` (Gitea push-mirror) **Structure**: ``` cmd/hatch/ # Go server entrypoint internal/ # Go packages (handler, store, face, etc.) Dockerfile # Multi-stage Docker build (Go → scratch) docker-compose.yml # Container orchestration (hatch + caddy) Caddyfile # Caddy reverse proxy config deploy.sh # Deployment script ``` --- ## Deployment Flow ### Automatic (Recommended) 1. Merge PR to `main` 2. Gitea webhook triggers `gitea-webhook.py` 3. Script runs `deploy.sh` automatically ### Manual ```bash cd /home/nara/apps/web ./deploy.sh ``` **What `deploy.sh` does**: 1. `git pull github main` — fetches latest from GitHub (source of truth) 2. `git push origin main` — syncs to Gitea (push-mirror) 3. `docker compose down` — stops current containers 4. `docker compose build hatch` — rebuilds the Go binary in a multi-stage build 5. `docker compose --profile with-caddy up -d` — starts hatch + caddy 6. Verifies health endpoint responds 200 --- ## Docker Setup **Services**: | Service | Image | Port | Purpose | |----------|----------------|-------|------------------------| | `hatch` | web-hatch | 8080 | Go API server | | `caddy` | caddy:2-alpine | 80/443| Reverse proxy + TLS | **Profiles**: - Default: `hatch` only (API on port 8080) - `with-caddy`: `hatch` + `caddy` (full HTTPS via Let's Encrypt) **Check status**: ```bash docker compose ps docker compose logs hatch docker compose logs caddy ``` --- ## Environment Variables Configure in `.env` or pass to Docker Compose: | Variable | Default | Description | |------------------------|----------------------|--------------------------------------| | `HATCH_HOSTNAME` | `localhost` | Public hostname for TLS cert | | `HATCH_BASE_URL` | `http://localhost` | Base URL for SSE and self-references | | `FACE_SERVICE_ENABLED` | `false` | Enable AWS Rekognition face search | | `AWS_REGION` | `us-east-1` | AWS region for Rekognition | | `REKOGNITION_COLLECTION` | `hatch-faces` | Rekognition collection ID | | `REDIS_URL` | — | Redis URL (optional, for caching) | --- ## Making Changes ### 1. Edit Go source ```bash cd /home/nara/apps/web vim cmd/hatch/main.go # Server entrypoint vim internal/handler/ # HTTP handlers vim internal/face/ # Face detection service vim internal/store/ # Database layer ``` ### 2. Build and test locally ```bash go build ./cmd/hatch/ go test ./... ``` ### 3. Commit and push ```bash git add . git commit -m "Description of changes" git push origin main ``` ### 4. Deploy Either wait for webhook or run manually: ```bash ./deploy.sh ``` ### 5. Verify ```bash curl -s http://localhost:8080/healthz curl -s http://localhost:8080/readyz ``` --- ## Common Mistakes to Avoid ❌ **DON'T**: Edit files directly inside the Docker container ❌ **DON'T**: Commit without testing ❌ **DON'T**: Use `go run` in production ✅ **DO**: Test with `go test ./...` before committing ✅ **DO**: Use `docker compose build` for production builds ✅ **DO**: Check health endpoints after deployment --- ## Rollback If a deployment causes issues: ```bash cd /home/nara/apps/web # Revert to previous version git revert HEAD git push origin main # Redeploy ./deploy.sh ``` --- ## API Endpoints | Method | Path | Description | |--------|-------------------------------|---------------------------------| | GET | `/healthz` | Liveness probe | | GET | `/readyz` | Readiness probe (checks DB) | | GET | `/api/v1/spaces` | List public spaces | | POST | `/api/v1/spaces` | Create a space | | GET | `/api/v1/spaces/{slug}` | Get space by slug | | POST | `/api/v1/spaces/{slug}/photos`| Upload photo to space | | POST | `/api/v1/face/search` | Search faces by image | | GET | `/e/{endpointID}` | Inspect captured requests | | GET | `/e/{endpointID}/events` | SSE stream for live updates | --- ## Troubleshooting **Container not starting**: ```bash docker compose logs hatch docker compose logs caddy ``` **Health check failing**: ```bash curl -v http://localhost:8080/healthz docker compose exec hatch /bin/hatch # Check binary exists ``` **Database issues**: ```bash # SQLite database is persisted in a Docker volume docker volume ls | grep hatch-data docker run --rm -v hatch-data:/data alpine ls -la /data/ ``` **Port conflict**: ```bash sudo lsof -i :8080 # Kill conflicting process or change port in docker-compose.yml ``` --- ## Integration Tests Integration tests require AWS credentials (build tag: `integration`): ```bash export AWS_REGION=us-east-1 export REKOGNITION_COLLECTION=hatch-faces-test go test -tags=integration ./internal/face/... -v ``` Performance benchmarks (build tag: `performance`): ```bash go test -tags=performance -bench=. ./internal/face/... ``` --- ## Contact - **CTO**: Jordan Patel - **Repository**: `/home/nara/apps/web/` - **API**: http://localhost:8080 (internal) / https://hatch.surf (public)