Files
rxminder/docs/setup/ENVIRONMENT_VARIABLES.md
2025-09-23 11:32:48 -07:00

17 KiB

Environment Variables Guide

This guide explains how to use environment variables with the rxminder Kustomize deployment system.

Overview

The rxminder application supports multiple ways to configure deployments using environment variables:

  1. Static Configuration: Pre-generated config files
  2. Dynamic Configuration: Runtime environment variable injection
  3. Hybrid Approach: Combination of both methods

Run Profiles at a Glance

Profile Typical Usage Key Files
Development Vite dev server with hot reload and optional mock CouchDB .env.local, bun run dev
Testing Jest unit/integration suites against the mock database strategy No additional env required (bun run test)
Production Hardened build served by Docker/Kubernetes with real services .env, Docker/compose manifests

See the Run Profiles section in the project README for commands and best practices.

Environment Variable Sources

Variables are loaded in the following priority order (last wins):

  1. ~/.env - Global user environment
  2. ./.env - Project-wide environment
  3. ./.env.{environment} - Environment-specific (e.g., .env.dev, .env.prod)
  4. ./.env.local - Local overrides (git-ignored)
  5. System environment variables

Quick Start

Method 1: Generate Static Configuration

# Generate configuration from your environment variables
make generate-config-dev
make generate-config-prod

# Deploy using generated config
make deploy-dev

Method 2: Dynamic Environment Injection

# Deploy with runtime environment variable substitution
make deploy-with-env-dev
make deploy-with-env-prod

Environment Files Setup

1. Global User Environment (~/.env)

Store your personal/machine-specific settings:

# ~/.env
REGISTRY_USERNAME=your_username
REGISTRY_EMAIL=your_email@example.com
KUBECONFIG=/path/to/your/kubeconfig

2. Project Environment (./.env)

Store project-wide defaults:

# ./.env
APP_NAME=rxminder
REGISTRY_URL=gitea-http.taildb3494.ts.net
IMAGE_REPOSITORY=will/rxminder
COUCHDB_DATABASE_NAME=meds_app

3. Environment-Specific Files

Development (./.env.dev)

NODE_ENV=development
LOG_LEVEL=debug
DEBUG=true
IMAGE_TAG=dev
INGRESS_HOST=rxminder-dev.local
DEV_MODE=true
ENABLE_MONITORING=false

# Development database
COUCHDB_USERNAME=admin
COUCHDB_PASSWORD=devpass123

# Development resource limits
FRONTEND_MEMORY_REQUEST=16Mi
FRONTEND_MEMORY_LIMIT=32Mi
COUCHDB_MEMORY_REQUEST=64Mi
COUCHDB_MEMORY_LIMIT=128Mi
STORAGE_SIZE=1Gi

Production (./.env.prod)

NODE_ENV=production
LOG_LEVEL=warn
DEBUG=false
IMAGE_TAG=v1.0.0
INGRESS_HOST=rxminder.yourdomain.com
ENABLE_MONITORING=true
ENABLE_METRICS=true
ENABLE_TRACING=true

# Production performance
CACHE_TTL=3600
REQUEST_TIMEOUT=30000
MAX_CONNECTIONS=200

# Production resources
FRONTEND_REPLICAS=3
FRONTEND_MEMORY_REQUEST=256Mi
FRONTEND_MEMORY_LIMIT=512Mi
COUCHDB_MEMORY_REQUEST=512Mi
COUCHDB_MEMORY_LIMIT=1Gi
STORAGE_SIZE=10Gi
STORAGE_CLASS=ssd

# Security
ENABLE_SECURITY_HEADERS=true
ENABLE_RATE_LIMITING=true
CORS_ORIGIN=https://rxminder.yourdomain.com

# TLS/SSL
ENABLE_TLS=true
CERT_MANAGER_ISSUER=letsencrypt-prod

Staging (./.env.staging)

NODE_ENV=staging
LOG_LEVEL=info
DEBUG=false
IMAGE_TAG=staging
INGRESS_HOST=staging.rxminder.yourdomain.com
ENABLE_MONITORING=true

# Staging resources (between dev and prod)
FRONTEND_REPLICAS=2
FRONTEND_MEMORY_REQUEST=128Mi
FRONTEND_MEMORY_LIMIT=256Mi
STORAGE_SIZE=5Gi

4. Local Overrides (./.env.local)

Note: This file should be in .gitignore and used for sensitive local settings:

# ./.env.local (DO NOT COMMIT)
COUCHDB_PASSWORD=your_secure_password
REGISTRY_PASSWORD=your_registry_token
API_SECRET_KEY=your_secret_key
JWT_SECRET=your_jwt_secret

# Local development overrides
INGRESS_HOST=localhost:8080
DEV_API_URL=http://localhost:5984

Available Environment Variables

Core Application Variables

