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