OGStack is self-hosted on a VPS. The public site runs at ogstack.dev, with the API behind api.ogstack.dev and docs at docs.ogstack.dev. Generated images are served from cdn.ogstack.dev (Cloudflare CDN in front of Cloudflare R2).
Two GitHub Actions workflows:
- ci.yml runs on every push and PR: format check, Prisma generate, typecheck (all 4 workspaces), API tests, web plus docs build, secret scan (gitleaks), dependency audit (
bun audit). - deploy.yml runs on push to
prod: builds Docker images forapi,web,docs, pushes them to GitHub Container Registry, SSHs into the VPS, and runsdocker compose pull && docker compose up -d --force-recreate. A post-deploy/healthcheck confirms the API is responsive.
- The API is a long-running process with Postgres connections, background jobs (demo project cleanup, Stripe webhook sync), and local image-generation binaries (resvg, Satori). Not a fit for serverless cold-start plus 10-second execution limits.
- Generated images are persisted to Cloudflare R2 (via direct S3-compatible calls from the API), then served from a CDN. Vercel's edge caching doesn't add value here.
- OAuth callback URLs and Stripe webhook endpoints need stable, predictable hostnames. VPS plus Nginx gives a single public surface without per-environment URL churn.
Set in GitHub, Settings, Secrets and variables, Actions:
SSH_HOST,SSH_USER,SSH_KEY. Target VPS.ENV_DOCKER. The full.envcontents the deploy step copies onto the host.GCP_SA_KEY. reCAPTCHA Enterprise service account JSON.
Set as repository variables (visible to the build step):
NEXT_PUBLIC_*. Web app environment values baked into the Next.js build.
- VPS with Docker plus docker-compose, reachable over SSH on port 22, with Nginx terminating TLS on 80/443.
- Postgres. The docker-compose brings up a local Postgres by default. Swap the
DATABASE_URLenv var for a managed provider if desired. - Cloudflare R2 bucket for generated images.
- Stripe account (test-mode key works for non-production environments).
- FAL.ai account for Flux AI image generation.
- Anthropic Claude API key for the AI prompt builder used by the generation service.
- GitHub plus Google OAuth apps registered with the correct callback URLs.
See .env.example for the full list of variables.
See development.md for running the apps locally. Production and local are intentionally similar. The same Dockerfile per app is used in both.