22 KiB
Environment Variables
Purpose
This document is the production-facing reference for runtime environment keys. It lists key names, ownership, placeholder expectations, and redaction rules only; it must never include live values, secret-shaped examples, connection strings, tokens, or provider credentials.
For the code-level access pattern, use docs/configuration.md. That guide defines the explicit rule that runtime entrypoints read process.env, validate and normalize values, then pass typed options into packages and handlers. For historical scan context, use docs/env-access-inventory.md; do not copy raw scan output or .env* contents into this document.
Local placeholders
Local examples may name keys but must use obvious placeholders such as <DATABASE_URL> or <MAILJET_API_KEY>. Placeholders are documentation markers, not usable credentials, and local-only files must stay out of production secret distribution.
Use placeholder-only examples when explaining required shape:
DATABASE_URL=<DATABASE_URL>
SESSION_SECRET=<SESSION_SECRET>
AUDIT_CHAIN_SECRET=<AUDIT_CHAIN_SECRET>
MAILJET_API_KEY=<MAILJET_API_KEY>
Never replace those placeholders with real secrets in docs, support notes, pull requests, screenshots, or copied CI output.
Production secret sources
Production secrets must come from CI or runtime secret stores. They must not come from docs, committed files, issue comments, chat transcripts, or copied local .env files.
The owning deployment platform should inject values at runtime. CI jobs may reference secret names, but logs and verifier output must show key names, diagnostic codes, missing/present status, or parse status only.
Required runtime keys
These keys are required for normal production application runtime unless the deployment contract explicitly scopes the runtime away from the feature that owns the key.
| Key | Owner | Purpose | Safe diagnostic surface |
|---|---|---|---|
APP_NAME |
Shared web/API/worker runtime | Human-readable product name for titles, metadata, and seeded app configuration. | Key name and configured/unconfigured status. |
DATABASE_URL |
Web/API runtime and Prisma operations | Primary application database connection. | Key name, missing/present status, migration status code. |
SESSION_SECRET |
Core web/API runtime | Core session signing and verification boundary; forbidden on the customer-portal resource. | Key name and redacted validator code only. |
WEB_RUNTIME_SURFACE |
Web runtime boundary | Selects exactly one surface, core or portal; production web resources fail closed without it. |
Key name and enum-validation status only. |
PORTAL_SESSION_SECRET |
Customer-portal web runtime | Dedicated portal-cookie signing boundary; required only on hivegrid-portal and forbidden on core web. |
Key name and redacted validator code only. |
AUDIT_CHAIN_SECRET |
Web/API/MCP/worker audit boundary | HMAC authentication for AuditEvent v2 hashes and retention checkpoints; minimum 32 bytes and stable across the retention lifetime. | Key name and redacted validator code only. |
APP_BASE_DOMAIN |
Split-host routing boundary | Root domain used to derive canonical app, admin, and API hosts. | Key name and host-normalization status only. |
WEB_APP_HOST |
Tenant web runtime | Canonical host for tenant app traffic, such as app.<domain>. |
Key name and host-normalization status only. |
ADMIN_APP_HOST |
Admin web runtime | Canonical host for admin traffic, such as admin.<domain>. |
Key name and host-normalization status only. |
API_HOST |
API runtime | Canonical host for versioned API traffic, such as api.<domain>. |
Key name and host-normalization status only. |
PORTAL_APP_HOST |
Core/customer-portal web and mail-worker runtimes | Canonical host for the isolated customer portal and the origin for status-mail links; must differ from app, admin, API, and base-domain hosts. | Key name and host-normalization status only. |
CRYPTO_SECRET |
Web/API and mail-worker runtime | Shared tenant-envelope master key. worker-mail must receive the exact hivegrid-web value so portal setup capabilities can be decrypted only at delivery time. |
Key name and redacted validator code only; never print or compare the value in logs. |
ADMIN_CONNECTION_MASTER_KEY |
Core web, API and admin-sales mail worker | Dedicated envelope-wrapping key for tenant-less AdminDataConnection credentials. Staging and production use distinct values; never reuse CRYPTO_SECRET or a session secret. |
Key name and redacted validator code only; never print, compare or copy the value into logs or tickets. |
API_ACCESS_TOKEN |
Web/API runtime | Service-token boundary for internal and API operator calls. | Key name and redacted validator code only. |
JWT_SECRET |
API runtime | API session JWT signing and verification boundary. | Key name and redacted validator code only. |
ANALYTICS_TOKEN |
API runtime | Browser-facing anonymous analytics ingestion capability only; it never authorizes analytics reads or identity attribution. | Key name and redacted validator code only. |
MCP_RESOURCE_URL |
MCP connector runtime | Public origin of the MCP resource server; used for RFC 9728 protected-resource metadata and OAuth audience binding. | Key name and host-normalization status only. |
MCP_AUTHORIZATION_SERVER_URL |
Web/MCP runtime | Public origin of the OAuth authorization server (the web app) that issues MCP access tokens. | Key name and host-normalization status only. |
WEB_PUSH_VAPID_PUBLIC_KEY |
Web and webhook-worker push boundary | Shared browser subscription key for incoming-call Web Push. Production web and webhook-worker deployments must receive the same generated key pair source. | Key name, configured/unconfigured status, and validation code only. |
DIRECT_URL is database-owned and may be required by Prisma or deployment-specific migration workflows. Treat it as secret material whenever present, and document only whether the key is configured for the workflow being run.
Optional integration keys
Optional integration keys are feature-gated. Missing optional keys should produce clear disabled or unavailable status, not raw value output.
| Key | Owner | Used when | Safe diagnostic surface |
|---|---|---|---|
WORKER_ENABLED |
Worker runtime | Queue processors should start for the deployment. | Boolean enablement status and diagnostic code. |
BULLMQ_REDIS_URL |
Web/API enqueue and worker runtime | Queue-backed features are enabled and need BullMQ connectivity. | Key name, missing/present status, queue readiness code. |
REDIS_URL |
MCP shared store; web/API/worker fallback | Always required by MCP in production; elsewhere used only when BULLMQ_REDIS_URL is absent and the deployment intentionally uses the generic Redis key. |
Key name and readiness code only. |
AUTHENTIK_ADMIN_JIT_DATABASE_URL |
Authentik admin callback on the web runtime | Admin SSO is enabled and the verified callback may JIT-link or create an operator identity. The URL must authenticate as the execute-only hivegrid_authentik_jit role. |
Key name, configured/unconfigured status, and exact-role diagnostic only; never log the URL. |
MAILJET_API_KEY |
Mail provider boundary | Outbound Mailjet delivery is enabled. | Key name and redacted validator code only. |
API_KEY_LEGACY_PLAINTEXT_FALLBACK |
API-key cutover boundary | Temporary plaintext API-key lookup fallback is disabled by default; enable only during a bounded hash-backfill migration window. | Boolean status only; never record API-key material. |
MAILJET_FROM_EMAIL |
Mail provider boundary | Outbound Mailjet delivery is enabled. | Key name and sender-domain validation status only. |
MAILJET_FROM_NAME |
Mail provider boundary | A display name is needed for outbound mail. | Key name and configured/unconfigured status. |
MAILJET_SECRET_KEY |
Mail provider boundary | Outbound Mailjet delivery is enabled (Basic-Auth password paired with the public key). | Key name and redacted validator code only. |
MAILJET_WEBHOOK_SECRET |
Mail webhook boundary | Inbound Mailjet webhook Basic-Auth verification is enabled. | Key name and credential verification code only. |
LAGO_API_URL |
Billing provider boundary | Lago billing sync is enabled. | Key name and redacted URL validation code only. |
LAGO_API_KEY |
Billing provider boundary | Lago billing sync is enabled. | Key name and redacted validator code only. |
LAGO_WEBHOOK_SECRET |
Billing webhook boundary | Lago webhook ingestion is enabled. | Key name and signature verification code only. |
LAGO_TIMEOUT_MS |
Billing provider boundary | Lago billing sync uses a non-default timeout. | Timeout parse status only. |
MOLLIE_API_KEY |
Payment provider boundary | Mollie payment checkout or webhook refetch is enabled. | Key name, mode label, and redacted validator code only. |
MOLLIE_PROFILE_ID |
Payment provider boundary | Mollie payment creation requires an explicit website profile. | Key name and configured/unconfigured status. |
MOLLIE_TIMEOUT_MS |
Payment provider boundary | Mollie payment gateway uses a non-default timeout. | Timeout parse status only. |
BILLING_MOLLIE_WEBHOOK_URL |
General-worker recurring billing boundary | Recurring Lago invoices may create Mollie payments. | Key name and validation status only; the value must be the environment-specific HTTPS API webhook route. |
IMPORT_QUEUE_ENABLED |
Web enqueue and worker runtime | Import jobs should be sent through BullMQ. | Boolean enablement status and diagnostic code. |
IMPORT_QUEUE_RUNTIME_READY |
Web enqueue and worker runtime | Import queue processors and scan/import services are wired end to end. | Boolean readiness status and diagnostic code. |
PORTAL_GDPR_EXPORT_QUEUE_ENABLED |
Internal worker runtime | The import worker may consume only portal/privacy GDPR jobs from hivegrid.exports. |
Boolean enablement status and diagnostic code only. |
MISTRAL_API_KEY |
AI provider boundary | Mistral generation is enabled. | Key name and redacted provider-readiness code only. |
MISTRAL_MODEL |
AI provider boundary | Mistral generation uses a non-default model. | Model label only when approved for release records. |
AI_PROCESSING_REGION |
AI provider boundary | AI generation is enabled under a deployment-region policy. | Expected region label and confirmation status only. |
SCALEWAY_API_KEY |
AI provider boundary | Scaleway fallback generation is enabled. | Key name and redacted provider-readiness code only. |
SCALEWAY_MODEL |
AI provider boundary | Scaleway fallback uses a non-default model. | Model label only when approved for release records. |
SCALEWAY_BASE_URL |
AI provider boundary | Scaleway-compatible endpoint is configured. | Provider endpoint label or redacted URL validation code only. |
SCALEWAY_REGION |
AI provider boundary | Scaleway fallback generation is enabled. | Expected region label and confirmation status only. |
ALEPH_ALPHA_API_KEY |
AI provider boundary | Aleph Alpha fallback generation is enabled. | Key name and redacted provider-readiness code only. |
ALEPH_ALPHA_MODEL |
AI provider boundary | Aleph Alpha fallback uses a non-default model. | Model label only when approved for release records. |
ALEPH_ALPHA_BASE_URL |
AI provider boundary | Aleph Alpha-compatible endpoint is configured. | Provider endpoint label or redacted URL validation code only. |
STORAGE_PROVIDER |
Storage provider boundary | Runtime uploads should use a primary provider such as S3-compatible storage. | Provider label, configured/unconfigured status, and diagnostic code only. |
STORAGE_FALLBACK_PROVIDER |
Storage provider boundary | Runtime uploads may fall back to another configured provider. | Fallback provider label and diagnostic code only. |
STORAGE_ENDPOINT |
Storage provider boundary | S3-compatible storage is enabled. | Provider endpoint label or redacted URL validation code only. |
STORAGE_REGION |
Storage provider boundary | S3-compatible storage request signing is enabled. | Region label and configured/unconfigured status only. |
STORAGE_BUCKET |
Storage provider boundary | S3-compatible upload/download operations need a default bucket. | Bucket alias or configured/unconfigured status only; avoid customer-specific bucket names in incidents. |
STORAGE_ACCESS_KEY_ID |
Storage provider boundary | S3-compatible storage is enabled. | Key name and redacted validator code only. |
STORAGE_SECRET_ACCESS_KEY |
Storage provider boundary | S3-compatible storage is enabled. | Key name and redacted validator code only. |
GDPR_EXPORT_SSE_C_KEY_BASE64 |
GDPR export storage boundary | Portal/privacy export objects are encrypted with SSE-C. Production core/portal web and the dedicated export worker must receive the same canonical Base64 value for 32 random bytes. | Key name and missing/invalid status only; never log, diff, or print the value. |
STORAGE_SESSION_TOKEN |
Storage provider boundary | Temporary S3-compatible credentials are used. | Key name and redacted validator code only. |
STORAGE_PUBLIC_BASE_URL |
Storage provider boundary | A CDN or public base URL is configured for storage object URLs. | Provider endpoint label or redacted URL validation code only. |
STORAGE_FORCE_PATH_STYLE |
Storage provider boundary | The S3-compatible provider requires path-style bucket addressing. | Boolean status only. |
STORAGE_LOCAL_ROOT |
Storage provider boundary | Explicit local storage fallback is enabled for development or staging. | Key name and configured/unconfigured status only; never log filesystem contents. |
STORAGE_LOCAL_PUBLIC_BASE_URL |
Storage provider boundary | Local fallback storage needs public object URLs. | Redacted URL validation code only. |
Worker key group
WORKER_ENABLED controls whether queue processors start. Set it to true only in deployments that should run background jobs. MCP requires REDIS_URL in production for distributed abuse limits and readiness. When queue-backed web/API features enqueue jobs or workers process jobs, prefer BULLMQ_REDIS_URL for BullMQ Redis connectivity; those runtimes use REDIS_URL only as a fallback when BULLMQ_REDIS_URL is absent.
IMPORT_QUEUE_ENABLED and IMPORT_QUEUE_RUNTIME_READY must both be true before tenant import submissions enqueue jobs. Full mode owns hivegrid.exports too, so it also requires complete HTTPS STORAGE_*, a canonical GDPR_EXPORT_SSE_C_KEY_BASE64, and generic plus portal/privacy GDPR export services. Keep the gates disabled unless the worker runtime can process both queues end to end.
PORTAL_GDPR_EXPORT_QUEUE_ENABLED=true is a worker-only, internal alternative
for WORKER_QUEUE_GROUP=import. Keep both IMPORT_QUEUE_* gates unset or
false; the worker then owns only hivegrid.exports and requires complete
STORAGE_*, GDPR_EXPORT_SSE_C_KEY_BASE64 and portal/privacy GDPR export
service wiring. The same key is mandatory on both production web surfaces so
downloads remain server-proxied; it must never be placed in a URL or browser
header. The modes are
mutually exclusive and fail closed on mixed gates or another worker group.
worker-general requires MEILI_URL and the HiveGrid-scoped MEILI_API_KEY
whenever tenant hard-delete runs under production, required RLS, or a
staging/production Sentry marker. Missing values or a missing search client
abort startup before queue ownership so a deletion request cannot complete
while tenant documents remain indexed.
Staging and production worker-general services must also fail loud for
outbox and workflow fanout. Set OUTBOX_DISPATCHER_ENABLED=true,
OUTBOX_DISPATCHER_REQUIRED=true, WORKFLOW_TRIGGER_OUTBOX_ENABLED=true, and
WORKFLOW_TRIGGER_OUTBOX_REQUIRED=true on worker-general together with the
workflow executor URL, API_ACCESS_TOKEN service token, and mode described in docs/worker.md. These
keys are not required on the isolated mail, import, webhook, or plugin
worker groups unless those groups explicitly take ownership of the same queue
contract in a future topology.
Each Coolify worker service must set WORKER_QUEUE_GROUP to its isolated
queue ownership (general, mail, import, webhook, or plugin) plus a
unique WORKER_HEALTH_PORT/WORKER_ADMIN_PORT pair when those ports are
exposed. The worker-mail service owns transactional mail and webhook
delivery and must set TRANSACTIONAL_MAIL_OUTBOX_REQUIRED=true in staging and
production so queued mail cannot silently pile up behind a healthy container.
Keep MARKETING_SEQUENCES_ENABLED=false until the remaining email-sequences
seed data, persisted stats aggregation, Playwright E2E, Mailjet delivery
evidence/reconciliation, scheduler/deploy evidence, and deployment record
explicitly approve production delivery.
Troubleshooting worker configuration should report queue health, enablement state, and diagnostic codes. It must not print Redis URLs, credentials, database URLs, mail tokens, job payload secrets, or customer data.
Mail key group
Mailjet outbound delivery requires MAILJET_API_KEY, MAILJET_SECRET_KEY, and MAILJET_FROM_EMAIL together (the public/secret key pair forms the Basic-Auth credential). MAILJET_FROM_NAME is optional display metadata. MAILJET_WEBHOOK_SECRET belongs to inbound webhook Basic-Auth verification and must not be confused with the outbound API key pair.
Mailjet (Sinch) hosts in the EU (Frankfurt and Belgium) by default, so there is no region-selection variable for mail; data-residency posture is a procurement/account property rather than an env toggle, and must still be backed by account/subprocessor evidence.
Diagnostics may say that a required Mailjet key is missing, a sender domain is not configured, the expected region is not confirmed, or webhook signing verification failed. They must not include API keys, signing secrets, raw webhook bodies, signatures, message contents, tenant identifiers, or real attempt identifiers.
Deployment-region provider key group
AI_PROCESSING_REGION must match the approved deployment-region policy when AI generation is enabled. The cataloged AI provider keys currently include Mistral, Scaleway, and Aleph Alpha entries; deployment records must define the allowed provider order and region labels before production traffic is routed. SCALEWAY_REGION and SCALEWAY_BASE_URL are provider-specific markers and must match the deployment record.
LAGO_API_URL, LAGO_API_KEY, and LAGO_WEBHOOK_SECRET are the AD-27 billing-engine keys. MOLLIE_API_KEY, MOLLIE_PROFILE_ID, and the environment-specific BILLING_MOLLIE_WEBHOOK_URL are the payment-processor boundary keys. Keep Lago and Mollie production values separate from staging/testmode values, and never paste provider keys, webhook secrets, payment references, invoice payloads, tenant identifiers, or customer identifiers into docs or verification records.
Customer-portal runtime key group
The core and portal containers use the same immutable web image but separate resources and secrets. Set WEB_RUNTIME_SURFACE=core, SESSION_SECRET, DATABASE_RUNTIME_ROLE=hivegrid_app, and PORTAL_APP_HOST on core web. Set WEB_RUNTIME_SURFACE=portal, PORTAL_SESSION_SECRET, DATABASE_RUNTIME_ROLE=hivegrid_portal, PORTAL_APP_HOST, REDIS_URL, and the selected CAPTCHA provider keys on hivegrid-portal. Both web resources receive the same GDPR_EXPORT_SSE_C_KEY_BASE64 as the dedicated GDPR export worker; this export-decryption secret stays server-only. Core, portal, import worker, and general worker require complete STORAGE_* credentials but may use the same existing STORAGE_ACCESS_KEY_ID/STORAGE_SECRET_ACCESS_KEY pair; credential separation is optional and shared credentials are not a rollout blocker. The general worker must not receive the SSE-C key. For the tenant-export barrier only, import and general resolve SharedStore from non-empty REDIS_URL before BULLMQ_REDIS_URL and must target the same normalized Redis endpoint and database. The staging Compose reference maps storage credentials from WEB_STORAGE_*, WORKER_IMPORT_STORAGE_*, and WORKER_GENERAL_STORAGE_*; those sources may resolve to the same pair, while portal remains a separate Coolify resource. Never copy core session, OAuth, billing, ingress, migration, seed, or retired PORTAL_SERVER_* credentials into the portal resource. The exact operator matrix and rollout order live in docs/deploy/customer-portal.md.
Database key group
DATABASE_URL is the primary database connection key. DIRECT_URL is reserved for database and Prisma workflows that require a direct connection path. Both keys are secret material.
Database troubleshooting may reference migration status, Prisma command names, connection readiness codes, and key names. It must not include connection strings, database passwords, usernames, hosts, schemas containing customer data, or copied SQL output with sensitive records.
Redaction rules
All environment diagnostics must redact raw values. The allowed public surface is:
- environment key names;
- diagnostic codes;
- missing, present, invalid, enabled, disabled, or parsed status;
- high-level remediation text;
- CI job names and non-secret command names.
Forbidden surfaces include raw secret values, secret-shaped sample values, URLs with credentials, tokens, API keys, webhook signing secrets, Redis URLs, database URLs, customer data, and copied .env* files.
Troubleshooting
When a deployment fails because of configuration, first identify the owning runtime: web/API, worker, mail provider, webhook handler, or database operation. Then compare the reported key name and diagnostic code against this document and docs/configuration.md.
Use messages such as missing required env key DATABASE_URL, worker disabled by WORKER_ENABLED, queue config missing BULLMQ_REDIS_URL, or mail provider missing MAILJET_API_KEY. These messages are safe because they name keys and states without interpolating values.
If a fallback key is involved, state the resolution order explicitly: BULLMQ_REDIS_URL is preferred for worker Redis, and REDIS_URL is considered only when the worker runtime allows the fallback. If ambiguity remains, update the runtime configuration contract rather than adding real values to documentation.