# Environment Variables This document covers the active environment variables used by the current Biergarten stack. ## Overview The application uses environment variables for: - **.NET API backend** - database connections, token secrets, runtime settings - **React Router website** - API base URL and session signing - **Docker containers** - environment-specific orchestration ## Configuration Patterns ### Backend (.NET API) Direct environment variable access via `Environment.GetEnvironmentVariable()`. ### Frontend (`src/Website`) The active website reads runtime values from the server environment for its auth and API integration. ### Docker Environment-specific `.env` files loaded via `env_file:` in docker-compose.yaml: - `.env.dev` - Development - `.env.test` - Testing - `.env.prod` - Production ## Backend Variables (.NET API) ### Database Connection **Option 1: Component-Based (Recommended for Docker)** Build connection string from individual components: ```bash DB_SERVER=sqlserver,1433 # SQL Server host and port DB_NAME=Biergarten # Database name DB_USER=sa # SQL Server username DB_PASSWORD=YourStrong!Passw0rd # SQL Server password DB_TRUST_SERVER_CERTIFICATE=True # Optional, defaults to True ``` **Option 2: Full Connection String (Local Development)** Provide complete connection string: ```bash DB_CONNECTION_STRING="Server=localhost,1433;Database=Biergarten;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;" ``` **Priority**: `DB_CONNECTION_STRING` is checked first. If not found, connection string is built from components. **Implementation**: See `DefaultSqlConnectionFactory.cs` ### JWT Authentication Secrets (Backend) The backend uses separate secrets for different token types to enable independent key rotation and validation isolation. ```bash # Access token secret (1-hour tokens) ACCESS_TOKEN_SECRET= # Signs short-lived access tokens # Refresh token secret (21-day tokens) REFRESH_TOKEN_SECRET= # Signs long-lived refresh tokens # Confirmation token secret (30-minute tokens) CONFIRMATION_TOKEN_SECRET= # Signs email confirmation tokens # Website base URL (used in confirmation emails) WEBSITE_BASE_URL=https://thebiergarten.app # Base URL for the website ``` **Security Requirements**: - Each secret should be minimum 32 characters - Recommend 127+ characters for production - Generate using cryptographically secure random functions - Never reuse secrets across token types or environments - Rotate secrets periodically in production **Generate Secrets**: ```bash # macOS/Linux - Generate 127-character base64 secret openssl rand -base64 127 # Windows PowerShell [Convert]::ToBase64String((1..127 | %{Get-Random -Max 256})) ``` **Token Expiration**: - **Access tokens**: 1 hour - **Refresh tokens**: 21 days - **Confirmation tokens**: 30 minutes (Defined in `TokenServiceExpirationHours` class) **JWT Implementation**: - **Algorithm**: HS256 (HMAC-SHA256) - **Handler**: Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler - **Validation**: Token signature, expiration, and malformed token checks ### Migration Control ```bash CLEAR_DATABASE=true ``` - **Required**: No - **Default**: false - **Effect**: If "true", drops and recreates database during migrations - **Usage**: Development and testing environments ONLY - **Warning**: NEVER use in production ### ASP.NET Core Configuration ```bash ASPNETCORE_ENVIRONMENT=Development # Development, Production, Staging ASPNETCORE_URLS=http://0.0.0.0:8080 # Binding address and port DOTNET_RUNNING_IN_CONTAINER=true # Flag for container execution ``` ## Frontend Variables (`src/Website`) The active website does not use the old Next.js/Prisma environment model. Its core runtime variables are: ```bash API_BASE_URL=http://localhost:8080 # Base URL for the .NET API SESSION_SECRET= # Cookie session signing secret NODE_ENV=development # Standard Node runtime mode ``` ### Frontend Variable Details #### `API_BASE_URL` - **Required**: Yes for local development - **Default in code**: `http://localhost:8080` - **Used by**: `src/Website/app/lib/auth.server.ts` - **Purpose**: Routes website auth actions to the .NET API #### `SESSION_SECRET` - **Required**: Strongly recommended in all environments - **Default in local code path**: `dev-secret-change-me` - **Used by**: React Router cookie session storage in `auth.server.ts` - **Purpose**: Signs and validates the website session cookie #### `NODE_ENV` - **Required**: No - **Typical values**: `development`, `production`, `test` - **Purpose**: Controls secure cookie behavior and runtime mode ### Admin Account (Seeding) ```bash ADMIN_PASSWORD=SecureAdminPassword123! # Initial admin password for seeding ``` - **Required**: No (only needed for seeding) - **Purpose**: Sets admin account password during database seeding - **Security**: Use strong password, change immediately in production ## Docker-Specific Variables ### SQL Server Container ```bash SA_PASSWORD=YourStrong!Passw0rd # SQL Server SA password ACCEPT_EULA=Y # Accept SQL Server EULA (required) MSSQL_PID=Express # SQL Server edition (Express, Developer, Enterprise) ``` **Password Requirements**: - Minimum 8 characters - Uppercase, lowercase, digits, and special characters - Maps to `DB_PASSWORD` for application containers ## Environment File Structure ### Backend/Docker (Root Directory) ``` .env.example # Template (tracked in Git) .env.dev # Development config (gitignored) .env.test # Testing config (gitignored) .env.prod # Production config (gitignored) ``` **Setup**: ```bash cp .env.example .env.dev # Edit .env.dev with your values ``` ## Legacy Frontend Variables Variables for the archived Next.js frontend (`src/Website-v1`) have been removed from this active reference. See [archive/legacy-website-v1.md](archive/legacy-website-v1.md) if you need the legacy Prisma, Cloudinary, Mapbox, or SparkPost notes. **Docker Compose Mapping**: - `docker-compose.dev.yaml` → `.env.dev` - `docker-compose.test.yaml` → `.env.test` - `docker-compose.prod.yaml` → `.env.prod` ## Variable Reference Table | Variable | Backend | Frontend | Docker | Required | Notes | | ----------------------------- | :-----: | :------: | :----: | :------: | -------------------------- | | `DB_SERVER` | ✓ | | ✓ | Yes\* | SQL Server address | | `DB_NAME` | ✓ | | ✓ | Yes\* | Database name | | `DB_USER` | ✓ | | ✓ | Yes\* | SQL username | | `DB_PASSWORD` | ✓ | | ✓ | Yes\* | SQL password | | `DB_CONNECTION_STRING` | ✓ | | | Yes\* | Alternative to components | | `DB_TRUST_SERVER_CERTIFICATE` | ✓ | | ✓ | No | Defaults to `True` | | `ACCESS_TOKEN_SECRET` | ✓ | | ✓ | Yes | Access token signing | | `REFRESH_TOKEN_SECRET` | ✓ | | ✓ | Yes | Refresh token signing | | `CONFIRMATION_TOKEN_SECRET` | ✓ | | ✓ | Yes | Confirmation token signing | | `WEBSITE_BASE_URL` | ✓ | | | Yes | Website URL for emails | | `API_BASE_URL` | | ✓ | | Yes | Website-to-API base URL | | `SESSION_SECRET` | | ✓ | | Yes | Website session signing | | `NODE_ENV` | | ✓ | | No | Runtime mode | | `CLEAR_DATABASE` | ✓ | | ✓ | No | Dev/test reset flag | | `ASPNETCORE_ENVIRONMENT` | ✓ | | ✓ | Yes | ASP.NET environment | | `ASPNETCORE_URLS` | ✓ | | ✓ | Yes | API binding address | | `SA_PASSWORD` | | | ✓ | Yes | SQL Server container | | `ACCEPT_EULA` | | | ✓ | Yes | SQL Server EULA | | `MSSQL_PID` | | | ✓ | No | SQL Server edition | | `DOTNET_RUNNING_IN_CONTAINER` | ✓ | | ✓ | No | Container flag | \* Either `DB_CONNECTION_STRING` OR the component variables (`DB_SERVER`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`) must be provided. ## Validation ### Backend Validation Variables are validated at startup: - Missing required variables cause application to fail - JWT_SECRET length is enforced (min 32 chars) - Connection string format is validated ### Frontend Validation The active website relies on runtime defaults for local development and the surrounding server environment in deployed environments. - `API_BASE_URL` defaults to `http://localhost:8080` - `SESSION_SECRET` falls back to a development-only local secret - `NODE_ENV` controls secure cookie behavior ## Example Configuration Files ### `.env.dev` (Backend/Docker) ```bash # Database DB_SERVER=sqlserver,1433 DB_NAME=Biergarten DB_USER=sa DB_PASSWORD=Dev_Password_123! # JWT Authentication Secrets ACCESS_TOKEN_SECRET= REFRESH_TOKEN_SECRET= CONFIRMATION_TOKEN_SECRET= WEBSITE_BASE_URL=http://localhost:3000 # Migration CLEAR_DATABASE=true # ASP.NET Core ASPNETCORE_ENVIRONMENT=Development ASPNETCORE_URLS=http://0.0.0.0:8080 # SQL Server Container SA_PASSWORD=Dev_Password_123! ACCEPT_EULA=Y MSSQL_PID=Express ``` ### Frontend local runtime example ```bash API_BASE_URL=http://localhost:8080 SESSION_SECRET= NODE_ENV=development ```