ShopySeed

Environment Variables Reference

Complete reference for all environment variables used in ShopySeed across development, staging, and production.

Complete reference for all environment variables used in ShopySeed. This guide covers development, staging, and production configurations.

Environment Files

FilePurposeWhen to Use
apps/api/.envAPI development settingsLocal development
apps/api/.env.productionAPI production settingsProduction deployment
apps/web/.env.localWeb development settingsLocal development
apps/web/.env.productionWeb production settingsProduction deployment
.env.productionGlobal production settingsDocker Compose production

Backend API Variables (apps/api/.env)

Application Configuration

VariableRequiredDefaultDescription
NODE_ENVdevelopmentApplication environment (development, staging, production)
PORT3011Port for the API server to listen on
LOG_LEVELdebugLogging level (debug, info, warn, error)
API_PREFIXapiGlobal API route prefix

Examples:

# Development
NODE_ENV=development
PORT=3011
LOG_LEVEL=debug
API_PREFIX=api

# Production
NODE_ENV=production
PORT=3011
LOG_LEVEL=info
API_PREFIX=api

Database Configuration

VariableRequiredDefaultDescription
DATABASE_URL-Complete PostgreSQL connection string
POSTGRES_USER-PostgreSQL username
POSTGRES_PASSWORD-PostgreSQL password
POSTGRES_DB-PostgreSQL database name
POSTGRES_HOSTlocalhostPostgreSQL host
POSTGRES_PORT5433PostgreSQL port

Examples:

# Development
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/shopyseed_dev?schema=public
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=shopyseed_dev
POSTGRES_HOST=localhost
POSTGRES_PORT=5433

# Production
DATABASE_URL=postgresql://postgres:STRONG_PASSWORD@db-host:5432/shopyseed_prod?schema=public
POSTGRES_USER=postgres
POSTGRES_PASSWORD=STRONG_PASSWORD_HERE
POSTGRES_DB=shopyseed_prod
POSTGRES_HOST=db-host
POSTGRES_PORT=5432

Notes:

  • DATABASE_URL takes precedence over individual connection variables
  • Use schema=public for the main schema, tenant schemas are managed automatically
  • Connection pooling is handled by Prisma automatically

Redis Configuration

VariableRequiredDefaultDescription
REDIS_URL-Complete Redis connection string
REDIS_HOSTlocalhostRedis host
REDIS_PORT6379Redis port
REDIS_PASSWORD-Redis password (if required)
REDIS_DB0Redis database number

Examples:

# Development (no auth)
REDIS_URL=redis://localhost:6379
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB=0

# Production (with auth)
REDIS_URL=redis://username:password@redis-host:6379/0
REDIS_HOST=redis-host
REDIS_PORT=6379
REDIS_PASSWORD=redis-password
REDIS_DB=0

Notes:

  • Redis is optional but recommended for production
  • Used for session storage and caching
  • If not configured, in-memory storage is used (not recommended for production)

Authentication & Security

VariableRequiredDefaultDescription
JWT_SECRET-Secret key for signing JWT tokens (min 32 characters)
JWT_EXPIRES_IN15mAccess token expiration time
REFRESH_TOKEN_EXPIRES_IN7dRefresh token expiration time
BCRYPT_ROUNDS12BCrypt hashing rounds for passwords

Examples:

# Generate a secure JWT secret
JWT_SECRET=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

# Token expiration
JWT_EXPIRES_IN=15m
REFRESH_TOKEN_EXPIRES_IN=7d

# Password hashing strength
BCRYPT_ROUNDS=12

Generate secure JWT secret:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# or
openssl rand -hex 32

CORS Configuration

VariableRequiredDefaultDescription
CORS_ORIGINShttp://localhost:3000Allowed frontend origins (comma-separated)
CORS_CREDENTIALStrueAllow credentials in CORS requests

Examples:

# Development
CORS_ORIGINS=http://localhost:3000,http://localhost:3001

# Production
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com,https://app.yourdomain.com

# Multiple environments
CORS_ORIGINS=https://staging.yourdomain.com,https://yourdomain.com,https://www.yourdomain.com

Rate Limiting

