Environment Variables
Complete reference of all configuration options. Environment variables use double underscore __ as separator for nested config.
Backend (ASP.NET Core)
Core
| Variable | Required | Default | Description |
PORT | No | 5191 | API server port |
ConnectionStrings__DefaultConnection | Yes | - | PostgreSQL connection string |
AllowedOrigin | Yes | - | Frontend URL for CORS |
Security
| Variable | Required | Default | Description |
Security__Secret | Yes | - | JWT signing key (min 64 chars) |
Security__Issuer | Yes | - | JWT issuer |
Security__Audience | Yes | - | JWT audience |
Security__AccessTokenValidityMinutes | No | 15 | Access token lifetime |
Security__RefreshTokenValidityDays | No | 1 | Refresh token lifetime |
Security__RefreshTokenValidityDaysExtended | No | 30 | Extended refresh (remember me) |
Security__UseHttps | No | true | HTTPS for cookies |
Security__UseRateLimiting | No | true | Enable rate limiting |
Security__AdminUserNames | No | - | Comma-separated admin usernames |
Security__HangfireTokenValidityMinutes | No | 1440 | Hangfire dashboard JWT lifetime |
Account Settings
| Variable | Required | Default | Description |
Security__Account__EmailConfirmationTokenValidityMinutes | No | 1440 | Email token lifetime |
Security__Account__EmailConfirmationCooldownMinutes | No | 2 | Resend cooldown |
Security__Account__PasswordResetTokenValidityMinutes | No | 60 | Password reset token lifetime |
Security__Account__PasswordResetCooldownMinutes | No | 2 | Reset request cooldown |
Security__Account__RegistrationExpiryDays | No | 10 | Unconfirmed registration expiry |
Security__Account__RegistrationWarningDays | No | 7 | Warning before expiry |
Security__Account__PendingUserNotificationDays | No | 7 | Admin reminder interval |
Object Storage (Cloudflare R2)
| Variable | Required | Default | Description |
ObjectStorage__Provider | Yes | - | Storage provider (R2) |
ObjectStorage__Endpoint | Yes | - | S3 endpoint URL |
ObjectStorage__AccessKeyId | Yes | - | Access key ID |
ObjectStorage__SecretAccessKey | Yes | - | Secret access key |
ObjectStorage__BucketName | Yes | - | Bucket name |
ObjectStorage__UseHttps | No | true | Use HTTPS for S3 |
ObjectStorage__SignedUrlExpirationMinutes | No | 60 | Download URL lifetime |
ObjectStorage__UploadUrlExpirationMinutes | No | 5 | Upload URL lifetime |
ObjectStorage__MaxFileSizeMB | Yes | 10 | Max file size |
ObjectStorage__AllowedMimeTypes | Yes | image/jpeg,image/png,image/webp | Allowed MIME types |
Application
| Variable | Required | Default | Description |
Application__SwaggerRoutePrefix | No | swagger | Swagger UI path |
Application__MaxImagesPerMarker | Yes | 5 | Max images per marker |
Application__TrashRetentionDays | Yes | 30 | Days before permanent deletion |
Application__AbandonedFileRetentionHours | No | 24 | Orphaned file cleanup threshold |
Hangfire
| Variable | Required | Default | Description |
Hangfire__DashboardUrl | No | /hangfire | Dashboard path |
Job schedules are configured in appsettings.json under Hangfire:JobsCron.
Email (Resend)
| Variable | Required | Default | Description |
Integrations__Email__Resend__ApiKey | Yes | - | Resend API key |
Integrations__Email__Resend__From__Email | Yes | - | Sender email |
Integrations__Email__Resend__From__Name | Yes | - | Sender display name |
Integrations__Email__Resend__AppDomain | No | unicorn-trails.site | App domain for email links |
Geocoding
| Variable | Required | Default | Description |
Integrations__Geocode__ApiKey | No | - | Geocode API key |
Integrations__Geocode__BaseUrl | No | - | Geocode base URL |
Integrations__Geocode__TimeoutSeconds | No | 30 | Request timeout |
Integrations__Geocode__Retry__MaxAttempts | No | 3 | Retry attempts |
Sentry
| Variable | Required | Default | Description |
Integrations__Sentry__Dsn | No | - | Sentry DSN (enables if set) |
Integrations__Sentry__Tracing__SampleRate | No | 0.1 | Trace sample rate |
Integrations__Sentry__Diagnostics__MaxBreadcrumbs | No | 50 | Max breadcrumbs |
Integrations__Sentry__Diagnostics__AttachStacktrace | No | true | Attach stack traces |
Integrations__Sentry__Diagnostics__SendDefaultPii | No | false | Send PII |
RAILWAY_GIT_COMMIT_SHA | No | dev | Release version (Railway auto-sets) |
Cloudflare Turnstile (CAPTCHA)
| Variable | Required | Default | Description |
Integrations__Turnstile__SecretKey | Yes | - | Turnstile secret key |
Integrations__Turnstile__VerifyUrl | No | https://challenges.cloudflare.com/turnstile/v0/siteverify | Verify endpoint |
Integrations__Turnstile__TimeoutSeconds | No | 10 | Request timeout |
Frontend (Vite)
Required
| Variable | Required | Description |
VITE_API_URL | Yes | Backend API URL |
Optional
| Variable | Default | Description |
VITE_HANGFIRE_PATH | /hangfire | Hangfire dashboard path |
VITE_MAX_IMAGES_PER_MARKER | 5 | Max images per marker |
VITE_MAX_FILE_SIZE_MB | 50 | Frontend file size limit (pre-compression) |
VITE_API_FILE_LIMIT_MB | 10 | Backend file size limit (post-compression) |
VITE_ACCEPTED_IMAGE_TYPES | image/jpeg,image/png,image/webp | Allowed MIME types |
VITE_SENTRY_DSN | - | Sentry DSN |
VITE_TURNSTILE_SITE_KEY | - | Cloudflare Turnstile site key |
VITE_APP_VERSION | dev | App version for Sentry |
Build-Time (Sentry Source Maps)
| Variable | Description |
SENTRY_AUTH_TOKEN | Sentry CLI auth token |
SENTRY_ORG | Sentry organization |
SENTRY_PROJECT | Sentry project name |
E2E Testing
| Variable | Description |
E2E_USERNAME | Test user username |
E2E_PASSWORD | Test user password |
E2E_BASE_URL | Frontend URL for tests |
E2E_API_URL | Backend URL for tests |