* Integrate Spectre.Console into seed application, use async data loading * Replace stored-procedure repositories with Dapper-based repositories Removes the USP_* stored procedures for Auth, Location, and Brewery data access in favour of services built with Dapper. Adds a new Features.Locations slice and optimistic concurrency support for the Brewery slice. * Add new documentation for Dapper migration/database schema * Update FluentAssertions to most recent open source ver * Update XML doc comment in backend projects * Modify brewery location dto to include denormalized data * - Updated column names from 'Timer' to 'RowVersion' in schema.sql for - Introduced new BeerPost entity and updated BreweryPost and BreweryPostLocation entities to use 'RowVersion' for concurrency. - Modified UserAccount, UserCredential, UserVerification, City, StateProvince, and Country entities to use 'RowVersion' instead of 'Timer'. - Updated tests and command handlers to reflect changes in concurrency token from 'Timer' to 'RowVersion'. - Adjusted BreweryDto and BreweryDtoMapper to include 'RowVersion' and updated mapping logic accordingly. - Ensured all repository methods and interfaces are aligned with the new concurrency handling approach. * updates * Add BeerStyle entity and related properties; refactor BreweryDto to remove BeerPosts * Fix Api.Specs test failures: stale Timer column refs and missing test.user fixture * Remove repository tests, usages of registration dto used in repo * archive old stored procs/functions * update stale docs * Add instructions for generating cryptographically secure base64 secrets on macOS/Linux and Windows
12 KiB
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 (web/frontend)
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:
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:
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
JSON Web Token (JWT) authentication secrets (backend)
The backend uses separate secrets for different token types to enable independent key rotation and validation isolation.
# Access token secret (1-hour tokens)
ACCESS_TOKEN_SECRET=<generated-secret> # Signs short-lived access tokens
# Refresh token secret (21-day tokens)
REFRESH_TOKEN_SECRET=<generated-secret> # Signs long-lived refresh tokens
# Confirmation token secret (30-minute tokens)
CONFIRMATION_TOKEN_SECRET=<generated-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:
- Use at least 32 characters per secret
- Use 127 or more characters in production
- Generate secrets with a cryptographically secure random function
- Never reuse secrets across token types or environments
- Rotate secrets periodically in production
Generate Secrets:
macOS/Linux - Generate a cryptographically secure base64 secret (127 raw bytes)
openssl rand -base64 127
Windows - PowerShell 5.1 compatible (cryptographically secure, 127 raw bytes)
$bytes = New-Object byte[] 127
$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
$rng.GetBytes($bytes)
[Convert]::ToBase64String($bytes)
$rng.Dispose()
Windows - PowerShell 7+ compatible (cryptographically secure, 127 raw bytes)
[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(127))
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
CLEAR_DATABASE=true
- Required: No
- Default:
false - Effect: If set to
true, drops and recreates the database during migrations - Usage: Development and testing environments only
- Warning: Never use in production
ASP.NET Core configuration
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 (web/frontend)
The active website does not use the old Next.js/Prisma environment model. Its core runtime variables are:
API_BASE_URL=http://localhost:8080 # Base URL for the .NET API
SESSION_SECRET=<generated-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:
web/frontend/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
SMTP configuration (backend)
Read by Infrastructure.Email/SmtpEmailProvider.cs for sending confirmation and
account emails.
SMTP_HOST=mailpit # Required, no default
SMTP_PORT=1025 # Optional, defaults to 587
SMTP_USERNAME=<username> # Optional, no default
SMTP_PASSWORD=<password> # Optional, no default
SMTP_USE_SSL=false # Optional, defaults to true
SMTP_FROM_EMAIL=noreply@thebiergarten.app # Required, no default
SMTP_FROM_NAME=The Biergarten App # Optional, defaults to "The Biergarten"
- Implementation:
Infrastructure.Email/SmtpEmailProvider.csthrows on startup ifSMTP_HOSTorSMTP_FROM_EMAILis missing - Local dev: point at the
mailpitDocker service (SMTP on port 1025, web UI on http://localhost:8025) - Production: point at a real provider (SendGrid, Mailgun, Amazon SES, and so on)
Docker-specific variables
SQL Server container
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_PASSWORDfor application containers
Environment file structure
Backend/Docker (web/ directory)
web/.env.example # Template (tracked in Git)
web/.env.dev # Development config (gitignored)
web/.env.test # Testing config (gitignored)
web/.env.prod # Production config (gitignored)
Setup:
cp web/.env.example web/.env.dev
# Edit web/.env.dev with your values
Legacy frontend variables
Variables for the archived Next.js frontend (archive/next-js-web-app/) have
been removed from this active reference, since that app is retained for
reference only and is not run as part of the active stack.
Docker Compose Mapping:
web/docker-compose.dev.yaml→web/.env.devweb/docker-compose.test.yaml→web/.env.testweb/docker-compose.prod.yaml→web/.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 | ||
SMTP_HOST |
✓ | ✓ | Yes | SMTP server host | |
SMTP_PORT |
✓ | ✓ | No | Defaults to 587 |
|
SMTP_USERNAME |
✓ | ✓ | No | SMTP auth username | |
SMTP_PASSWORD |
✓ | ✓ | No | SMTP auth password | |
SMTP_USE_SSL |
✓ | ✓ | No | Defaults to true |
|
SMTP_FROM_EMAIL |
✓ | ✓ | Yes | Email sender address | |
SMTP_FROM_NAME |
✓ | ✓ | No | Defaults to The Biergarten |
|
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 (
ACCESS_TOKEN_SECRET,REFRESH_TOKEN_SECRET,CONFIRMATION_TOKEN_SECRET,SMTP_HOST,SMTP_FROM_EMAIL, DB connection values) cause the application to fail with anInvalidOperationException - No minimum length is enforced on the token secrets in code; the "minimum 32 characters" guidance above is a recommendation, not an enforced check
Frontend validation
The active website relies on runtime defaults for local development and the surrounding server environment in deployed environments.
API_BASE_URLdefaults tohttp://localhost:8080SESSION_SECRETfalls back to a development-only local secretNODE_ENVcontrols secure cookie behavior
Example configuration files
.env.dev (backend/Docker)
# Database
DB_SERVER=sqlserver,1433
DB_NAME=Biergarten
DB_USER=sa
DB_PASSWORD=Dev_Password_123!
# JWT Authentication Secrets
ACCESS_TOKEN_SECRET=<generated-with-openssl>
REFRESH_TOKEN_SECRET=<generated-with-openssl>
CONFIRMATION_TOKEN_SECRET=<generated-with-openssl>
WEBSITE_BASE_URL=http://localhost:3000
# SMTP (Mailpit in dev)
SMTP_HOST=mailpit
SMTP_PORT=1025
SMTP_USE_SSL=false
SMTP_FROM_EMAIL=noreply@thebiergarten.app
SMTP_FROM_NAME=The Biergarten App
# 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
API_BASE_URL=http://localhost:8080
SESSION_SECRET=<generated-with-openssl>
NODE_ENV=development