GitHub/Google buttons on the login page pointed at providers that may not be configured in Supabase, dead-ending in an error. Add NEXT_PUBLIC_OAUTH_GITHUB / NEXT_PUBLIC_OAUTH_GOOGLE (opt-in, "true" to show); a provider button renders only when enabled and the whole social block is hidden when neither is. Pure resolveOAuthProviders helper is unit-tested; flags documented in .env.example and DEPLOYMENT.md.
3.0 KiB
3.0 KiB
Deployment
The supported production target is a single DigitalOcean Droplet running self-hosted Supabase plus the Next.js app behind Caddy with automatic HTTPS. The end-to-end procedure lives in DEPLOY_DO_SELFHOSTED.md.
At a glance
| Component | Hosted on |
|---|---|
| Database (Postgres) | Supabase container on the Droplet, data on a persistent block volume |
| Auth (GoTrue) | Supabase container on the Droplet |
| REST and Realtime | Supabase containers on the Droplet |
| App (Next.js) | systemd service on the Droplet, port 3000 |
| Reverse proxy | Caddy 2 on the Droplet, ports 80 and 443 |
| Resend (SMTP) | |
| Backups | Daily pg_dumpall to /mnt/data/backups, 14-day retention |
| Continuous deployment | GitHub Actions runs /opt/hackerspace-ops/deploy.sh over SSH on every push to main |
Required environment variables
All variables are listed in .env.example. At minimum:
NEXT_PUBLIC_SUPABASE_URL— public Supabase API URLNEXT_PUBLIC_SUPABASE_ANON_KEY— anon JWT, publicSUPABASE_SERVICE_ROLE_KEY— service-role JWT, server-side onlyNEXT_PUBLIC_APP_URL— public URL of the deployed app, used in OAuth redirects
Optional:
NEXT_PUBLIC_OAUTH_GITHUB/NEXT_PUBLIC_OAUTH_GOOGLE— set to"true"only for an OAuth provider you have actually configured in Supabase Auth. The login page hides any provider button that is not enabled, and hides the whole social-sign-in block if neither is set. These are build-time public values, so a change requires a redeploy to take effect.
How a deploy runs
- A developer pushes to
main. - GitHub Actions (
.github/workflows/deploy.yml) opens an SSH connection to the Droplet using a deploy key stored in repository secrets. - The action invokes
/opt/hackerspace-ops/deploy.sh, which:- Fetches latest
main. - Runs
pnpm install --frozen-lockfile. - Iterates over
scripts/0*.sql. Any file not present inpublic._migrations_appliedis applied and recorded. - Restarts PostgREST to refresh its schema cache.
- Runs
pnpm build. - Restarts the
hackerspace-appsystemd unit. - Probes the local app for a 200 response.
- Fetches latest
Migrations are idempotent. A redeploy that introduces no new migrations is a no-op on the database.
Local development
See LOCAL_DEV.md for the fresh-clone-to-running sequence using the Supabase CLI.
First-time provisioning
For initial server provisioning (Docker, the Supabase stack, Caddy, firewall, SSH hardening, deploy-key registration, the systemd unit, backup cron), follow DEPLOY_DO_SELFHOSTED.md end to end.
Operational checklist
- Monitor
/var/log/hackerspace-deploy.logfor deploy outcomes. - Verify backups by restoring
pg_*.sql.gzto a staging instance quarterly. - Rotate the Supabase service-role key and JWT secret if the
.envon the Droplet is ever exposed. - Keep the host OS patched. The bootstrap installs
unattended-upgrades.