VariableRequiredDefaultDescription
RATE_LIMIT_TTL60000Rate limit window in milliseconds
RATE_LIMIT_MAX100Maximum requests per window
RATE_LIMIT_AUTH_TTL60000Auth endpoint rate limit window
RATE_LIMIT_AUTH_MAX10Auth endpoint max requests per window

Examples:

# Development (relaxed)
RATE_LIMIT_TTL=60000     # 1 minute
RATE_LIMIT_MAX=1000      # 1000 requests per minute
RATE_LIMIT_AUTH_TTL=60000
RATE_LIMIT_AUTH_MAX=20   # 20 auth attempts per minute

# Production (strict)
RATE_LIMIT_TTL=60000     # 1 minute
RATE_LIMIT_MAX=100       # 100 requests per minute
RATE_LIMIT_AUTH_TTL=60000
RATE_LIMIT_AUTH_MAX=5    # 5 auth attempts per minute

Stripe Integration

VariableRequiredDefaultDescription
STRIPE_SECRET_KEY-Stripe secret API key
STRIPE_WEBHOOK_SECRET-Stripe webhook endpoint secret
STRIPE_WEBHOOK_TOLERANCE300Webhook timestamp tolerance in seconds

Examples:

# Development (test keys)
STRIPE_SECRET_KEY=sk_test_51ABC123...
STRIPE_WEBHOOK_SECRET=whsec_abc123...

# Production (live keys)
STRIPE_SECRET_KEY=sk_live_51XYZ789...
STRIPE_WEBHOOK_SECRET=whsec_xyz789...

Getting Stripe keys:

  1. API Keys: Stripe Dashboard → Developers → API Keys
  2. Webhook Secret: Stripe Dashboard → Developers → Webhooks → Select endpoint → Reveal signing secret

Email Configuration

VariableRequiredDefaultDescription
EMAIL_HOST-SMTP server hostname
EMAIL_PORT587SMTP server port
EMAIL_USER-SMTP username
EMAIL_PASSWORD-SMTP password
EMAIL_FROMnoreply@localhostFrom email address
EMAIL_FROM_NAMEShopySeedFrom name

Examples:

# Resend (recommended)
EMAIL_HOST=smtp.resend.com
EMAIL_PORT=587
EMAIL_USER=resend
EMAIL_PASSWORD=re_abc123...
EMAIL_FROM=noreply@yourdomain.com
EMAIL_FROM_NAME="Your SaaS Name"

# SendGrid
EMAIL_HOST=smtp.sendgrid.net
EMAIL_PORT=587
EMAIL_USER=apikey
EMAIL_PASSWORD=SG.abc123...
EMAIL_FROM=noreply@yourdomain.com
EMAIL_FROM_NAME="Your SaaS Name"

# Amazon SES
EMAIL_HOST=email-smtp.us-east-1.amazonaws.com
EMAIL_PORT=587
EMAIL_USER=AKIA...
EMAIL_PASSWORD=BHs5...
EMAIL_FROM=noreply@yourdomain.com
EMAIL_FROM_NAME="Your SaaS Name"

# Development (optional - uses MailHog if not configured)
# Leave empty to use MailHog for testing

OAuth Providers

VariableRequiredDefaultDescription
GOOGLE_CLIENT_ID-Google OAuth client ID
GOOGLE_CLIENT_SECRET-Google OAuth client secret
GITHUB_CLIENT_ID-GitHub OAuth app ID
GITHUB_CLIENT_SECRET-GitHub OAuth app secret
OAUTH_REDIRECT_URLhttp://localhost:3000/auth/callbackOAuth callback URL

Examples:

# Google OAuth
GOOGLE_CLIENT_ID=123456789-abc123.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-abc123...

# GitHub OAuth
GITHUB_CLIENT_ID=abc123...
GITHUB_CLIENT_SECRET=github_pat_123...

# Callback URL (must match OAuth app settings)
OAUTH_REDIRECT_URL=https://yourdomain.com/auth/callback

Setting up OAuth:

  1. Google: Google Cloud Console → APIs & Services → Credentials
  2. GitHub: GitHub Settings → OAuth Apps

File Upload & Storage

