Runtime Configuration
Learn about runtime configuration in Nuxt Umbu, including secrets management, environment variables, and secure configuration practices.
Overview
Nuxt Umbu leverages Nuxt's runtime configuration system to manage sensitive data like API credentials, secrets, and environment-specific settings. This ensures sensitive information never leaks to the client bundle.
Runtime Config vs Public Config
Runtime Config (Server-Side Only)
Runtime config is only available on the server and never exposed to the client:
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
// Server-side only
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
})
Public Runtime Config (Client-Side)
Public config is exposed to the client:
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
// Available on both client and server
auth: {
provider: 'sanctum',
cookie: {
prefix: 'auth.',
options: {
httpOnly: false,
secure: false,
sameSite: 'Lax'
}
}
}
}
}
})
Passport Secrets Configuration
For Passport provider, you must configure secrets in runtime config:
Required Structure
runtimeConfig: {
secret: {
[strategyName]: {
client_id: string | number,
client_secret: string,
grant_type: 'password' | 'authorization_code'
}
}
}
Example Configuration
// nuxt.config.ts
export default defineNuxtConfig({
auth: {
provider: 'passport',
strategies: {
password: {
endpoints: {
login: { url: '/oauth/token', method: 'post' },
user: { url: '/api/user', method: 'get' }
},
redirect: {
login: '/login',
logout: '/'
}
}
}
},
runtimeConfig: {
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
})
Multiple Strategies
runtimeConfig: {
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
},
social: {
client_id: process.env.NUXT_AUTH_SOCIAL_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_SOCIAL_CLIENT_SECRET,
grant_type: 'authorization_code'
}
}
}
Environment Variables
Using .env Files
Create environment files for different environments:
# .env
NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_client_secret
# .env.production
NUXT_AUTH_PASSWORD_CLIENT_ID=prod_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=prod_client_secret
# .env.development
NUXT_AUTH_PASSWORD_CLIENT_ID=dev_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=dev_client_secret
Accessing Environment Variables
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
})
Environment-Specific Config
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
secret: {
password: {
client_id: process.env.NODE_ENV === 'production'
? process.env.NUXT_AUTH_PASSWORD_CLIENT_ID
: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NODE_ENV === 'production'
? process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET
: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
})
Accessing Runtime Config
Server-Side Access
// server/api/config.get.ts
export default defineEventHandler((event) => {
const config = useRuntimeConfig()
const secret = config.secret.password
return {
clientId: secret.client_id
// Never expose client_secret!
}
})
Client-Side Access (Public Config Only)
// In components
const config = useRuntimeConfig()
const authConfig = config.public.auth
console.log(authConfig.provider) // 'sanctum' or 'passport'
Validation
The module automatically validates runtime config:
Secret Validation
For Passport provider, the module validates:
- Secret exists
if (!runtimeConfig.secret) { logger.error('Missing "runtimeConfig.secret" in nuxt.config.ts') } - Secret structure is valid
function isValidSecretConfig(secret: unknown): secret is Record<string, AuthSecretConfig> { return typeof secret === 'object' && secret !== null && Object.values(secret).every(config => typeof config === 'object' && config !== null && 'client_id' in config && 'client_secret' in config && 'grant_type' in config ) } - Strategy correspondence
Object.entries(runtimeConfig.secret).forEach(([key, config]) => { if (!options.strategies[key]) { logger.error(`Strategy "${key}" found in secret but not in strategies`) } })
Common Validation Errors
Missing runtimeConfig.secret
Error: Missing "runtimeConfig.secret" in nuxt.config.ts
Solution:
runtimeConfig: {
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
Invalid secret structure
Error: Invalid "runtimeConfig.secret" structure in nuxt.config.ts
Solution: Ensure each secret has client_id, client_secret, and grant_type.
Strategy not found
Error: Strategy "password" found in secret but not in options.strategies
Solution: Ensure strategy names match between strategies and secret.
Security Best Practices
Never Expose Secrets
// ❌ BAD - Exposes secret to client
export default defineNuxtConfig({
runtimeConfig: {
public: {
secret: {
client_secret: 'secret' // This will be in client bundle!
}
}
}
})
// ✅ GOOD - Secret stays on server
export default defineNuxtConfig({
runtimeConfig: {
secret: {
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET
}
}
})
Use Environment Variables
# .env
NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_secret_here
# Add to .gitignore
.env
.env.local
.env.*.local
Validate at Build Time
// nuxt.config.ts
if (!process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET) {
throw new Error('NUXT_AUTH_PASSWORD_CLIENT_SECRET environment variable is required')
}
Use Different Secrets per Environment
# .env.development
NUXT_AUTH_PASSWORD_CLIENT_SECRET=dev_secret
# .env.staging
NUXT_AUTH_PASSWORD_CLIENT_SECRET=staging_secret
# .env.production
NUXT_AUTH_PASSWORD_CLIENT_SECRET=prod_secret
Common Patterns
Multi-Environment Configuration
// nuxt.config.ts
export default defineNuxtConfig({
auth: {
provider: 'passport',
cookie: {
prefix: process.env.NODE_ENV === 'production' ? '__Secure-' : 'auth.',
options: {
secure: process.env.NODE_ENV === 'production',
httpOnly: process.env.NODE_ENV === 'production',
sameSite: process.env.NODE_ENV === 'production' ? 'Strict' : 'Lax'
}
}
},
runtimeConfig: {
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
}
}
})
Feature Flag Configuration
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
auth: {
provider: process.env.AUTH_PROVIDER || 'sanctum',
enable2FA: process.env.ENABLE_2FA === 'true'
}
}
}
})
Dynamic Endpoint Configuration
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
auth: {
apiBase: process.env.API_BASE_URL || 'https://api.example.com'
}
}
}
})
// Use in strategy configuration
strategies: {
default: {
endpoints: {
login: {
url: `${useRuntimeConfig().public.auth.apiBase}/login`,
method: 'post'
}
}
}
}
Deployment Configuration
Vercel
# Set environment variables in Vercel dashboard
NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_client_secret
Netlify
# Set in Netlify environment variables
NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_client_secret
Docker
# Dockerfile
ENV NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
# Secret injected at runtime via docker-compose.yml or deployment platform
# docker-compose.yml
services:
app:
environment:
- NUXT_AUTH_PASSWORD_CLIENT_ID=${NUXT_AUTH_PASSWORD_CLIENT_ID}
- NUXT_AUTH_PASSWORD_CLIENT_SECRET=${NUXT_AUTH_PASSWORD_CLIENT_SECRET}
Traditional Server
# Set environment variables
export NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
export NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_client_secret
# Or use .env file
cp .env.example .env
# Edit .env with your values
Troubleshooting
Config Not Loading
Problem: Runtime config not available
Solution:
- Restart dev server after config changes
- Check that config is in
nuxt.config.ts - Verify environment variables are set
- Check for typos in config keys
Secrets Not Working
Problem: Passport secrets not being used
Solution:
- Verify
runtimeConfig.secretstructure - Check that strategy names match
- Ensure environment variables are set
- Check module logs for validation errors
Environment Variables Not Available
Problem: process.env values are undefined
Solution:
- Ensure
.envfile exists - Check that
.envis in project root - Verify variable names match
- Restart dev server after adding variables
Public Config Exposing Secrets
Problem: Sensitive data in client bundle
Solution:
- Move secrets from
publicto rootruntimeConfig - Check browser network tab for exposed data
- Use
nuxi buildand inspect bundle - Review
runtimeConfig.publiccontents
Best Practices Summary
- Always use runtime config for secrets: Never put secrets in public config
- Use environment variables: Keep secrets out of code
- Validate at build time: Fail fast if config is missing
- Different environments: Use different secrets per environment
- Never commit secrets: Add
.envto.gitignore - Rotate secrets regularly: Update secrets periodically
- Use strong secrets: Generate random, complex secrets
- Monitor for leaks: Check bundles and network traffic
- Document config: Document required environment variables
- Use type safety: Leverage TypeScript for config validation
Configuration Template
Complete Example
// nuxt.config.ts
export default defineNuxtConfig({
// Auth module configuration (public)
auth: {
provider: process.env.AUTH_PROVIDER || 'sanctum',
cookie: {
prefix: process.env.NODE_ENV === 'production' ? '__Secure-' : 'auth.',
options: {
httpOnly: process.env.NODE_ENV === 'production',
secure: process.env.NODE_ENV === 'production',
sameSite: process.env.NODE_ENV === 'production' ? 'Strict' : 'Lax',
priority: 'high'
}
},
strategies: {
default: {
endpoints: {
login: { url: '/login', method: 'post' },
user: { url: '/api/user', method: 'get' },
logout: { url: '/logout', method: 'post' }
},
redirect: {
login: '/login',
logout: '/',
home: '/dashboard'
}
}
}
},
// Runtime configuration
runtimeConfig: {
// Server-side only (secrets)
secret: {
password: {
client_id: process.env.NUXT_AUTH_PASSWORD_CLIENT_ID,
client_secret: process.env.NUXT_AUTH_PASSWORD_CLIENT_SECRET,
grant_type: 'password'
}
},
// Public (client and server)
public: {
auth: {
provider: process.env.AUTH_PROVIDER || 'sanctum',
apiBase: process.env.API_BASE_URL || 'https://api.example.com'
}
}
}
})
Environment File Template
# .env.example
AUTH_PROVIDER=sanctum
API_BASE_URL=https://api.example.com
# Passport (if using passport provider)
NUXT_AUTH_PASSWORD_CLIENT_ID=your_client_id
NUXT_AUTH_PASSWORD_CLIENT_SECRET=your_client_secret
# Sanctum (if using sanctum provider)
SANCTUM_CSRF_URL=/sanctum/csrf-cookie