Overview
Zephyr uses type-safe environment variables via @t3-oss/env-nextjs. Variables are validated at build time, ensuring you never miss required configuration.
Environment variables are defined in apps/web/keys.ts and apps/auth/keys.ts with Zod schemas for validation.
Quick Setup
The fastest way to configure environment variables:
bun run env:devThis copies .env.example files from both apps into .env files with pre-configured values that work with Docker.
Environment files are required! Several critical variables (database URLs, Redis, MinIO endpoint, Resend API key, Better Auth secret) have no defaults and must be set in .env files.
Environment Files
Apps look for environment variables in:
apps/web/.env- Web app configurationapps/auth/.env- Auth service configuration.env.examplefiles exist as templates (gitignored, so you may not see them)
.env files are gitignored. Never commit secrets to the repository!
Required Environment Variables
These variables must be set - they have no defaults in keys.ts:
apps/web/.env (Required)
# Database - REQUIRED (no defaults)
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
POSTGRES_PRISMA_URL="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
POSTGRES_URL_NON_POOLING="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
# Caching - REQUIRED (no default)
REDIS_URL="redis://:zephyrredis@localhost:6379/0"
# Object Storage - REQUIRED (no default for ENDPOINT)
MINIO_ENDPOINT="http://localhost:9000"apps/auth/.env (Required)
# Database - REQUIRED (same as web app)
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
POSTGRES_PRISMA_URL="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
POSTGRES_URL_NON_POOLING="postgresql://postgres:postgres@localhost:5433/zephyr?schema=public"
# Email Service - REQUIRED (no default)
RESEND_API_KEY="re_your_api_key_here"
# Auth Encryption - REQUIRED (no default)
BETTER_AUTH_SECRET="your-secret-here-min-32-chars"Get a Resend API key: Sign up at resend.com for free. Required for email verification during signup.
Optional Environment Variables
These have defaults in keys.ts but can be overridden:
Object Storage (MinIO)
MINIO_ROOT_USER="minioadmin" # Default: minioadmin
MINIO_ROOT_PASSWORD="minioadmin" # Default: minioadmin
MINIO_BUCKET_NAME="uploads" # Default: uploads
MINIO_HOST="localhost" # Default: localhost
MINIO_PORT="9000" # Default: 9000
MINIO_CONSOLE_PORT="9001" # Default: 9001
MINIO_ENABLE_OBJECT_LOCKING="on" # Default: onCaching & Search
# Meilisearch
MEILISEARCH_URL="http://localhost:7700" # Default: http://localhost:7700
MEILISEARCH_MASTER_KEY="masterKey123" # Default: masterKey123
# RabbitMQ (not actively used)
RABBITMQ_URL="amqp://admin:admin123@localhost:5672" # Default: amqp://admin:admin123@localhost:5672
# TimescaleDB (analytics)
TIMESCALEDB_URL="postgresql://postgres:postgres@localhost:5434/zephyr-logs?schema=public" # Has defaultApplication
NODE_ENV="development" # Default: development
NEXT_TELEMETRY_DISABLED="1" # Default: 1
TURBO_TELEMETRY_DISABLED="1" # Default: 1
BETTER_AUTH_TELEMETRY="0" # Default: 0
SUPPORT_EMAIL="info@zephyyrr.in" # Default: info@zephyyrr.inPublic Variables (Client-Side)
NEXT_PUBLIC_URL="http://localhost:3000" # Default: http://localhost:3000
NEXT_PUBLIC_AUTH_URL="http://localhost:3001" # Default: http://localhost:3001
NEXT_PUBLIC_PORT="3000" # Default: 3000
NEXT_PUBLIC_MINIO_ENDPOINT="http://localhost:9000" # Default: http://localhost:9000Optional: OAuth Providers
To enable social authentication, add provider credentials to apps/auth/.env:
Google OAuth
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"GitHub OAuth
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"Discord OAuth
DISCORD_CLIENT_ID="your-discord-client-id"
DISCORD_CLIENT_SECRET="your-discord-client-secret"Twitter OAuth
TWITTER_CLIENT_ID="your-twitter-client-id"
TWITTER_CLIENT_SECRET="your-twitter-client-secret"Reddit OAuth
REDDIT_CLIENT_ID="your-reddit-client-id"
REDDIT_CLIENT_SECRET="your-reddit-client-secret"Optional: Cron Job Security
To secure cron job endpoints:
# Set a secret token for cron job authentication
CRON_SECRET="your-random-secret-string"
# or
CRON_SECRET_KEY="your-random-secret-string"Pass as Authorization: Bearer {token} when calling cron endpoints.
Creating .env Files
Method 1: Using env:dev Script (Recommended)
The fastest and most reliable way:
bun run env:devThis copies .env.example files from both apps, which contain all the required configuration pre-filled with values that work with Docker.
Success message: ✅ Environment files copied successfully
After running this, you must edit apps/auth/.env to add your Resend API key:
# In apps/auth/.env
RESEND_API_KEY="re_your_actual_api_key"Method 2: Manual Creation
If you prefer to create files manually or customize values, the .env.example files provide the template. The required minimal configuration is shown in the sections above.
Environment Validation
Zephyr validates environment variables at build time using Zod schemas in keys.ts files.
If you’re missing a required variable, you’ll see:
❌ Invalid environment variables:
{
"DATABASE_URL": [
"Required"
]
}Type safety: All environment variables are fully typed in TypeScript!
import { keys } from "./keys";
// TypeScript knows all available keys
const dbUrl = keys.DATABASE_URL; // string
const port = keys.NEXT_PUBLIC_PORT; // numberProduction Configuration
For production deployments:
- Use strong passwords: Replace all default passwords
- Enable SSL: Use
postgresql://with?sslmode=require - Use managed services: RDS, ElastiCache, S3, etc.
- Set NODE_ENV: Always
"production" - Configure secrets management: Use AWS Secrets Manager, Vault, etc.
Example production variables:
NODE_ENV="production"
DATABASE_URL="postgresql://user:pass@your-db.region.rds.amazonaws.com:5432/zephyr?sslmode=require"
REDIS_URL="rediss://your-redis.cache.amazonaws.com:6379"
MINIO_ENDPOINT="https://your-bucket.s3.amazonaws.com"
NEXT_PUBLIC_URL="https://zephyyrr.in"
NEXT_PUBLIC_AUTH_URL="https://auth.zephyyrr.in"Troubleshooting
”Invalid environment variables” error
Cause: Missing or incorrectly formatted environment variables.
Solution: Check the error message for which variables are invalid, then verify:
- Variable exists in
.envfile - Format matches expected type (URL, number, string)
- No typos in variable names
Apps can’t connect to services
Cause: Connection strings don’t match running services.
Solution for Docker:
# Verify services are running
docker ps
# Check service logs
docker compose -f docker/docker-compose.dev.yml logs postgres-dev
docker compose -f docker/docker-compose.dev.yml logs redis-devSolution for Native:
- Verify services are running:
pg_isready,redis-cli ping - Check port numbers match your
.env - Verify credentials are correct
OAuth not working
Cause: Missing OAuth credentials or incorrect redirect URLs.
Solution:
- Add credentials to
apps/auth/.env - Configure redirect URLs in OAuth provider dashboard:
- Authorized redirect URIs:
http://localhost:3001/api/auth/callback/{provider} - Replace
{provider}with:google,github,discord,twitter,reddit
- Authorized redirect URIs:
Next Steps
- Verification - Test your configuration
- Troubleshooting - Fix common issues