This library is in early development. Expect breaking changes.
Guides

Production Deployment

Checklist and best practices for deploying Nuxt Better Auth in production.

Environment Variables

Production requires these environment variables:

.env.production
# Required: 32+ character secret for session encryption
NUXT_BETTER_AUTH_SECRET="your-32-character-secret-here-minimum"

# 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'))"

The secret must be at least 32 characters. Shorter secrets will cause the module to throw an error.

Security Checklist

Before Deploying

  • NUXT_BETTER_AUTH_SECRET is set and 32+ characters
  • NUXT_PUBLIC_SITE_URL set (or using Vercel/Cloudflare/Netlify auto-detection)
  • OAuth redirect URIs configured for production domain
  • NODE_ENV=production is set (disables devtools)

Route Protection

Route rules and definePageMeta are for UX (redirects). Always protect API endpoints with requireUserSession:

server/api/protected.get.ts
export default defineEventHandler(async (event) => {
  const { user } = await requireUserSession(event)
  return { data: 'protected' }
})

Rate Limiting

The module does not include built-in rate limiting. Implement rate limiting at the infrastructure level or use a middleware:

server/middleware/rate-limit.ts
import { getRequestIP } from 'h3'

const requests = new Map<string, number[]>()
const WINDOW_MS = 60_000 // 1 minute
const MAX_REQUESTS = 100

export default defineEventHandler((event) => {
  if (!event.path.startsWith('/api/auth'))
    return

  const ip = getRequestIP(event) || 'unknown'
  const now = Date.now()
  const windowStart = now - WINDOW_MS

  const timestamps = (requests.get(ip) || []).filter(t => t > windowStart)
  timestamps.push(now)
  requests.set(ip, timestamps)

  if (timestamps.length > MAX_REQUESTS) {
    throw createError({ statusCode: 429, message: 'Too many requests' })
  }
})

For production, consider using Cloudflare rate limiting or a Redis-backed solution.

NuxtHub Deployment

When deploying with NuxtHub:

  1. Database migrations run automatically during build
  2. Set environment variables in your deployment platform
  3. Ensure @nuxthub/core is listed before @onmax/nuxt-better-auth in modules
nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@nuxthub/core',  // Must be first
    '@onmax/nuxt-better-auth',
  ],
})

Common Issues

"BETTER_AUTH_SECRET must be at least 32 characters"

Your secret is too short. Generate a new one using the command above.

"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/google
  • https://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.