Production Setup
Requirements
Section titled “Requirements”- Node.js 20+
- PostgreSQL 14+
- A domain with wildcard DNS or multiple subdomains
DNS Configuration
Section titled “DNS Configuration”For SSO to work, all SaaS frontends and saas-core must share a parent domain:
auth.example.com → saas-core instancetobby.example.com → Acme frontendstudio.example.com → Beta frontendThe session cookie is set with Domain=.example.com, which means all
*.example.com subdomains receive it.
HTTPS is required for:
- Secure cookies — Better Auth uses
__Secure-prefixed cookies in production, which require HTTPS - OAuth redirects — Google, Apple, and GitHub require HTTPS callback URLs
- CORS — Modern browsers enforce same-origin policies over HTTPS
Use a reverse proxy (Caddy, Nginx, Cloudflare) to terminate TLS.
Environment Variables
Section titled “Environment Variables”PORT=3000DATABASE_URL=postgresql://user:pass@host:5432/saas_coreLOG_LEVEL=infoADMIN_TOKEN=<openssl rand -hex 32>BETTER_AUTH_SECRET=<openssl rand -hex 32>BETTER_AUTH_BASE_URL=https://auth.example.comAUTH_COOKIE_DOMAIN=.example.comSAAS_TRUSTED_ORIGINS=https://tobby.example.com,https://studio.example.comOAUTH_LOGIN_PAGE=/loginOAUTH_CONSENT_PAGE=/consentProcess Management
Section titled “Process Management”Recommended: use a process manager (systemd, PM2) to keep saas-core running:
# systemd unit example[Unit]Description=saas-coreAfter=network.target postgresql.service
[Service]Type=simpleUser=deployWorkingDirectory=/opt/saas-coreExecStart=/usr/bin/node /opt/saas-core/dist/server.jsEnvironmentFile=/opt/saas-core/.envRestart=alwaysRestartSec=5
[Install]WantedBy=multi-user.targetnpm run build # Builds the backend to dist/npm -w saas-admin run build # Builds the admin consoleDatabase Migrations
Section titled “Database Migrations”Run migrations on deploy:
npm run db:migrateThis is idempotent — safe to run on every deploy.