Skip to content

Environment Management Guide

This guide covers comprehensive environment management practices for development, staging, and production environments in Trae.

Overview

Environment management is crucial for maintaining consistent, reliable, and secure development workflows. This guide covers:

  • Environment configuration strategies
  • Variable management
  • Development environment setup
  • Production deployment considerations
  • Security best practices

Environment Types

Development Environment

Characteristics:

  • Local development setup
  • Debug mode enabled
  • Hot reloading
  • Development databases
  • Verbose logging

Configuration:

bash
# .env.development
NODE_ENV=development
DEBUG=true
API_URL=http://localhost:3000
DATABASE_URL=postgresql://localhost:5432/myapp_dev
LOG_LEVEL=debug
HOT_RELOAD=true

Staging Environment

Characteristics:

  • Production-like setup
  • Testing and QA
  • Performance testing
  • Integration testing
  • Limited debugging

Configuration:

bash
# .env.staging
NODE_ENV=staging
DEBUG=false
API_URL=https://staging-api.myapp.com
DATABASE_URL=postgresql://staging-db:5432/myapp_staging
LOG_LEVEL=info
CACHE_ENABLED=true

Production Environment

Characteristics:

  • Optimized performance
  • Security hardened
  • Monitoring enabled
  • Error tracking
  • Minimal logging

Configuration:

bash
# .env.production
NODE_ENV=production
DEBUG=false
API_URL=https://api.myapp.com
DATABASE_URL=postgresql://prod-db:5432/myapp_prod
LOG_LEVEL=error
CACHE_ENABLED=true
MONITORING_ENABLED=true

Environment Variables

Variable Categories

Application Configuration

bash
# Application settings
APP_NAME=MyApplication
APP_VERSION=1.0.0
APP_PORT=3000
APP_HOST=0.0.0.0

Database Configuration

bash
# Database settings
DATABASE_URL=postgresql://user:password@host:port/database
DATABASE_POOL_SIZE=10
DATABASE_TIMEOUT=30000
REDIS_URL=redis://localhost:6379

External Services

bash
# Third-party services
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=us-east-1
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587

Security Configuration

bash
# Security settings
JWT_SECRET=your_jwt_secret_key
ENCRYPTION_KEY=your_encryption_key
API_KEY=your_api_key
SESSION_SECRET=your_session_secret

Variable Management

Environment Files

File Structure:

project/
├── .env.example          # Template with all variables
├── .env.local           # Local overrides (gitignored)
├── .env.development     # Development settings
├── .env.staging         # Staging settings
├── .env.production      # Production settings
└── .env.test           # Test environment settings

Loading Environment Variables

Node.js Example:

javascript
// config/environment.js
require('dotenv').config({
  path: `.env.${process.env.NODE_ENV || 'development'}`
});

const config = {
  app: {
    name: process.env.APP_NAME || 'MyApp',
    port: parseInt(process.env.APP_PORT) || 3000,
    env: process.env.NODE_ENV || 'development'
  },
  database: {
    url: process.env.DATABASE_URL,
    poolSize: parseInt(process.env.DATABASE_POOL_SIZE) || 10
  },
  auth: {
    jwtSecret: process.env.JWT_SECRET,
    sessionSecret: process.env.SESSION_SECRET
  }
};

module.exports = config;

Python Example:

python
# config/settings.py
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv(f".env.{os.getenv('ENVIRONMENT', 'development')}")

class Config:
    APP_NAME = os.getenv('APP_NAME', 'MyApp')
    APP_PORT = int(os.getenv('APP_PORT', 5000))
    DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'
    
    DATABASE_URL = os.getenv('DATABASE_URL')
    REDIS_URL = os.getenv('REDIS_URL')
    
    JWT_SECRET = os.getenv('JWT_SECRET')
    API_KEY = os.getenv('API_KEY')

Development Environment Setup

Local Development

Prerequisites

bash
# Install required tools
npm install -g node@18
pip install python@3.9
docker --version
git --version

Project Setup

bash
# Clone and setup project
git clone https://github.com/yourorg/project.git
cd project

# Copy environment template
cp .env.example .env.local

# Install dependencies
npm install
# or
pip install -r requirements.txt

# Setup database
npm run db:setup
# or
python manage.py migrate

# Start development server
npm run dev
# or
python manage.py runserver

Docker Development

Docker Compose Setup

yaml
# docker-compose.dev.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://postgres:password@db:5432/myapp_dev
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    environment:
      - POSTGRES_DB=myapp_dev
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7
    ports:
      - "6379:6379"

volumes:
  postgres_data:

Development Dockerfile

dockerfile
# Dockerfile.dev
FROM node:18-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm install

# Copy source code
COPY . .

# Expose port
EXPOSE 3000

# Start development server
CMD ["npm", "run", "dev"]

Environment Validation

Schema Validation

Using Zod (TypeScript):

typescript
// config/env-schema.ts
import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'staging', 'production', 'test']),
  PORT: z.string().transform(Number).default('3000'),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
  API_KEY: z.string().optional(),
  DEBUG: z.string().transform(val => val === 'true').default('false')
});

export const env = envSchema.parse(process.env);

Using Pydantic (Python):

python
# config/env_schema.py
from pydantic import BaseSettings, validator
from typing import Optional

