48-Hour Teardown Runbook
Target: Current personal / portfolio demo stack
Primary services: Cloudflare Pages frontend, Fly.io API (cloudforge-api), optional Fly Postgres (cloudforge-db), optional local PuppyGraph via Docker Compose
Calendar reminder: Set at deploy time for every short-lived demo sprint
The earlier AWS-heavy personal stack (ECS, RDS, ALB, NAT gateway, PuppyGraph EC2) has already been torn down. This runbook covers the active Fly.io-based topology only.
1. Pre-Teardown Checklist
# Authenticate
fly auth whoami
wrangler whoami
# Inventory current Fly apps
fly apps list | rg 'cloudforge-api|cloudforge-db'
# Verify the API is still reachable before capture / backup
curl -sf https://api.cloudforge.lvonguyen.com/health | jq .
# Optional: verify PuppyGraph local stack state
docker ps --format '{{.Names}}' | rg 'puppy|postgres'
# Screenshot the live demo if needed for portfolio assets
# open https://cloudforge.lvonguyen.com
# open https://api.cloudforge.lvonguyen.com/health
Confirm before proceeding:
- Portfolio screenshots or recordings captured
- If Postgres is attached, a verified backup exists
- Custom domain / DNS records to remove are known
- No active demo or stakeholder review depends on the environment
2. Database Backup (If Postgres Is In Use)
If the current deployment is still using in-memory findings/GRC, skip this section.
# Preferred: dump from the configured DSN
pg_dump "$AEGIS_DATABASE_URL" > cloudforge-backup-$(date +%Y%m%d).sql
# Sanity check the dump file exists and is non-empty
ls -lh cloudforge-backup-$(date +%Y%m%d).sql
If the database is a dedicated Fly Postgres app, keep the backup with the session artifacts before destroying the DB app.
3. PuppyGraph Cleanup
PuppyGraph is local-only unless explicitly reintroduced.
# Stop local PuppyGraph stack if it is running
docker compose -f docker-compose.puppygraph.yml down
If PUPPYGRAPH_URL was set on Fly.io for a temporary graph demo:
fly secrets unset PUPPYGRAPH_URL -a cloudforge-api
4. Fly.io API Teardown
# Inspect the current app one last time
fly status -a cloudforge-api
fly releases list -a cloudforge-api | head
# Destroy the API app
fly apps destroy cloudforge-api --yes
This removes the cloudforge-api.fly.dev origin behind api.cloudforge.lvonguyen.com.
5. Fly Postgres Teardown (Optional)
Only do this if:
- the Postgres app exists
- a backup has already been taken
- no other app is attached to it
# Confirm the Postgres app exists
fly status -a cloudforge-db
# Destroy the dedicated Fly Postgres app if it is no longer needed
fly apps destroy cloudforge-db --yes
If the app does not exist, or the API still runs in memory mode, skip this section.
6. Cloudflare Pages / DNS Cleanup
Cloudflare Pages is free, so cleanup is optional unless you want a fully blank slate.
# Review recent Pages deployments before removing anything
wrangler pages deployment list --project-name cloudforge-demo | head -5
DNS records to consider:
api.cloudforge.lvonguyen.com->cloudforge-api.fly.devcloudforge.lvonguyen.com-> Cloudflare Pages projectcloudforge-democloudguard.lvonguyen.com-> legacy Cloudflare Pages hostname if it still exists in the account
If decommissioning entirely:
- remove the API CNAME after the Fly.io app is destroyed
- optionally delete the Pages projects from the Cloudflare dashboard
7. Verification
# Fly apps should no longer exist
fly apps list | rg 'cloudforge-api|cloudforge-db'
# API endpoint should no longer respond successfully
curl -s -o /dev/null -w "%{http_code}" https://api.cloudforge.lvonguyen.com/health
# PuppyGraph containers should be gone
docker ps --format '{{.Names}}' | rg 'puppy|postgres'
Expected outcome:
cloudforge-apiis absent fromfly apps listcloudforge-dbis absent if it was intentionally destroyedapi.cloudforge.lvonguyen.comreturns000,404, or a CDN/origin failure after DNS cleanup- no local PuppyGraph demo containers remain running
8. Re-Spin Notes
# Recreate or redeploy the API
fly deploy -a cloudforge-api
# Reapply secrets
fly secrets set AEGIS_JWT_SECRET=... -a cloudforge-api
fly secrets set AEGIS_DATABASE_URL=... -a cloudforge-api
# If using Postgres, restore from backup before enabling postgres-backed modes
psql "$AEGIS_DATABASE_URL" < cloudforge-backup-YYYYMMDD.sql
After redeploy:
- restore the API DNS record if it was removed
- verify
https://api.cloudforge.lvonguyen.com/health - verify frontend Pages builds still point at
/api/v1