Environment reference
OpenPartner follows the principle that env is for secrets and build-time config; runtime content lives in the admin UI. So this list is shorter than you’d expect from competing products.
Required
| Variable | Description |
|---|---|
DATABASE_URL | Postgres connection string. |
SECRETS_ENCRYPTION_KEY | 32-byte hex. Used to encrypt SMTP passwords, Postmark tokens, etc. |
Generate a key with:
openssl rand -hex 32Optional
| Variable | Description |
|---|---|
OPENPARTNER_MODE | selfhost (default), flat, or revshare. Gates billing layer. |
COOKIE_DOMAIN | First-party cookie scope. Default: request host. |
MAIL_FROM | Default From: address. Overridable in admin UI. |
POSTMARK_SERVER_TOKEN | Postmark API token. Overridable in admin UI. |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD | SMTP fallback. Overridable. |
STRIPE_SECRET_KEY | Required for Connect payouts on hosted tiers and for billing the merchant subscription. |
STRIPE_WEBHOOK_SECRET | Webhook signing secret(s). Accepts a single value or a comma-separated list — Stripe’s “Event destinations” UI uses separate destinations for platform-account vs connected-account events, so you’ll have two secrets to verify against. |
STRIPE_FLAT_PRICE_ID | Stripe Price ID for the Hosted Flex monthly subscription (flat mode). |
ADMIN_API_KEY | Bootstrap / CI bearer. Bypasses Admin user, behaves like a headless admin. |
File uploads (brand logos, creator avatars)
Two backends, picked by OPENPARTNER_STORAGE_KIND. Default is fs — a local
directory served at /uploads/*. Switch to s3 if your runtime is ephemeral (DO App
Platform, Fly Machines, Heroku, etc.) or you just want a managed object store. Same env-var
shape on the Network app under NETWORK_*.
fs (default)
| Variable | Description |
|---|---|
OPENPARTNER_STORAGE_KIND | fs (default). |
OPENPARTNER_STORAGE_FS_DIR | Where to write files. Default: /var/lib/openpartner/uploads. Mount a docker volume here so uploads survive restarts. |
OPENPARTNER_STORAGE_FS_PUBLIC_BASE | Public URL base for the static handler. Default: ${API_URL}/uploads. Override if the API is behind a CDN or different hostname. |
s3 (any S3-compatible bucket — DO Spaces, AWS S3, Cloudflare R2, MinIO)
| Variable | Description |
|---|---|
OPENPARTNER_STORAGE_KIND | s3. |
OPENPARTNER_STORAGE_S3_BUCKET | Bucket name. |
OPENPARTNER_STORAGE_S3_REGION | Region (e.g. nyc3 for DO, us-east-1 for AWS). |
OPENPARTNER_STORAGE_S3_ENDPOINT | Custom endpoint URL. Required for non-AWS providers (e.g. https://nyc3.digitaloceanspaces.com). Omit for AWS S3. |
OPENPARTNER_STORAGE_S3_ACCESS_KEY_ID | Access key ID. |
OPENPARTNER_STORAGE_S3_SECRET_ACCESS_KEY | Secret access key. |
OPENPARTNER_STORAGE_S3_PUBLIC_BASE | Optional CDN URL base (e.g. https://uploads.cdn.openpartner.dev). When unset, URLs are constructed from endpoint + bucket. |
Uploads are written public-read with a 1-year immutable cache header. Object keys are
random hex (16 bytes), so directory enumeration isn’t possible — but make sure the bucket
itself doesn’t allow listing.
What’s NOT in env
These all live in the Config table and are managed from the admin UI:
- Program name (the brand partners see)
- Support email
- Active mail transport (Postmark vs. SMTP vs. none)
- Attribution model + lookback window
- Commission rules
Why? You can rotate them without redeploying, and self-host customers don’t have to manage config in two places.