Files
orion/docs/deployment/environment.md
Samir Boulahtit c2c0e3c740
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
refactor: rename platform_domain → main_domain to avoid confusion with platform.domain
The setting `settings.platform_domain` (the global/main domain like "wizard.lu")
was easily confused with `platform.domain` (per-platform domain like "rewardflow.lu").
Renamed to `settings.main_domain` / `MAIN_DOMAIN` env var across the entire codebase.

Also updated docs to reflect the refactored store detection logic with
`is_platform_domain` / `is_subdomain_of_platform` guards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 04:45:28 +01:00

17 KiB

Environment Variables Reference

All configuration for the Orion platform is managed through environment variables, loaded via Pydantic Settings from an .env file or the process environment. This page provides a complete reference for every variable recognised by app/core/config.py.

Variables are read at startup and exposed through the settings singleton. In most cases the defaults are tuned for local development; production deployments must override the security-sensitive values listed in the Production Checklist at the bottom of this page.


Core / Project

Metadata used in the OpenAPI schema and health endpoints.

Variable Description Default Required
PROJECT_NAME Display name shown in API docs and health responses Orion - Multi-Store Marketplace Platform No
VERSION Semantic version reported by the platform 2.2.0 No

Database

!!! danger "Production requirement" You must set DATABASE_URL to a real PostgreSQL connection string in every non-development environment. The default value contains a placeholder password and should never be used in production.

Variable Description Default Required
DATABASE_URL PostgreSQL connection string (postgresql://user:pass@host:port/db) postgresql://orion_user:secure_password@localhost:5432/orion_db Yes

Admin Initialisation

Used by init_production.py and the database seeder to create the initial platform administrator account.

!!! warning "Change the default password" The default ADMIN_PASSWORD is admin123. The production validation check will emit a warning if this value is left unchanged.

Variable Description Default Required
ADMIN_EMAIL Email address for the initial admin account admin@orion.lu No
ADMIN_USERNAME Username for the initial admin account admin No
ADMIN_PASSWORD Password for the initial admin account admin123 No (but must change in production)
ADMIN_FIRST_NAME First name of the admin user Platform No
ADMIN_LAST_NAME Last name of the admin user Administrator No

JWT Authentication

Controls JSON Web Token generation and expiry.

!!! danger "Production requirement" JWT_SECRET_KEY must be replaced with a strong random value. Generate one with:

```bash
openssl rand -hex 32
```
Variable Description Default Required
JWT_SECRET_KEY Secret used to sign and verify JWTs change-this-in-production Yes
JWT_EXPIRE_HOURS Hours component of the token lifetime 24 No
JWT_EXPIRE_MINUTES Minutes component of the token lifetime 30 No

API Server

Settings passed to Uvicorn when the application starts.

Variable Description Default Required
API_HOST Bind address for the API server 0.0.0.0 No
API_PORT Port the API server listens on 8000 No
DEBUG Enable debug mode (extra logging, auto-reload) True No (set False in production)

Documentation

Variable Description Default Required
DOCUMENTATION_URL URL where the MkDocs site is served http://localhost:8001 No

Security / Middleware

!!! warning "Restrict allowed hosts" The default ALLOWED_HOSTS value of ["*"] accepts requests with any Host header. In production, restrict this to your actual domain names.

Variable Description Default Required
ALLOWED_HOSTS JSON list of permitted Host header values ["*"] No (but restrict in production)
RATE_LIMIT_ENABLED Enable request rate limiting True No
RATE_LIMIT_REQUESTS Maximum number of requests per window 100 No
RATE_LIMIT_WINDOW Rate limit window duration in seconds 3600 No

Logging

Variable Description Default Required
LOG_LEVEL Python log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) INFO No
LOG_FILE Path to a log file; None means stdout only None No

Platform Domain

Controls the base domain for store subdomains and custom-domain features.

