SendGrid handles both transactional emails and marketing campaigns under one account. Updated alertmanager SMTP placeholders, hetzner setup guide (Step 19.5), and environment reference to recommend SendGrid as the primary email provider. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 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 |
|---|---|---|---|
PLATFORM_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 |
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
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