Variable Default Description
APP_NAME rxminder Application name used in labels and resources
NODE_ENV production Runtime environment (development, staging, production)
LOG_LEVEL info Logging level (debug, info, warn, error)
DEBUG false Enable debug mode
APP_VERSION 1.0.0 Application version

Container Registry Variables

Variable Default Description
REGISTRY_URL gitea-http.taildb3494.ts.net Container registry URL
IMAGE_REPOSITORY will/rxminder Image repository path
IMAGE_TAG latest Image tag to deploy
REGISTRY_USERNAME - Registry authentication username
REGISTRY_PASSWORD - Registry authentication password
REGISTRY_EMAIL - Registry authentication email

Database Variables

Variable Default Description
DB_HOST rxminder-couchdb-service Database host
DB_PORT 5984 Database port
COUCHDB_DATABASE_NAME meds_app CouchDB database name
COUCHDB_USERNAME admin Database username
COUCHDB_PASSWORD - Database password (required)

Email (Mailgun) Variables

Variable Default Description
VITE_MAILGUN_API_KEY required Mailgun API key used for authenticated requests
VITE_MAILGUN_DOMAIN required Mailgun sending domain (e.g. mg.yourdomain.com)
VITE_MAILGUN_BASE_URL https://api.mailgun.net/v3 Mailgun REST API base URL
VITE_MAILGUN_FROM_NAME Medication Reminder Friendly name used in the from header
VITE_MAILGUN_FROM_EMAIL required Email address used in the from header (must belong to the configured domain)

Tip: When any required Mailgun variables are missing, the application falls back to a development mode that logs email previews instead of sending real messages. Configure the variables above in .env.local (git ignored) before testing real email flows.

Network & Ingress Variables

Variable Default Description
INGRESS_HOST Environment-specific Ingress hostname
INGRESS_CLASS nginx Ingress class to use
ENABLE_TLS false Enable TLS/HTTPS
CERT_MANAGER_ISSUER letsencrypt-prod Certificate issuer
CORS_ORIGIN * CORS allowed origins

When running via docker compose up --build, CouchDB CORS settings are sourced from couchdb-config/cors.ini. Update the origins list in that file to add additional frontend domains.

Performance Variables

Variable Default Description
FRONTEND_REPLICAS 1 Number of frontend replicas
CACHE_TTL 1800 Cache time-to-live in seconds
REQUEST_TIMEOUT 30000 Request timeout in milliseconds
MAX_CONNECTIONS 100 Maximum concurrent connections

Resource Limits

Variable Default Description
FRONTEND_MEMORY_REQUEST 32Mi Frontend memory request
FRONTEND_MEMORY_LIMIT 64Mi Frontend memory limit
FRONTEND_CPU_REQUEST 20m Frontend CPU request
FRONTEND_CPU_LIMIT 40m Frontend CPU limit
COUCHDB_MEMORY_REQUEST 64Mi CouchDB memory request
COUCHDB_MEMORY_LIMIT 128Mi CouchDB memory limit
STORAGE_SIZE 1Gi Storage volume size
STORAGE_CLASS standard Storage class

Monitoring & Observability

Variable Default Description
ENABLE_MONITORING false Enable monitoring features
ENABLE_METRICS false Enable metrics collection
ENABLE_TRACING false Enable distributed tracing
METRICS_PORT 9090 Metrics server port

Security Variables

Variable Default Description
ENABLE_SECURITY_HEADERS false Enable security headers
ENABLE_RATE_LIMITING false Enable rate limiting
API_SECRET_KEY - API secret key
JWT_SECRET - JWT signing secret

Bootstrap Admin Variables

These variables control the default admin account created/updated at app startup by the frontend seeder. They are read at build-time (Vite), so changing them requires rebuilding the frontend image.

Variable Default Description
VITE_ADMIN_EMAIL admin@localhost Email of the default admin user
VITE_ADMIN_PASSWORD admin123! Password for the default admin user

Notes:

  • To change these in Docker, set build args in docker-compose.yaml or define them in .env and rebuild: docker compose build frontend && docker compose up -d.
  • The seeder is idempotent: if a user with this email exists, it updates role/status and keeps the latest password you set.

Usage Examples

Basic Development Setup

  1. Create your development environment file:
cat > .env.dev << EOF
NODE_ENV=development
LOG_LEVEL=debug
DEBUG=true
IMAGE_TAG=dev
INGRESS_HOST=rxminder-dev.local
COUCHDB_PASSWORD=devpass123
EOF
  1. Generate configuration and deploy:
make generate-config-dev
make deploy-dev

Production Deployment with Secrets

  1. Set up your production environment:
# .env.prod (commit this)
NODE_ENV=production
LOG_LEVEL=warn
IMAGE_TAG=v1.0.0
INGRESS_HOST=rxminder.yourdomain.com
ENABLE_TLS=true

# .env.local (DO NOT commit)
COUCHDB_PASSWORD=your_secure_production_password
REGISTRY_PASSWORD=your_registry_token
  1. Deploy with environment variables:
