Skip to main content

Environment Variables Configuration Guide

Overview

The Reshma-Core backend utilizes a strict fail-fast initialization strategy. All environment variables are validated at runtime using a Zod schema located in src/config/env.ts. If any required variable is missing, empty, or incorrectly formatted, the Node.js process will terminate immediately with a descriptive validation error. This ensures that the system never runs in an insecure or partially configured state.


Validation Rules & Defaults

The table below reflects the exact rules defined in env.ts. Variables marked Required must be present in your .env file – the server will not start without them.

VariableRequiredDefaultValidation / Notes
PORT"5000"String (coerced to number internally)
NODE_ENV"development"Must be development, production, or test
CLIENT_URLValid URL (e.g., http://localhost:3000)
ADMIN_URLValid URL (e.g., http://localhost:3001)
MONGO_URINon‑empty string – MongoDB connection string
JWT_ACCESS_SECRETMin 10 characters – strong secret recommended
JWT_ACCESS_EXPIRES_IN"15m"String (e.g., 15m, 1h, 7d)
JWT_REFRESH_SECRETMin 10 characters – different from access secret
JWT_REFRESH_EXPIRES_IN"7d"String
GOOGLE_CLIENT_IDNon‑empty string
GOOGLE_CLIENT_SECRETOptional – only needed if using Google OAuth
GOOGLE_CALLBACK_URLOptional – valid URL
CLOUDINARY_CLOUD_NAMENon‑empty
CLOUDINARY_API_KEYNon‑empty
CLOUDINARY_API_SECRETNon‑empty
REDIS_URL"redis://localhost:6379"Valid Redis URL
REDIS_PASSWORDOptional – used if Redis requires auth
SMTP_HOSTNon‑empty string (e.g., smtp.gmail.com)
SMTP_PORT587Coerced to number
SMTP_USERValid email address
SMTP_PASSNon‑empty
EMAIL_FROMNon‑empty (e.g., "Reshma <support@...>")
RAZORPAY_KEY_IDNon‑empty
RAZORPAY_KEY_SECRETNon‑empty
RAZORPAY_WEBHOOK_SECRETNon‑empty
SHIPROCKET_EMAILValid email
SHIPROCKET_PASSWORDNon‑empty
SHIPROCKET_API_BASE_URL"https://apiv2.shiprocket.in"Valid URL
SHIPROCKET_WEBHOOK_SECRETNon‑empty
TYPESENSE_HOSTNon‑empty (e.g., localhost or xxx.typesense.net)
TYPESENSE_PORT8108Coerced to number
TYPESENSE_PROTOCOL"http"Must be http or https
TYPESENSE_API_KEYNon‑empty – Admin API key (not search‑only)

Important: CLIENT_URL and ADMIN_URL have no default – you must set them even for local development. They are used for CORS and email link generation.


1. Core Server Settings

VariableDescriptionExample
PORTPort the Express server listens on5000
NODE_ENVEnvironment – affects logging, error messages, and CORSdevelopment / production / test
CLIENT_URLOrigin of the main customer frontend (React/Next.js)http://localhost:3000
ADMIN_URLOrigin of the admin dashboardhttp://localhost:3001

Graceful Shutdown: The server traps SIGTERM and SIGINT signals, stops accepting new requests, drains active connections, and safely closes MongoDB & Redis connections to prevent data corruption during deployments or container stops.


2. Database & Infrastructure

VariableDescriptionLocal ExampleDocker Example
MONGO_URIFull MongoDB connection stringmongodb://localhost:27017/reshma-boutique-devmongodb://admin:pass@reshma-db:27017/reshmabangles?authSource=admin
REDIS_URLRedis connection endpointredis://localhost:6379redis://default:${REDIS_PASSWORD}@reshma-redis:6379
REDIS_PASSWORDOptional – for password‑protected Redis(leave blank)Set in .env and referenced in compose

Additional Redis usage:

  • BullMQ queues – email dispatch, data export, search sync retries.
  • Distributed locking – prevents duplicate cron jobs across multiple server instances.
  • Rate limiting – stores request counts (when using rate-limit-redis).

3. Two‑Token Authentication Architecture

The system uses short‑lived Access Tokens (in memory, Authorization header) and long‑lived Refresh Tokens (HttpOnly cookies).

VariableRequiredRecommended ValueGeneration Command
JWT_ACCESS_SECRET64‑character hexopenssl rand -hex 32
JWT_ACCESS_EXPIRES_IN15m
JWT_REFRESH_SECRET64‑character hex (different from above)openssl rand -hex 32
JWT_REFRESH_EXPIRES_IN7d

Security: Never use the same secret for access and refresh tokens. Rotate secrets periodically in production.


4. Social Authentication (Google OAuth)

VariableRequiredNotes
GOOGLE_CLIENT_IDObtained from Google Cloud Console
GOOGLE_CLIENT_SECRETOnly needed if you enable Google login
GOOGLE_CALLBACK_URLDefault callback route: /api/v1/auth/google/callback

If you are not using Google OAuth, you can leave the optional variables blank – but GOOGLE_CLIENT_ID must still have a dummy value to pass validation (the auth routes will be unavailable).


5. Media Pipeline (Cloudinary)

All images (product photos, user avatars) are uploaded directly from memory buffers to Cloudinary.

VariableRequiredWhere to find
CLOUDINARY_CLOUD_NAMECloudinary Dashboard
CLOUDINARY_API_KEYCloudinary Dashboard
CLOUDINARY_API_SECRETCloudinary Dashboard (keep secret)

The integration is defined in src/config/cloudinary.ts. It automatically converts uploaded images to WebP format for bandwidth savings.


6. Notification Engine (SMTP)

Used for transactional emails (OTP, password change confirmation, order updates, data export).

VariableRequiredExample
SMTP_HOSTsmtp.gmail.com
SMTP_PORT587 (default)
SMTP_USERsupport@reshmabangles.com
SMTP_PASSFor Gmail: 16‑character App Password
EMAIL_FROM"Reshma Bangles <support@reshmabangles.com>"

Gmail users: Enable 2‑Factor Authentication and generate an App Password. Your regular Gmail password will not work.


7. Payment Gateway (Razorpay)

VariableRequiredFormat
RAZORPAY_KEY_IDStarts with rzp_test_ or rzp_live_
RAZORPAY_KEY_SECRETSecret from Razorpay Dashboard
RAZORPAY_WEBHOOK_SECRETUsed to verify webhook signatures

Webhook secret is mandatory – even for local testing you can set a dummy value, but the endpoint will validate it.


8. Logistics & Shipping (Shiprocket)

VariableRequiredNotes
SHIPROCKET_EMAILEmail used to log into Shiprocket
SHIPROCKET_PASSWORDShiprocket account password
SHIPROCKET_API_BASE_URLDefaults to production API
SHIPROCKET_WEBHOOK_SECRETUsed to verify delivery status callbacks

These are required for shipping label generation and order tracking. For local development without Shiprocket, you can use dummy values – but the integration will log errors.


9. Search Engine (Typesense)

VariableRequiredLocal (Docker)Cloud
TYPESENSE_HOSTlocalhost or reshma-typesensexxx.a1.typesense.net
TYPESENSE_PORT8108443
TYPESENSE_PROTOCOLhttphttps
TYPESENSE_API_KEYany strong string (must match compose)Admin API key from Typesense Cloud

Important: The API key must be the Admin key (capable of creating collections and indexing). The search‑only key will cause schema initialisation to fail.

Sync resilience: Failed Typesense operations (e.g., network timeout) are automatically queued in BullMQ for retry with exponential backoff – see src/config/typesense.ts.


Quick Start: Minimal .env for Local Development (Manual)

# Core
PORT=5000
NODE_ENV=development
CLIENT_URL=http://localhost:3000
ADMIN_URL=http://localhost:3001

# Database
MONGO_URI=mongodb://localhost:27017/reshma-boutique-dev

# Redis (no password)
REDIS_URL=redis://localhost:6379

# JWT (generate actual secrets)
JWT_ACCESS_SECRET=5f8d9a3c7e2b1f6a4d8c0e9b7a3f2d6c1e8b4a7f9d2c5b8e1a6f4c3d7e9b2a1
JWT_REFRESH_SECRET=7b2e1f6a4d8c0e9b7a3f2d6c1e8b4a7f9d2c5b8e1a6f4c3d7e9b2a1f5c8d2e

# Typesense (local binary or Docker)
TYPESENSE_HOST=localhost
TYPESENSE_PORT=8108
TYPESENSE_PROTOCOL=http
TYPESENSE_API_KEY=your_super_secret_key

# Cloudinary (required, but can be dummy for local testing)
CLOUDINARY_CLOUD_NAME=dummy
CLOUDINARY_API_KEY=dummy
CLOUDINARY_API_SECRET=dummy

# SMTP (optional – use ethereal.email for testing)
SMTP_HOST=smtp.ethereal.email
SMTP_PORT=587
SMTP_USER=dummy@ethereal.email
SMTP_PASS=dummy
EMAIL_FROM="Test <test@example.com>"

# Razorpay (required but can be dummy)
RAZORPAY_KEY_ID=rzp_test_dummy
RAZORPAY_KEY_SECRET=dummy
RAZORPAY_WEBHOOK_SECRET=dummy

# Shiprocket (required but can be dummy)
SHIPROCKET_EMAIL=dummy@example.com
SHIPROCKET_PASSWORD=dummy
SHIPROCKET_WEBHOOK_SECRET=dummy

# Google OAuth (required but can be dummy – login will not work)
GOOGLE_CLIENT_ID=dummy.apps.googleusercontent.com

Save this as .env in the project root. Replace JWT secrets with your own generated values.


Docker Compose Overrides

When using Docker (see docker-compose.yml), the following environment variables are automatically set or overridden inside containers – you do not need to set them in .env:

  • MONGO_URImongodb://reshma-db:27017/reshmabangles
  • REDIS_URLredis://reshma-redis:6379
  • TYPESENSE_HOSTreshma-typesense

However, you must still define in .env:

  • JWT_ACCESS_SECRET / JWT_REFRESH_SECRET
  • TYPESENSE_API_KEY (must match the one in docker-compose.yml)

For production docker-compose.prod.yml, variables like MONGO_INITDB_ROOT_USERNAME and REDIS_PASSWORD are used – those are also read from .env.

Troubleshooting Validation Errors

If the server fails to start with an error like:

Invalid environment variables: { "MONGO_URI": { "_errors": ["Required"] } }

Solution: Add the missing variable to your .env file.

Common errors and fixes

ErrorLikely CauseFix
MONGO_URI: RequiredMissing MONGO_URI in .envAdd MONGO_URI=mongodb://localhost:27017/reshma-boutique-dev
CLIENT_URL: Invalid urlCLIENT_URL is not a valid URLUse http://localhost:3000 (no trailing slash)
JWT_ACCESS_SECRET: At least 10 charactersSecret too shortGenerate a 32‑byte hex string: openssl rand -hex 32
TYPESENSE_HOST: RequiredTypesense variables missingAdd all four TYPESENSE_* variables (see example)
SMTP_USER: Invalid emailSMTP user is not a valid emailUse a real email address or a dummy like test@example.com

Note: If you are not using a particular integration (e.g., Shiprocket), you can still provide dummy values that pass validation (non‑empty, correct format) – the code will log errors but will not crash.


Security Best Practices

  • Never commit .env – it is already listed in .gitignore. Use .env.example as a template.
  • Rotate secrets – change JWT_ACCESS_SECRET and JWT_REFRESH_SECRET periodically in production.
  • Use different databases – separate development and production MongoDB instances.
  • Limit API key scope – the Typesense API key should be the Admin key for indexing, but use a Search‑only key in the frontend.
  • SMTP App Password – never use your primary email password; generate an App Password for Gmail/Outlook.

Code References

FilePurpose
src/config/env.tsValidation schema for environment variables
src/config/cloudinary.tsCloudinary integration
src/config/redis.tsRedis client
src/config/typesense.tsTypesense manager

The Reshma-Core Team