VariableRequiredDefaultDescription
UPLOAD_MAX_SIZE10485760Maximum file size in bytes (10MB)
UPLOAD_ALLOWED_TYPESimage/jpeg,image/png,image/gifAllowed MIME types (comma-separated)
AWS_ACCESS_KEY_ID-AWS access key for S3 uploads
AWS_SECRET_ACCESS_KEY-AWS secret key for S3 uploads
AWS_REGIONus-east-1AWS region for S3
AWS_S3_BUCKET-S3 bucket name for file uploads

Examples:

# Local file storage (development)
UPLOAD_MAX_SIZE=10485760  # 10MB
UPLOAD_ALLOWED_TYPES=image/jpeg,image/png,image/gif,application/pdf

# S3 storage (production)
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=abc123...
AWS_REGION=us-east-1
AWS_S3_BUCKET=your-app-uploads

Frontend Web Variables (apps/web/.env.local)

API Connection

VariableRequiredDefaultDescription
NEXT_PUBLIC_API_URLhttp://localhost:3011Backend API base URL
NEXT_PUBLIC_APP_URLhttp://localhost:3000Frontend app base URL

Examples:

# Development
NEXT_PUBLIC_API_URL=http://localhost:3011
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Production
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
NEXT_PUBLIC_APP_URL=https://yourdomain.com

# Staging
NEXT_PUBLIC_API_URL=https://api-staging.yourdomain.com
NEXT_PUBLIC_APP_URL=https://staging.yourdomain.com

Stripe Configuration

VariableRequiredDefaultDescription
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY-Stripe publishable key

Examples:

# Development
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51ABC123...

# Production  
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_51XYZ789...

OAuth URLs

VariableRequiredDefaultDescription
NEXT_PUBLIC_GOOGLE_OAUTH_URL-Google OAuth initiation URL
NEXT_PUBLIC_GITHUB_OAUTH_URL-GitHub OAuth initiation URL

Examples:

# Development
NEXT_PUBLIC_GOOGLE_OAUTH_URL=http://localhost:3011/auth/oauth/google
NEXT_PUBLIC_GITHUB_OAUTH_URL=http://localhost:3011/auth/oauth/github

# Production
NEXT_PUBLIC_GOOGLE_OAUTH_URL=https://api.yourdomain.com/auth/oauth/google
NEXT_PUBLIC_GITHUB_OAUTH_URL=https://api.yourdomain.com/auth/oauth/github

Analytics & Tracking

VariableRequiredDefaultDescription
NEXT_PUBLIC_GA_ID-Google Analytics tracking ID
NEXT_PUBLIC_POSTHOG_KEY-PostHog project API key
NEXT_PUBLIC_SENTRY_DSN-Sentry error tracking DSN

Examples:

# Google Analytics
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX

# PostHog
NEXT_PUBLIC_POSTHOG_KEY=phc_abc123...

# Sentry
NEXT_PUBLIC_SENTRY_DSN=https://abc123@sentry.io/123456

Global Production Variables (.env.production)

Docker Configuration

VariableRequiredDefaultDescription
API_PORT3011Exposed API port
WEB_PORT3000Exposed web port
POSTGRES_PORT5433Exposed PostgreSQL port
REDIS_PORT6379Exposed Redis port

Examples:

# Standard ports
API_PORT=3011
WEB_PORT=3000
POSTGRES_PORT=5433
REDIS_PORT=6379

# Custom ports (if conflicts exist)
API_PORT=8011
WEB_PORT=8000
POSTGRES_PORT=5434
REDIS_PORT=6380

Monitoring & Observability

VariableRequiredDefaultDescription
GRAFANA_PASSWORD-Grafana admin password
PROMETHEUS_RETENTION15dPrometheus data retention period

Examples:

# Monitoring
GRAFANA_PASSWORD=secure_grafana_password
PROMETHEUS_RETENTION=30d

Environment-Specific Examples

Complete Development Configuration

apps/api/.env

# Application
NODE_ENV=development
PORT=3011
LOG_LEVEL=debug

# Database  
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/shopyseed_dev?schema=public
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=shopyseed_dev
POSTGRES_PORT=5433

# Redis
REDIS_URL=redis://localhost:6379

# Security (development values)
JWT_SECRET=development-jwt-secret-minimum-32-characters
CORS_ORIGINS=http://localhost:3000