make deploy-with-env-prod

Dynamic Configuration Updates

Update configuration without rebuilding:

# Update environment variable
export LOG_LEVEL=debug

# Deploy with updated configuration
./scripts/deploy-with-env.sh prod apply

Testing Different Configurations

# Test with different image tag
export IMAGE_TAG=feature-branch
make diff-with-env-dev

# Test with different resources
export FRONTEND_REPLICAS=5
./scripts/deploy-with-env.sh prod dry-run

Available Commands

Configuration Generation

make generate-config-dev          # Generate dev config from env vars
make generate-config-prod         # Generate prod config from env vars
make generate-config-staging      # Generate staging config from env vars
make generate-config-all          # Generate all environment configs
make validate-config              # Validate generated configuration
make generate-secrets-template    # Generate secrets template files

Environment-Aware Deployment

make deploy-with-env-dev          # Deploy dev with env vars
make deploy-with-env-prod         # Deploy prod with env vars
make deploy-with-env-staging      # Deploy staging with env vars
make undeploy-with-env-dev        # Remove dev deployment
make diff-with-env-dev            # Show dev diff with env vars
make status-with-env-dev          # Show dev status with env vars

Direct Script Usage

# Generate configuration
./scripts/generate-config.sh dev
./scripts/generate-config.sh prod --secrets

# Deploy with environment variables
./scripts/deploy-with-env.sh dev apply
./scripts/deploy-with-env.sh prod diff
./scripts/deploy-with-env.sh staging delete

Best Practices

Security

  1. Never commit sensitive data:

    • Add .env.local to .gitignore
    • Use external secret management for production
    • Rotate passwords regularly
  2. Use environment-specific files:

    • .env.dev for development settings
    • .env.prod for production configuration
    • .env.local for sensitive overrides

Organization

  1. Group related variables:

    • Database settings together
    • Resource limits together
    • Feature flags together
  2. Use descriptive names:

    • FRONTEND_MEMORY_LIMIT vs MEM_LIMIT
    • ENABLE_DEBUG_MODE vs DEBUG
  3. Document your variables:

    • Add comments explaining purpose
    • Include example values
    • Note required vs optional

Development Workflow

  1. Start with examples:

    cp .env.example .env.dev
    # Edit .env.dev with your settings
    
  2. Test configurations:

    make generate-config-dev
    make kustomize-dry-run-dev
    
  3. Validate before deploying:

    make validate-config
    make diff-with-env-dev
    

Troubleshooting

Common Issues

  1. Variables not being loaded:

    • Check file permissions (chmod 644 .env.*)
    • Verify file format (no spaces around =)
    • Check file encoding (UTF-8)
  2. Configuration not updating:

    • Regenerate config: make generate-config-dev
    • Clear cached resources: kubectl delete configmap -l app=rxminder
  3. Deployment failures:

    • Validate syntax: make validate-config
    • Check logs: kubectl logs -l app=rxminder
    • Verify resources: kubectl describe deployment rxminder-frontend

Debug Commands

# Check loaded environment variables
./scripts/generate-config.sh dev --dry-run

# Validate generated configuration
make validate-config

# Show what would be deployed
./scripts/deploy-with-env.sh dev dry-run

# Check current deployment status
make status-with-env-dev

Migration from Legacy System

Step 1: Extract Current Configuration

# Export current settings to environment file
echo "APP_NAME=rxminder" > .env.dev
echo "IMAGE_TAG=dev" >> .env.dev
# ... add other variables

Step 2: Test New System

# Generate and validate configuration
make generate-config-dev
make validate-config

# Test deployment
make kustomize-dry-run-dev

Step 3: Deploy

# Deploy using new system
make deploy-with-env-dev

# Verify deployment
make status-with-env-dev

External Secret Management

For production environments, integrate with external secret management:

HashiCorp Vault Integration

# .env.prod
VAULT_ADDR=https://vault.yourdomain.com
VAULT_ROLE=rxminder-prod
VAULT_SECRET_PATH=secret/rxminder/prod

# Use Vault Agent or CSI driver to inject secrets

Kubernetes External Secrets

# external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: rxminder-secrets
spec:
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: couchdb-secret
  data:
    - secretKey: password
      remoteRef:
        key: rxminder/prod
        property: couchdb_password

AWS Secrets Manager

# .env.prod
AWS_REGION=us-west-2
AWS_SECRET_NAME=rxminder/prod/couchdb

# Use AWS Load Balancer Controller or external-secrets-operator

Summary

The environment variable system provides:

  • Flexibility: Configure deployments without changing code
  • Security: Keep sensitive data out of version control
  • Consistency: Standardized configuration across environments
  • Maintainability: Clear separation of configuration and code

Choose the approach that best fits your workflow:

  • Static generation for stable, version-controlled configurations
  • Dynamic injection for flexible, runtime configurations
  • Hybrid approach for the best of both worlds

For more information, see: