# Environment Configuration

All environment variables are stored in a single .env file at the project root. Both the client and server read from this file.

# File Location

CloudPOS/
├── .env          ← Environment file (create this)
├── .env.example  ← Template (if exists)
├── server/
└── client/

# Environment Variables Reference

# Server Configuration

Variable Description Example Required
NODE_ENV Environment mode development or production Yes
PORT API server port 3000 Yes

# Database Configuration

Variable Description Example Required
DATABASE_URL MySQL connection string mysql://user:password@localhost:3306/cloudpos Yes

Format: mysql://USERNAME:PASSWORD@HOST:PORT/DATABASE_NAME

Examples:

  • Laragon (Windows, no password): mysql://root:@localhost:3306/cloudpos
  • MySQL with password: mysql://root:mypassword@localhost:3306/cloudpos
  • Remote database: mysql://user:pass@db.example.com:3306/cloudpos

# JWT Authentication

Variable Description Example Required
JWT_SECRET Secret key for access tokens (min 32 chars) your-super-secret-jwt-key-change-in-production-min-32-chars Yes
JWT_EXPIRES_IN Access token expiry 15m (15 minutes) Yes
JWT_REFRESH_SECRET Secret key for refresh tokens (min 32 chars) your-super-secret-refresh-token-key-change-in-production-min-32-chars Yes
JWT_REFRESH_EXPIRES_IN Refresh token expiry 7d (7 days) Yes

Generate secure secrets:

# Generate random secret (32+ characters)
openssl rand -base64 32

# CORS & Frontend URLs

Variable Description Example Required
CORS_ORIGIN Allowed frontend origin http://localhost:5173 (dev) or https://yourdomain.com (prod) Yes
FRONTEND_URL Frontend URL for email links http://localhost:5173 (dev) or https://yourdomain.com (prod) Yes

# Encryption

Variable Description Example Required
ENCRYPTION_KEY AES-256-GCM encryption key (32+ chars) Generate with: openssl rand -base64 32 Yes

⚠️ Important: Change this in production! Used to encrypt sensitive data.

# Email Configuration (SMTP)

Variable Description Example Required
SMTP_HOST SMTP server hostname smtp.gmail.com Optional
SMTP_PORT SMTP port 587 (TLS) or 465 (SSL) Optional
SMTP_SECURE Use SSL/TLS false (for port 587) or true (for port 465) Optional
SMTP_USER SMTP username your-email@gmail.com Optional
SMTP_PASSWORD SMTP password or app password your-app-password Optional
SMTP_FROM_EMAIL From email address noreply@cloudpos.com Optional
SMTP_FROM_NAME From name CloudPOS Optional

Gmail Setup:

  1. Enable 2-factor authentication
  2. Generate app password: https://myaccount.google.com/apppasswords
  3. Use app password in SMTP_PASSWORD

# Stripe Payment Gateway

Variable Description Example Required
STRIPE_SECRET_KEY Stripe secret key sk_test_... (test) or sk_live_... (prod) Optional
STRIPE_WEBHOOK_SECRET Webhook signing secret whsec_... Optional

Note: Stripe configuration can also be done via Admin Panel (recommended). See Payment Gateway.

# Demo Mode

Variable Description Example Required
DEMO_MODE Enable demo mode (blocks mutations) false (prod) or true (demo) Optional

When enabled: Blocks all POST, PUT, PATCH, DELETE requests. See Security & Demo Mode.

# Client Configuration (Vite)

Important: Vite only loads variables prefixed with VITE_ for security.

Variable Description Example Required
VITE_API_URL API base URL http://localhost:3000/api (dev) or https://yourdomain.com/api (prod) Yes
VITE_APP_NAME Application name CloudPOS Optional
VITE_APP_VERSION Application version 1.0.0 Optional

# Complete .env Example

# Development

# Server
NODE_ENV=development
PORT=3000

# Database
DATABASE_URL="mysql://root:@localhost:3306/cloudpos"

# JWT
JWT_SECRET=dev-jwt-secret-key-min-32-characters-long-change-in-production
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=dev-refresh-secret-key-min-32-characters-long-change-in-production
JWT_REFRESH_EXPIRES_IN=7d