# Rate limiting (relaxed for development)
RATE_LIMIT_TTL=60000
RATE_LIMIT_MAX=1000
RATE_LIMIT_AUTH_MAX=20

# Stripe (test keys)
STRIPE_SECRET_KEY=sk_test_your_test_key
STRIPE_WEBHOOK_SECRET=whsec_your_test_webhook_secret

# Email (optional - uses MailHog if not set)
# EMAIL_HOST=smtp.resend.com
# EMAIL_PORT=587
# EMAIL_USER=resend
# EMAIL_PASSWORD=your_test_api_key
# EMAIL_FROM=dev@localhost

# OAuth (optional)
# GOOGLE_CLIENT_ID=your-google-client-id
# GOOGLE_CLIENT_SECRET=your-google-client-secret

apps/web/.env.local

# API Connection
NEXT_PUBLIC_API_URL=http://localhost:3011
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_test_publishable_key

# OAuth
NEXT_PUBLIC_GOOGLE_OAUTH_URL=http://localhost:3011/auth/oauth/google
NEXT_PUBLIC_GITHUB_OAUTH_URL=http://localhost:3011/auth/oauth/github

Complete Production Configuration

apps/api/.env.production

# Application
NODE_ENV=production
PORT=3011
LOG_LEVEL=info

# Database
DATABASE_URL=postgresql://postgres:STRONG_DB_PASSWORD@postgres:5432/shopyseed_prod?schema=public
POSTGRES_USER=postgres
POSTGRES_PASSWORD=STRONG_DB_PASSWORD
POSTGRES_DB=shopyseed_prod

# Redis
REDIS_URL=redis://redis:6379

# Security
JWT_SECRET=SECURE_32_CHAR_JWT_SECRET_FOR_PRODUCTION
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com

# Rate limiting
RATE_LIMIT_TTL=60000
RATE_LIMIT_MAX=100
RATE_LIMIT_AUTH_MAX=5

# Stripe (live keys)
STRIPE_SECRET_KEY=sk_live_your_live_secret_key
STRIPE_WEBHOOK_SECRET=whsec_your_live_webhook_secret

# Email
EMAIL_HOST=smtp.resend.com
EMAIL_PORT=587
EMAIL_USER=resend
EMAIL_PASSWORD=your_production_api_key
EMAIL_FROM=noreply@yourdomain.com
EMAIL_FROM_NAME="Your SaaS Name"

# OAuth
GOOGLE_CLIENT_ID=your-production-google-client-id
GOOGLE_CLIENT_SECRET=your-production-google-client-secret
GITHUB_CLIENT_ID=your-production-github-client-id
GITHUB_CLIENT_SECRET=your-production-github-client-secret

# File uploads
AWS_ACCESS_KEY_ID=your-aws-access-key
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
AWS_REGION=us-east-1
AWS_S3_BUCKET=your-production-uploads-bucket

apps/web/.env.production

# API Connection
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
NEXT_PUBLIC_APP_URL=https://yourdomain.com

# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_your_live_publishable_key

# OAuth
NEXT_PUBLIC_GOOGLE_OAUTH_URL=https://api.yourdomain.com/auth/oauth/google
NEXT_PUBLIC_GITHUB_OAUTH_URL=https://api.yourdomain.com/auth/oauth/github

# Analytics
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
NEXT_PUBLIC_SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id

Security Considerations

Environment File Security

  1. Never commit environment files to git

    # .gitignore should include:
    .env*
    !.env.example
    !.env*.example
  2. Use strong, unique values in production

    • JWT secrets: minimum 32 characters, cryptographically random
    • Database passwords: long, complex passwords
    • API keys: use production-grade keys from providers
  3. Restrict access to environment files

    chmod 600 .env*

Secret Management

For production deployments, consider using dedicated secret management:

AWS Secrets Manager

# Store secrets in AWS Secrets Manager
aws secretsmanager create-secret \
  --name "shopyseed/production/jwt-secret" \
  --secret-string "your-secure-jwt-secret"

# Retrieve in application
JWT_SECRET=$(aws secretsmanager get-secret-value \
  --secret-id "shopyseed/production/jwt-secret" \
  --query SecretString --output text)

Docker Secrets

