@@ -97,19 +97,18 @@ make ps # Show running containers
9797docker compose -f compose.local.yml up -d
9898uv run fastapi dev app/main.py
9999
100- # Dev environment (auto-deploy via Watchtower)
101- make dev:deploy # Deploy to dev environment
100+ # Dev environment (auto-deploy via GitHub Actions)
101+ # Server setup (one-time): ./scripts/setup-server.sh dev
102+ # Then push to develop branch for auto-deploy
102103make dev:logs # View dev logs
103104make dev:ps # Check dev status
104105
105- # Production environment (auto-deploy via Watchtower)
106- make prod:deploy # Deploy to production (with confirmation)
106+ # Production environment (auto-deploy via GitHub Actions)
107+ # Server setup (one-time): ./scripts/setup-server.sh prod
108+ # Then push to main branch for auto-deploy
107109make prod:logs # View production logs
108110make prod:ps # Check production status
109111
110- # Watchtower setup (one-time per server)
111- ./scripts/setup-watchtower.sh
112-
113112# Secrets management (SOPS + age)
114113make secrets:encrypt:dev # Encrypt dev secrets
115114make secrets:encrypt:prod # Encrypt prod secrets
@@ -246,10 +245,9 @@ IMPORTANT: Follow these conventions strictly:
246245- ** Automatic execution** : Migrations run on application startup (FastAPI lifespan event)
247246- ** Location** : ` app/infrastructure/database/alembic/versions/ `
248247- ** Safety** : If migration fails, application startup stops (prevents data corruption)
249- - ** Watchtower compatibility** : When Watchtower updates the server image, migrations run automatically
248+ - ** Auto-deploy compatibility** : When GitHub Actions deploys new image, migrations run automatically
250249- ** Idempotency** : Alembic ensures migrations only run once (safe to restart)
251250- ** Manual rollback** : Use ` make db:downgrade REV=-1 ` if needed
252- - ** Legacy db-migrator** : Removed (migrations now embedded in server container)
253251
254252### Docker Profiles
255253- Use ` --profile local-db ` to enable local database container
@@ -263,15 +261,15 @@ IMPORTANT: Follow these conventions strictly:
263261
264262## Deployment Architecture
265263
266- IMPORTANT: The project uses three distinct deployment environments with automatic updates .
264+ IMPORTANT: The project uses three distinct deployment environments with GitHub Actions auto-deploy .
267265
268266### Environment Overview
269267
270268| Environment | App Execution | Database | Proxy | Auto-Deploy | Compose File |
271269| -------------| --------------| ----------| -------| -------------| --------------|
272270| ** Local** | uv native (hot reload) | Docker (optional) | None | No | ` compose.local.yml ` |
273- | ** Dev** | Docker (GHCR.io) | Docker PostgreSQL | Cloudflare Tunnels | Watchtower (develop) | ` compose.dev.yml ` |
274- | ** Prod** | Docker (GHCR.io) | External (Supabase) | nginx + Cloudflare | Watchtower (latest ) | ` compose.prod.yml ` |
271+ | ** Dev** | Docker (GHCR.io) | Docker PostgreSQL | Cloudflare Tunnels | GitHub Actions (develop) | ` compose.dev.yml ` |
272+ | ** Prod** | Docker (GHCR.io) | External (Supabase) | nginx + Cloudflare | GitHub Actions (main ) | ` compose.prod.yml ` |
275273
276274### Key Deployment Features
277275
@@ -281,29 +279,12 @@ IMPORTANT: The project uses three distinct deployment environments with automati
281279- ` main ` branch → ` latest ` + ` main ` + ` main-sha-xxx ` tags
282280- ` develop ` branch → ` develop ` + ` develop-sha-xxx ` tags
283281
284- ** Automatic deployment** : Watchtower monitors GHCR.io and auto-updates containers (10 min polling)
282+ ** Automatic deployment** : GitHub Actions SSHs into server and deploys on push to develop/main
285283
286- ** Label-based control ** : Only containers with ` com.centurylinklabs.watchtower.enable=true ` update
284+ ** Sparse checkout ** : Server only clones necessary files (compose.yml, Makefile, etc.) to minimize disk usage
287285
288286** Secrets management** : SOPS + age for encrypted environment files (` .env.dev.enc ` , ` .env.prod.enc ` )
289287
290- ### Watchtower Setup
291-
292- ** One Watchtower per server** (not per project):
293- - Label-based control prevents unintended updates
294- - Weekly self-update via cron
295- - Discord/Slack notifications via Shoutrrr
296- - Setup: ` ./scripts/setup-watchtower.sh `
297-
298- ** Auto-update enabled for** :
299- - ` server ` container
300- - ` db-dumper ` container (from ukwhatn/postgres-tools)
301- - ` db-migrator ` container (from ukwhatn/postgres-tools)
302-
303- ** Auto-update disabled for** :
304- - ` db ` container (PostgreSQL)
305- - ` cloudflared ` container
306-
307288### Secrets Management (SOPS + age)
308289
309290** Why** : Encrypted secrets can be safely committed to Git with full audit trail
@@ -316,9 +297,12 @@ IMPORTANT: The project uses three distinct deployment environments with automati
3162975 . Commit encrypted file to Git
317298
318299** Deployment flow** :
319- 1 . Deploy script decrypts ` .env.dev.enc ` → ` .env `
320- 2 . Starts containers with decrypted secrets
321- 3 . Removes ` .env ` after deployment
300+ 1 . GitHub Actions builds image and pushes to GHCR.io
301+ 2 . GitHub Actions SSHs into server
302+ 3 . Server runs ` git pull ` to get latest compose.yml
303+ 4 . Server runs ` docker compose pull ` to get latest image
304+ 5 . Server runs ` docker compose up -d --force-recreate ` to restart containers
305+ 6 . Health check confirmation (60s timeout)
322306
323307** Reference** : See ` docs/secrets-management.md ` for detailed guide
324308
@@ -332,36 +316,40 @@ uv run fastapi dev app/main.py
332316
333317** Dev deployment** (initial):
334318``` bash
335- ./scripts/setup-watchtower.sh # One-time per server
336- ./scripts/deploy-dev.sh # Deploy
319+ # On server (one-time setup)
320+ ./scripts/setup-server.sh dev
321+
322+ # Configure GitHub Secrets (one-time):
323+ # DEV_SSH_HOST, DEV_SSH_USER, DEV_SSH_PORT, DEV_SSH_PRIVATE_KEY
337324```
338325
339326** Dev deployment** (subsequent):
340327``` bash
341- git push origin develop # GitHub Actions builds and pushes
342- # Watchtower auto-updates within 10 minutes
328+ git push origin develop # GitHub Actions auto-deploys
343329```
344330
345331** Production deployment** (initial):
346332``` bash
347- ./scripts/setup-watchtower.sh # One-time per server
348- ./scripts/deploy-prod.sh # Deploy with confirmation
333+ # On server (one-time setup)
334+ ./scripts/setup-server.sh prod
335+
336+ # Configure GitHub Secrets (one-time):
337+ # PROD_SSH_HOST, PROD_SSH_USER, PROD_SSH_PORT, PROD_SSH_PRIVATE_KEY
349338```
350339
351340** Production deployment** (subsequent):
352341``` bash
353- git push origin main # GitHub Actions builds and pushes
354- # Watchtower auto-updates within 10 minutes
342+ git push origin main # GitHub Actions auto-deploys
355343```
356344
357345### Important Deployment Notes
358346
359- - ** No SSH required ** : All deployments use GHCR.io pull + Watchtower
360- - ** Downtime** : 10-30 seconds during auto-updates
361- - ** Branch isolation** : develop and main branches use different tags (no cross-contamination)
362- - ** Rollback** : Use SHA tags for specific version deployment
363- - ** Monitoring** : Check Watchtower logs with ` docker logs watchtower -f `
364- - ** Health checks** : Containers have built-in health checks; Watchtower respects them
347+ - ** SSH managed by GitHub Actions ** : Developers don't need server access
348+ - ** Downtime** : ~ 10-30 seconds during deploys (forced container recreation)
349+ - ** Branch isolation** : develop and main branches use different tags and servers
350+ - ** Rollback** : Use ` git revert ` and push, or manually checkout previous commit on server
351+ - ** Monitoring** : Check GitHub Actions logs and server logs with ` ENV={dev|prod} make compose:logs `
352+ - ** Health checks** : Deployment fails if health check doesn't pass within 60 seconds
365353
366354** Reference** : See ` docs/deployment.md ` for comprehensive deployment guide
367355
0 commit comments