# CORS & Frontend
CORS_ORIGIN=http://localhost:5173
FRONTEND_URL=http://localhost:5173

# Encryption
ENCRYPTION_KEY=dev-encryption-key-change-in-production-use-strong-random-string

# Email (Optional)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@cloudpos.com
SMTP_FROM_NAME=CloudPOS

# Stripe (Optional)
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here

# Demo Mode
DEMO_MODE=false

# Client (Vite)
VITE_API_URL=http://localhost:3000/api
VITE_APP_NAME=CloudPOS
VITE_APP_VERSION=1.0.0

# Production

# Server
NODE_ENV=production
PORT=3000

# Database
DATABASE_URL="mysql://cloudpos:STRONG_PASSWORD@localhost:3306/cloudpos"

# JWT (Generate strong secrets!)
JWT_SECRET=GENERATE_STRONG_SECRET_MIN_32_CHARS_USE_OPENSSL_RAND_BASE64_32
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=GENERATE_STRONG_SECRET_MIN_32_CHARS_USE_OPENSSL_RAND_BASE64_32
JWT_REFRESH_EXPIRES_IN=7d

# CORS & Frontend
CORS_ORIGIN=https://yourdomain.com
FRONTEND_URL=https://yourdomain.com

# Encryption (Generate: openssl rand -base64 32)
ENCRYPTION_KEY=GENERATE_STRONG_ENCRYPTION_KEY_32_CHARS_MIN

# Email
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=noreply@yourdomain.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@yourdomain.com
SMTP_FROM_NAME=CloudPOS

# Stripe
STRIPE_SECRET_KEY=sk_live_your_production_stripe_secret_key
STRIPE_WEBHOOK_SECRET=whsec_your_production_webhook_secret

# Demo Mode
DEMO_MODE=false

# Client (Vite)
VITE_API_URL=https://yourdomain.com/api
VITE_APP_NAME=CloudPOS
VITE_APP_VERSION=1.0.0

# How to Set Environment Variables

# 1. Create .env File

# From project root
cp .env.example .env  # If .env.example exists
# Or create manually
nano .env

# 2. Edit Variables

nano .env
# Add or modify variables
# Save: Ctrl+O, Enter, Ctrl+X

# 3. Restart Services

After changing .env:

# Development
# Stop servers (Ctrl+C) and restart

# Production
pm2 restart cloudpos

# Security Best Practices

  1. Never commit .env to Git

    • Already in .gitignore
    • Use .env.example as template
  2. Use strong secrets in production

    # Generate JWT secrets
    openssl rand -base64 32
    
    # Generate encryption key
    openssl rand -base64 32
    
  3. Restrict file permissions

    chmod 600 .env
    
  4. Use different secrets for production

    • Never use development secrets in production
    • Generate new secrets for each environment
  5. Rotate secrets periodically

    • Change JWT secrets every 90 days
    • Change encryption key if compromised

# Multi-Environment Setup

# Development

  • File: .env.development (optional)
  • Load: Automatically by NestJS/Vite

# Production

  • File: .env.production (optional)
  • Load: Automatically by NestJS/Vite

# Staging

  • File: .env.staging (optional)
  • Load: Set NODE_ENV=staging

# Troubleshooting

# Variables Not Loading

Issue: Environment variables not being read

Solutions:

  1. Check file location: .env must be in project root
  2. Check variable names: Vite variables must start with VITE_
  3. Restart servers after changes
  4. Check for typos in variable names

# Database Connection Fails

Issue: DATABASE_URL not working

Solutions:

  1. Test connection string format
  2. Verify MySQL is running
  3. Check credentials
  4. Test with: mysql -u USER -p -h HOST DATABASE

# CORS Errors

Issue: Frontend can't connect to API

Solutions:

  1. Check CORS_ORIGIN matches frontend URL exactly
  2. Include protocol: http:// or https://
  3. No trailing slash
  4. Restart API server after changes

Next: See Database Setup for database configuration details.