# docker-compose.prod.yml
secrets:
  jwt_secret:
    external: true
  db_password:
    external: true

services:
  api:
    secrets:
      - jwt_secret
      - db_password
    environment:
      JWT_SECRET_FILE: /run/secrets/jwt_secret
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

Kubernetes Secrets

apiVersion: v1
kind: Secret
metadata:
  name: shopyseed-secrets
type: Opaque
data:
  jwt-secret: <base64-encoded-secret>
  db-password: <base64-encoded-password>

Validation

Environment Validation Schema

ShopySeed includes runtime environment validation. Add new variables to the validation schema:

// apps/api/src/common/config/env.validation.ts
import { plainToClass, Type } from 'class-transformer';
import { IsString, IsNumber, IsOptional, IsBoolean, Min, Max } from 'class-validator';

export class EnvironmentVariables {
  @IsString()
  NODE_ENV: string;

  @Type(() => Number)
  @IsNumber()
  @Min(1)
  @Max(65535)
  @IsOptional()
  PORT?: number = 3011;

  @IsString()
  DATABASE_URL: string;

  @IsString()
  JWT_SECRET: string;

  // Add validation for your custom environment variables
  @IsString()
  @IsOptional()
  YOUR_CUSTOM_VARIABLE?: string;

  @Type(() => Number)
  @IsNumber()
  @IsOptional()
  YOUR_NUMERIC_VARIABLE?: number;

  @Type(() => Boolean)
  @IsBoolean()
  @IsOptional()
  YOUR_BOOLEAN_VARIABLE?: boolean = false;
}

export function validate(config: Record<string, unknown>) {
  const validatedConfig = plainToClass(EnvironmentVariables, config, {
    enableImplicitConversion: true,
  });

  return validatedConfig;
}

Manual Validation

You can also validate your environment setup:

# Check required variables
node -e "
const required = ['DATABASE_URL', 'JWT_SECRET', 'STRIPE_SECRET_KEY'];
const missing = required.filter(key => !process.env[key]);
if (missing.length) {
  console.error('Missing required environment variables:', missing);
  process.exit(1);
} else {
  console.log('All required environment variables are set ✅');
}
"

Troubleshooting

Common Issues

1. Database Connection Fails

# Test connection manually
psql postgresql://postgres:password@localhost:5433/shopyseed_dev

# Check if DATABASE_URL is properly formatted
node -e "console.log(process.env.DATABASE_URL)"

2. CORS Errors

# Verify CORS_ORIGINS includes your frontend URL
# Development: http://localhost:3000
# Production: https://yourdomain.com

3. Stripe Webhooks Fail

# Test webhook secret
stripe listen --forward-to localhost:3011/billing/webhooks

4. JWT Token Issues

# Verify JWT secret length (minimum 32 characters)
node -e "console.log('JWT_SECRET length:', process.env.JWT_SECRET?.length)"

5. Email Not Sending

# Test SMTP connection
node -e "
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransporter({
  host: process.env.EMAIL_HOST,
  port: process.env.EMAIL_PORT,
  auth: { user: process.env.EMAIL_USER, pass: process.env.EMAIL_PASSWORD }
});
transporter.verify().then(() => console.log('SMTP connection successful'))
  .catch(err => console.error('SMTP connection failed:', err));
"

Quick Reference

Development Setup Checklist

  • Copy .env.example files to .env files
  • Set DATABASE_URL for local PostgreSQL
  • Generate JWT_SECRET (32+ characters)
  • Configure STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET (test keys)
  • Set CORS_ORIGINS=http://localhost:3000
  • Set NEXT_PUBLIC_API_URL=http://localhost:3011
  • Set NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY (test key)

Production Setup Checklist

  • Use strong, unique passwords and secrets
  • Configure production database connection
  • Set up production Stripe keys and webhooks
  • Configure email provider (Resend, SendGrid, etc.)
  • Set production CORS origins
  • Configure OAuth providers with production URLs
  • Set up file storage (S3, etc.)
  • Configure monitoring and analytics
  • Secure environment files (chmod 600)
  • Use secret management service for sensitive data

This environment reference ensures your ShopySeed deployment is properly configured and secure across all environments. 🚀

On this page