Variable Description Default Required
MAIN_DOMAIN Root domain under which store subdomains are created wizard.lu No
ALLOW_CUSTOM_DOMAINS Allow stores to use their own domain names True No
REQUIRE_DOMAIN_VERIFICATION Require DNS verification before activating a custom domain True No
SSL_PROVIDER SSL certificate provider (letsencrypt, cloudflare, manual) letsencrypt No
AUTO_PROVISION_SSL Automatically provision SSL certificates for custom domains False No
DNS_VERIFICATION_PREFIX TXT record prefix used for domain ownership verification _orion-verify No
DNS_VERIFICATION_TTL TTL in seconds for DNS verification records 3600 No

Platform Limits

Guard-rails for multi-tenant resource usage.

Variable Description Default Required
MAX_STORES_PER_USER Maximum number of stores a single user can own 5 No
MAX_TEAM_MEMBERS_PER_STORE Maximum team members allowed per store 50 No
INVITATION_EXPIRY_DAYS Days before a team invitation link expires 7 No

Stripe Billing

!!! info "Required for payments" All three Stripe keys must be set to enable subscription billing and payment processing. Obtain them from the Stripe Dashboard.

Variable Description Default Required
STRIPE_SECRET_KEY Stripe secret API key "" (empty) Yes (for payments)
STRIPE_PUBLISHABLE_KEY Stripe publishable API key "" (empty) Yes (for payments)
STRIPE_WEBHOOK_SECRET Stripe webhook signing secret "" (empty) Yes (for payments)
STRIPE_TRIAL_DAYS Length of the free trial period in days 30 No

Email Configuration

Orion supports multiple email providers. Set EMAIL_PROVIDER to choose one, then configure the matching provider-specific variables below.

Variable Description Default Required
EMAIL_PROVIDER Email transport backend (smtp, sendgrid, mailgun, ses) smtp No
EMAIL_FROM_ADDRESS Sender address for outgoing emails noreply@orion.lu No
EMAIL_FROM_NAME Sender display name Orion No
EMAIL_REPLY_TO Optional reply-to address "" (empty) No
EMAIL_ENABLED Master switch to enable/disable all outgoing email True No
EMAIL_DEBUG Log emails to console instead of sending (development only) False No

SMTP Settings

Used when EMAIL_PROVIDER=smtp.

Variable Description Default Required
SMTP_HOST SMTP server hostname localhost No
SMTP_PORT SMTP server port 587 No
SMTP_USER SMTP authentication username "" (empty) No
SMTP_PASSWORD SMTP authentication password "" (empty) No
SMTP_USE_TLS Use STARTTLS (port 587) True No
SMTP_USE_SSL Use implicit SSL (port 465) False No

SendGrid Settings

Used when EMAIL_PROVIDER=sendgrid.

Variable Description Default Required
SENDGRID_API_KEY SendGrid API key "" (empty) Yes (if using SendGrid)

Mailgun Settings

Used when EMAIL_PROVIDER=mailgun.

Variable Description Default Required
MAILGUN_API_KEY Mailgun API key "" (empty) Yes (if using Mailgun)
MAILGUN_DOMAIN Mailgun sending domain "" (empty) Yes (if using Mailgun)

Amazon SES Settings

Used when EMAIL_PROVIDER=ses.

Variable Description Default Required
AWS_ACCESS_KEY_ID AWS access key for SES "" (empty) Yes (if using SES)
AWS_SECRET_ACCESS_KEY AWS secret key for SES "" (empty) Yes (if using SES)
AWS_REGION AWS region for the SES endpoint eu-west-1 No

Storefront Defaults

Default locale and currency applied to new storefronts. Individual stores can override these through the admin interface or the AdminSetting database table.

Variable Description Default Required
DEFAULT_STOREFRONT_LOCALE Locale code for currency and number formatting fr-LU No
DEFAULT_CURRENCY ISO 4217 currency code EUR No

Seed Data

Controls the volume of demo data generated by the database seeder.

