# Environment Configuration Guide ## Overview The application uses **hierarchical configuration** with environment-specific settings. There are two ways the environment is determined: 1. **DOTNET_ENVIRONMENT** (environment variable) - Controls which `appsettings.{Environment}.json` file is loaded 2. **Application:Environment** (configuration setting) - Stored in each appsettings file for application code to read --- ## How It Works ### Step 1: Set DOTNET_ENVIRONMENT The `DOTNET_ENVIRONMENT` environment variable determines which configuration file to load: ```bash # Load appsettings.Development.json DOTNET_ENVIRONMENT=Development # Load appsettings.Staging.json DOTNET_ENVIRONMENT=Staging # Load appsettings.Production.json (default) DOTNET_ENVIRONMENT=Production ``` ### Step 2: Configuration File Is Loaded Based on `DOTNET_ENVIRONMENT`, .NET loads: 1. `appsettings.json` (base configuration) 2. `appsettings.{Environment}.json` (overrides base) ### Step 3: Application:Environment Setting Each environment-specific file defines its own `Application:Environment` value: **appsettings.Development.json:** ```json { "Application": { "Environment": "Development" }, ... } ``` **appsettings.Production.json:** ```json { "Application": { "Environment": "Production" }, ... } ``` --- ## Usage Examples ### Local Development ```bash cd src/EmbaseConferenceScheduler.Worker # Run with Development settings dotnet run --environment Development ``` **Result:** - Loads `appsettings.Development.json` - Application:Environment = "Development" - Uses local database, test SFTP - CRON runs every 5 minutes ### Docker Production **Run with Production environment:** ```bash docker run -d \ -e DOTNET_ENVIRONMENT=Production \ -v /data/production/articles/pdf:/production/articles/pdf:ro \ -v embase-logs:/logs \ --name embase-conference-scheduler \ embase-conference-scheduler:latest ``` **Result:** - Loads `appsettings.Production.json` - Application:Environment = "Production" - Uses production database, production SFTP - CRON runs daily at 02:00 IST ### Docker Staging **Run with Staging environment:** ```bash docker run -d \ -e DOTNET_ENVIRONMENT=Staging \ -v /data/production/articles/pdf:/production/articles/pdf:ro \ -v embase-logs:/logs \ --name embase-conference-scheduler \ embase-conference-scheduler:latest ``` **Result:** - Loads `appsettings.Staging.json` - Application:Environment = "Staging" - Uses staging database, staging SFTP - CRON runs daily at 03:00 IST --- ## Reading Environment in Code You can inject `IOptions` to read the environment: ```csharp using EmbaseConferenceScheduler.Domain.Configuration; using Microsoft.Extensions.Options; public class MyService { private readonly ApplicationSettings _appSettings; public MyService(IOptions options) { _appSettings = options.Value; } public void DoSomething() { if (_appSettings.Environment == "Development") { // Special dev behavior } else if (_appSettings.Environment == "Production") { // Production behavior } } } ``` --- ## Configuration Priority Settings are loaded in this order (last wins): 1. **appsettings.json** (base defaults) 2. **appsettings.{Environment}.json** (environment-specific) 3. **Environment variables** (runtime overrides) 4. **Command-line arguments** (highest priority) ### Example Override Even if `appsettings.Production.json` says: ```json { "ConnectionStrings": { "EmbaseDb": "Host=prod-db;..." } } ``` You can override at runtime: ```yaml # docker-compose.yml environment: ConnectionStrings__EmbaseDb: "Host=override-db;Port=5432;..." ``` --- ## Environment Settings Reference | File | Application:Environment | Database | SFTP | CRON Schedule | |------|------------------------|----------|------|---------------| | `appsettings.json` | Production | localhost | sftp.elsevier.com | Daily 02:00 | | `appsettings.Development.json` | Development | localhost:embase_dev | localhost:2222 | Every 5 min | | `appsettings.Staging.json` | Staging | staging-db | sftp-staging | Daily 03:00 | | `appsettings.Production.json` | Production | prod-db | sftp.elsevier.com | Daily 02:00 | --- ## Logging On startup, the application logs the active environment: ``` [2026-03-09 10:30:15 INF] Starting Embase Conference Abstract Scheduler... [2026-03-09 10:30:16 INF] Scheduler host built successfully. [2026-03-09 10:30:16 INF] DOTNET_ENVIRONMENT: Production [2026-03-09 10:30:16 INF] Application Environment (from appsettings): Production [2026-03-09 10:30:16 INF] Configuration file loaded: appsettings.Production.json [2026-03-09 10:30:16 INF] Waiting for Quartz trigger... ``` --- ## Quick Reference ### Change Environment | Method | How To Set | |--------|-----------| | **Command Line** | `dotnet run --environment Staging` | | **Docker Compose** | `DOTNET_ENVIRONMENT: Staging` in environment section | | **Docker Run** | `docker run -e DOTNET_ENVIRONMENT=Staging ...` | | **Windows** | `$env:DOTNET_ENVIRONMENT="Staging"` | | **Linux** | `export DOTNET_ENVIRONMENT=Staging` | ### Verify Active Environment 1. Check startup logs for "DOTNET_ENVIRONMENT" message 2. Check startup logs for "Application Environment (from appsettings)" message 3. Both should match the environment you intended to use --- ## Best Practices ✅ **DO:** - Set `DOTNET_ENVIRONMENT` to control which file loads - Keep environment-sensitive values in environment-specific files - Use environment variables to override secrets at runtime - Verify logs on startup to confirm correct environment ❌ **DON'T:** - Commit production secrets to source control - Mix environment settings (e.g., production DB in development file) - Rely solely on `Application:Environment` - use .NET's built-in `IHostEnvironment` --- ## Troubleshooting ### Wrong Environment Loaded **Problem:** Application loads Production settings when you expected Development **Solution:** ```bash # Verify DOTNET_ENVIRONMENT is set echo $env:DOTNET_ENVIRONMENT # Windows echo $DOTNET_ENVIRONMENT # Linux # Set it explicitly dotnet run --environment Development ``` ### Settings Not Overriding **Problem:** Changed `appsettings.Development.json` but changes don't apply **Possible causes:** 1. Wrong environment loaded - check DOTNET_ENVIRONMENT 2. Environment variable override - check docker-compose.yml 3. Cached build - run `dotnet clean; dotnet build` ### Application:Environment Doesn't Match **Problem:** Logs show: ``` DOTNET_ENVIRONMENT: Production Application Environment: Development ``` **This means:** - You're running with `DOTNET_ENVIRONMENT=Production` - But `appsettings.Production.json` has wrong `Application:Environment` value - Fix the JSON file to match --- For more details, see [README_Architecture.md](../README_Architecture.md)