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>
378 lines
14 KiB
Markdown
378 lines
14 KiB
Markdown
# 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](#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](https://dashboard.stripe.com/apikeys).
|
|
|
|
| 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](https://sentry.io).
|
|
|
|
| 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)
|
|
|
|
```bash
|
|
# 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
|
|
```
|