Variable Description Default Required
SEED_DEMO_STORES Number of demo stores to create 3 No
SEED_CUSTOMERS_PER_STORE Number of demo customers per store 15 No
SEED_PRODUCTS_PER_STORE Number of demo products per store 20 No
SEED_ORDERS_PER_STORE Number of demo orders per store 10 No

Celery / Redis

Background task processing. When USE_CELERY is False, tasks fall back to FastAPI's built-in BackgroundTasks.

!!! tip "Enable Celery in production" Set USE_CELERY=True and ensure a Redis instance is reachable at REDIS_URL for reliable background task processing.

Variable Description Default Required
REDIS_URL Redis connection string used as Celery broker and result backend redis://localhost:6379/0 No
USE_CELERY Use Celery for background tasks instead of FastAPI BackgroundTasks False No (set True in production)
FLOWER_URL URL of the Flower monitoring dashboard http://localhost:5555 No
FLOWER_PASSWORD Password for Flower authentication changeme No (but change in production)

Sentry

Error tracking and performance monitoring via Sentry.

Variable Description Default Required
SENTRY_DSN Sentry Data Source Name; None disables Sentry None No
SENTRY_ENVIRONMENT Environment tag sent with events (development, staging, production) development No
SENTRY_TRACES_SAMPLE_RATE Fraction of transactions sampled for performance monitoring (0.0--1.0) 0.1 No

Monitoring

Prometheus metrics and Grafana dashboard integration.

Variable Description Default Required
ENABLE_METRICS Expose a /metrics endpoint for Prometheus scraping False No (set True in production)
GRAFANA_URL URL of the Grafana instance https://grafana.wizard.lu No
GRAFANA_ADMIN_USER Grafana admin username admin No
GRAFANA_ADMIN_PASSWORD Grafana admin password "" (empty) No

Cloudflare R2 Storage

Object storage for media uploads. When STORAGE_BACKEND is local, files are stored on the server filesystem.

