- Update Dockerfile to golang:1.26-alpine (matching go.mod) - Update deploy.sh for Docker Compose workflow - Rewrite DEPLOYMENT.md for new API architecture - Add env vars for face service and Redis configuration
5.8 KiB
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)
- Merge PR to
main - Gitea webhook triggers
gitea-webhook.py - Script runs
deploy.shautomatically
Manual
cd /home/nara/apps/web
./deploy.sh
What deploy.sh does:
git pull github main— fetches latest from GitHub (source of truth)git push origin main— syncs to Gitea (push-mirror)docker compose down— stops current containersdocker compose build hatch— rebuilds the Go binary in a multi-stage builddocker compose --profile with-caddy up -d— starts hatch + caddy- 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:
hatchonly (API on port 8080) with-caddy:hatch+caddy(full HTTPS via Let's Encrypt)
Check status:
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
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
go build ./cmd/hatch/
go test ./...
3. Commit and push
git add .
git commit -m "Description of changes"
git push origin main
4. Deploy
Either wait for webhook or run manually:
./deploy.sh
5. Verify
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:
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:
docker compose logs hatch
docker compose logs caddy
Health check failing:
curl -v http://localhost:8080/healthz
docker compose exec hatch /bin/hatch # Check binary exists
Database issues:
# 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:
sudo lsof -i :8080
# Kill conflicting process or change port in docker-compose.yml
Integration Tests
Integration tests require AWS credentials (build tag: integration):
export AWS_REGION=us-east-1
export REKOGNITION_COLLECTION=hatch-faces-test
go test -tags=integration ./internal/face/... -v
Performance benchmarks (build tag: performance):
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)