class Settings(BaseSettings):
    app_name: str = "MyApp"
    debug: bool = False
    database_url: str
    jwt_secret: str
    api_key: Optional[str] = None
    
    @validator('jwt_secret')
    def jwt_secret_must_be_long(cls, v):
        if len(v) < 32:
            raise ValueError('JWT secret must be at least 32 characters')
        return v
    
    class Config:
        env_file = ".env"

settings = Settings()

Security Best Practices

Secret Management

Never Commit Secrets

bash
# .gitignore
.env
.env.local
.env.*.local
*.key
*.pem
secrets/

Use Secret Management Services

AWS Secrets Manager:

javascript
// utils/secrets.js
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();

async function getSecret(secretName) {
  try {
    const result = await secretsManager.getSecretValue({
      SecretId: secretName
    }).promise();
    return JSON.parse(result.SecretString);
  } catch (error) {
    console.error('Error retrieving secret:', error);
    throw error;
  }
}

HashiCorp Vault:

javascript
// utils/vault.js
const vault = require('node-vault')({
  endpoint: process.env.VAULT_ENDPOINT,
  token: process.env.VAULT_TOKEN
});

async function getVaultSecret(path) {
  try {
    const result = await vault.read(path);
    return result.data;
  } catch (error) {
    console.error('Error reading from Vault:', error);
    throw error;
  }
}

Environment Isolation

Network Isolation

yaml
# docker-compose.yml
version: '3.8'
services:
  app:
    networks:
      - app-network
  db:
    networks:
      - db-network
      - app-network

networks:
  app-network:
    driver: bridge
  db-network:
    driver: bridge
    internal: true

Resource Limits

yaml
# docker-compose.yml
services:
  app:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

CI/CD Integration

GitHub Actions

yaml
# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main, staging]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set environment variables
        run: |
          if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
            echo "ENVIRONMENT=production" >> $GITHUB_ENV
          else
            echo "ENVIRONMENT=staging" >> $GITHUB_ENV
          fi
      
      - name: Deploy to environment
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
        run: |
          echo "Deploying to $ENVIRONMENT"
          # Deployment commands here

GitLab CI/CD

yaml
# .gitlab-ci.yml
stages:
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2

deploy_staging:
  stage: deploy
  environment:
    name: staging
    url: https://staging.myapp.com
  variables:
    ENVIRONMENT: staging
  script:
    - echo "Deploying to staging"
  only:
    - develop

deploy_production:
  stage: deploy
  environment:
    name: production
    url: https://myapp.com
  variables:
    ENVIRONMENT: production
  script:
    - echo "Deploying to production"
  only:
    - main

Monitoring and Logging

Environment-Specific Logging

javascript
// utils/logger.js
const winston = require('winston');

const logLevel = {
  development: 'debug',
  staging: 'info',
  production: 'error'
}[process.env.NODE_ENV] || 'info';

const logger = winston.createLogger({
  level: logLevel,
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'app.log' })
  ]
});

module.exports = logger;

Health Checks

javascript
// routes/health.js
const express = require('express');
const router = express.Router();

router.get('/health', async (req, res) => {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV,
    version: process.env.APP_VERSION,
    checks: {
      database: await checkDatabase(),
      redis: await checkRedis(),
      external_api: await checkExternalAPI()
    }
  };
  
  const isHealthy = Object.values(health.checks).every(check => check.status === 'ok');
  
  res.status(isHealthy ? 200 : 503).json(health);
});

module.exports = router;

Troubleshooting

Common Issues

Environment Variables Not Loading

bash
# Check if .env file exists
ls -la .env*

# Verify environment variable loading
node -e "console.log(process.env.NODE_ENV)"

# Check for syntax errors in .env file
cat .env | grep -E '^[^#].*='

Database Connection Issues

bash
# Test database connection
psql $DATABASE_URL -c "SELECT 1;"

# Check database logs
docker logs container_name

# Verify network connectivity
telnet db_host db_port

Permission Issues

bash
# Fix file permissions
chmod 600 .env*

# Check Docker permissions
docker run --rm -v $(pwd):/app alpine ls -la /app

Debugging Tools

javascript
// debug/env-check.js
console.log('Environment Check:');
console.log('NODE_ENV:', process.env.NODE_ENV);
console.log('Database URL:', process.env.DATABASE_URL ? 'Set' : 'Not set');
console.log('JWT Secret:', process.env.JWT_SECRET ? 'Set' : 'Not set');
console.log('All env vars:', Object.keys(process.env).filter(key => !key.startsWith('npm_')));

Best Practices

Environment Management

  1. Use Environment Templates: Maintain .env.example with all required variables
  2. Validate Early: Validate environment variables at application startup
  3. Document Variables: Document the purpose and format of each variable
  4. Use Defaults: Provide sensible defaults for non-critical variables
  5. Separate Concerns: Keep different types of configuration separate

Security

  1. Never Commit Secrets: Use .gitignore to exclude sensitive files
  2. Rotate Secrets: Regularly rotate API keys and passwords
  3. Principle of Least Privilege: Grant minimal necessary permissions
  4. Audit Access: Regularly audit who has access to production secrets
  5. Use Secret Management: Leverage dedicated secret management tools

Development Workflow

  1. Consistent Environments: Keep development and production environments similar
  2. Automated Setup: Provide scripts for easy environment setup
  3. Documentation: Maintain up-to-date setup documentation
  4. Testing: Test environment configurations in CI/CD pipelines
  5. Monitoring: Monitor environment health and performance

Your Ultimate AI-Powered IDE Learning Guide