Variable Description Default Required
STORAGE_BACKEND Storage backend to use (local or r2) local No
R2_ACCOUNT_ID Cloudflare account ID None Yes (if using R2)
R2_ACCESS_KEY_ID R2 API access key None Yes (if using R2)
R2_SECRET_ACCESS_KEY R2 API secret key None Yes (if using R2)
R2_BUCKET_NAME R2 bucket name orion-media No
R2_PUBLIC_URL Custom public URL for media access (e.g. https://media.yoursite.com) None No

Loyalty Module

Configuration for the loyalty module (stamp/points programs, wallet integration). All variables use the LOYALTY_ prefix and are managed by app/modules/loyalty/config.py.

Anti-Fraud Defaults

Variable Description Default Required
LOYALTY_DEFAULT_COOLDOWN_MINUTES Minimum minutes between stamps for the same card 15 No
LOYALTY_MAX_DAILY_STAMPS Maximum stamps per card per day 5 No
LOYALTY_PIN_MAX_FAILED_ATTEMPTS Failed PIN attempts before lockout 5 No
LOYALTY_PIN_LOCKOUT_MINUTES Duration of PIN lockout in minutes 30 No

Points

Variable Description Default Required
LOYALTY_DEFAULT_POINTS_PER_EURO Points earned per euro spent 10 No

Google Wallet

!!! info "Required for Google Wallet passes" Both variables must be set for loyalty cards to appear in Google Wallet. See Hetzner Step 25 for setup guide.

Variable Description Default Required
LOYALTY_GOOGLE_ISSUER_ID Google Wallet Issuer ID (numeric string from Pay & Wallet Console) None Yes (for Google Wallet)
LOYALTY_GOOGLE_SERVICE_ACCOUNT_JSON Path to the Google service account JSON key file None Yes (for Google Wallet)

Apple Wallet

!!! info "Required for Apple Wallet passes" All five variables must be set for .pkpass generation. Requires an Apple Developer account ($99/year).

Variable Description Default Required
LOYALTY_APPLE_PASS_TYPE_ID Pass type identifier (e.g., pass.com.example.loyalty) None Yes (for Apple Wallet)
LOYALTY_APPLE_TEAM_ID Apple Developer Team ID None Yes (for Apple Wallet)
LOYALTY_APPLE_WWDR_CERT_PATH Path to Apple WWDR intermediate certificate None Yes (for Apple Wallet)
LOYALTY_APPLE_SIGNER_CERT_PATH Path to pass signing certificate (.pem) None Yes (for Apple Wallet)
LOYALTY_APPLE_SIGNER_KEY_PATH Path to pass signing private key (.pem) None Yes (for Apple Wallet)

QR Code

Variable Description Default Required
LOYALTY_QR_CODE_SIZE QR code image size in pixels 300 No

Cloudflare CDN / Proxy

Variable Description Default Required
CLOUDFLARE_ENABLED Set to True when the application sits behind Cloudflare proxy (adjusts trusted-proxy headers) False No (set True when proxied)

Production Checklist

Before deploying to production, ensure the following variables are set correctly. Items marked critical will trigger a startup warning if left at their default values.

!!! danger "Critical -- must change" - [x] DATABASE_URL -- point to a production PostgreSQL instance - [x] JWT_SECRET_KEY -- generate with openssl rand -hex 32 - [x] ADMIN_PASSWORD -- choose a strong, unique password - [x] DEBUG -- set to False - [x] ALLOWED_HOSTS -- restrict to your domain(s)

!!! warning "Strongly recommended" - [x] USE_CELERY -- set to True with a production Redis instance - [x] FLOWER_PASSWORD -- change from the default changeme - [x] ENABLE_METRICS -- set to True for observability - [x] SENTRY_DSN -- configure for error tracking - [x] SENTRY_ENVIRONMENT -- set to production - [x] STORAGE_BACKEND -- set to r2 for scalable media storage - [x] CLOUDFLARE_ENABLED -- set to True if behind Cloudflare proxy

!!! info "Required for specific features" - [x] Payments: STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET - [x] Email (SendGrid — recommended): EMAIL_PROVIDER=sendgrid, SENDGRID_API_KEY — handles transactional + marketing in one account - [x] Email (Mailgun): MAILGUN_API_KEY, MAILGUN_DOMAIN — transactional only, no marketing features - [x] Email (SES): AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY — cheapest at scale - [x] R2 Storage: R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY - [x] Google Wallet: LOYALTY_GOOGLE_ISSUER_ID, LOYALTY_GOOGLE_SERVICE_ACCOUNT_JSON - [ ] Apple Wallet: LOYALTY_APPLE_PASS_TYPE_ID, LOYALTY_APPLE_TEAM_ID, LOYALTY_APPLE_WWDR_CERT_PATH, LOYALTY_APPLE_SIGNER_CERT_PATH, LOYALTY_APPLE_SIGNER_KEY_PATH

Example .env file (production)

# Core
DATABASE_URL=postgresql://orion:STRONG_PASSWORD@db.internal:5432/orion
JWT_SECRET_KEY=a]3f...your-random-hex-here...9c2b
DEBUG=False
ALLOWED_HOSTS=["wizard.lu","*.wizard.lu"]

# Admin
ADMIN_PASSWORD=your-strong-admin-password

# Celery / Redis
REDIS_URL=redis://redis.internal:6379/0
USE_CELERY=True
FLOWER_PASSWORD=a-secure-flower-password

# Stripe
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Email (example: SendGrid)
EMAIL_PROVIDER=sendgrid
SENDGRID_API_KEY=SG....

# R2 Storage
STORAGE_BACKEND=r2
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_PUBLIC_URL=https://media.wizard.lu

# Monitoring
ENABLE_METRICS=True
SENTRY_DSN=https://examplePublicKey@o0.ingest.sentry.io/0
SENTRY_ENVIRONMENT=production
CLOUDFLARE_ENABLED=True

# Google Wallet (Loyalty)
LOYALTY_GOOGLE_ISSUER_ID=3388000000023089598
LOYALTY_GOOGLE_SERVICE_ACCOUNT_JSON=/app/google-wallet-sa.json