docker-compose.prod.yml targets the public VPS: Postgres is never published, the app binds to 127.0.0.1 (Caddy proxies it), and every service has a memory/CPU cap plus no-new-privileges / cap_drop / read-only rootfs. deploy/deploy.sh rolls out main with a host-side build (migrations run via the entrypoint). CI type-checks and builds the frontend and byte-compiles the backend on every push to main.
2.1 KiB
Deploying Subfeed to the public VPS (the VPS)
The public test instance runs on the the VPS VPS at https://subfeed.b1fr0st.eu, behind
Caddy (which terminates TLS and reverse-proxies to the app on 127.0.0.1:8080).
Layout on the VPS
/srv/subfeed/
src/ git clone of this repo (build context + compose file)
.env secrets, mode 0600 — NEVER committed
The hardened compose is docker-compose.prod.yml: Postgres is
never published, the app binds to localhost only, and every service is memory/CPU-capped for
the small VPS.
First-time setup
-
DNS
A/AAAAforsubfeed→ the VPS (done via the your DNS provider CLI). -
Caddy vhost block
subfeed.b1fr0st.eu { reverse_proxy 127.0.0.1:8080 }(+ the shared security-headers snippet), then reload Caddy. -
git clonethis repo to/srv/subfeed/src. -
Create
/srv/subfeed/.env(mode 0600) with the required keys — see.env.example. Generate the secrets:SECRET_KEY:python -c "import secrets; print(secrets.token_urlsafe(48))"TOKEN_ENCRYPTION_KEY:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"POSTGRES_PASSWORD: any long random string.OAUTH_REDIRECT_URL=https://subfeed.b1fr0st.eu/auth/callbackGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET/YOUTUBE_API_KEYfrom Google Cloud Console.ALLOWED_EMAILS/ADMIN_EMAILS= the invited Google accounts.
The app refuses to start in production (an
httpsredirect URL) ifSECRET_KEYis the placeholder/too short orTOKEN_ENCRYPTION_KEYis missing — by design.
Rolling out a new version
/srv/subfeed/src/deploy/deploy.sh
It pulls main, rebuilds the image on the host, and restarts the stack (migrations run
automatically via the entrypoint's alembic upgrade head).
CI
.forgejo/workflows/ci.yml type-checks/builds the frontend and byte-compiles the backend on
every push to main. It does not auto-deploy; rollout is the script above. (A future
improvement: a Forgejo-triggered or watchtower-based auto-rollout.)