Production Deployment
Use this guide when your auth flow works locally and you are preparing to ship it to a real environment.
Environment Variables
Production requires a singular or versioned auth secret at runtime:
# Required: 32+ character secret for session encryption
NUXT_BETTER_AUTH_SECRET="your-32-character-secret-here-minimum"
# Alternative for non-destructive rotation
# BETTER_AUTH_SECRETS="2:current-secret-must-be-at-least-32-characters,1:previous-secret-must-be-at-least-32-characters"
# Optional: Auto-detected on Vercel/Cloudflare/Netlify
NUXT_PUBLIC_SITE_URL="https://your-app.com"
# OAuth provider credentials (if using)
GOOGLE_CLIENT_ID="..."
GOOGLE_CLIENT_SECRET="..."
Generate a Secure Secret
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Singular secrets must be at least 32 characters. Shorter NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET values cause auth initialization to throw at runtime. Better Auth validates versioned BETTER_AUTH_SECRETS/secrets entries and warns when the current key is too short.
Security Checklist
Before Deploying
-
NUXT_BETTER_AUTH_SECRET,BETTER_AUTH_SECRET,BETTER_AUTH_SECRETS, ordefineServerAuth({ secrets })is configured -
NUXT_PUBLIC_SITE_URLset (or using Vercel/Cloudflare/Netlify auto-detection) -
trustedOriginsincludes every active frontend origin (primary domain and preview domain, if used) - OAuth redirect URIs configured for production domain
-
NODE_ENV=productionis set (disables devtools)
Route Protection
Route rules and definePageMeta are for UX (redirects). Always protect API endpoints with requireUserSession:
export default defineEventHandler(async (event) => {
const { user } = await requireUserSession(event)
return { data: 'protected' }
})
Rate Limiting
Better Auth enables its built-in rate limiter by default in production with a 60-second window and a maximum of 100 requests. It is disabled by default in development.
Better Auth stores rate-limit data in memory by default. For serverless or multi-instance deployments, configure database, secondary storage, or custom storage instead of relying on separate per-instance counters.
Separate Build and Runtime Environments
Some platforms, including Cloudflare Workers Builds, expose build-time and runtime environment variables separately. Your singular or versioned auth secret must be available to the deployed runtime, but it does not need to be present in the build container.
Trusted Origins for Preview Environments
If your workflow uses preview URLs (for example, *.workers.dev), include those origins in your Better Auth server config.
import { defineServerAuth } from '@nuxtjs/better-auth/config'
export default defineServerAuth({
trustedOrigins: [
'https://your-app.com',
'https://your-preview.workers.dev',
],
})
Without the preview origin, browser auth flows can fail because Better Auth rejects cookie-based requests from unknown origins.
NuxtHub Deployment
When deploying with NuxtHub:
- Database migrations run automatically during build
- Set environment variables in your deployment platform
- Ensure
@nuxthub/coreis listed before@nuxtjs/better-authin modules
export default defineNuxtConfig({
modules: [
'@nuxthub/core', // Must be first
'@nuxtjs/better-auth',
],
})
Common Issues
"Singular auth secret must be at least 32 characters"
Your NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET is too short. Generate a new one using the command above. This error is raised when auth initializes at runtime. NUXT_BETTER_AUTH_SECRET remains the recommended variable.
"An auth secret is required in production"
The deployed server runtime could not resolve an auth secret. Set NUXT_BETTER_AUTH_SECRET, BETTER_AUTH_SECRET, BETTER_AUTH_SECRETS, or secrets in defineServerAuth.
"siteUrl required in production"
The module auto-detects URLs on Vercel, Cloudflare Pages, and Netlify. For other platforms, set NUXT_PUBLIC_SITE_URL to your production domain.
OAuth Redirects Fail
Ensure your OAuth provider's authorized redirect URIs include:
https://your-app.com/api/auth/callback/googlehttps://your-app.com/api/auth/callback/github- (Replace with your domain and providers)
DevTools
DevTools are automatically disabled in production (NODE_ENV=production). The /api/_better-auth/* endpoints and /__better-auth-devtools page are not registered.