Skip to main content

Self-Hosted Environment Reference

Start with the product repository's .env.example. It is the smallest supported Compose configuration. Use .env.full.example when you need an optional setting; this page explains which settings belong together and when to change them.

After editing .env, validate interpolation without printing the resolved configuration:

docker compose config --quiet

Do not commit .env, paste it into support requests, or expose the output of docker compose config: the resolved output contains secrets.

Required production values

Generate each secret independently with openssl rand -hex 32. Keep the old values through every upgrade and store a recovery copy outside the server.

VariableProduction valueWhy it matters
POSTGRES_PASSWORDUnique random passwordProtects the bundled PostgreSQL database.
WEB_ORIGINPublic HTTPS app origin, such as https://kanera.example.comUsed for browser links, CORS, and authentication flows. Do not include a trailing slash.
COOKIE_DOMAINApp hostname, such as kanera.example.comScope for the refresh cookie.
COOKIE_SECUREtrueRequired when the app is served over HTTPS.
JWT_SECRETStable random secret, at least 16 charactersSigns user sessions. Rotation signs everyone out.
MCP_INTERNAL_SECRETStable random secret, at least 32 characters and different from JWT_SECRETLets the MCP and public API services exchange audience-bound OAuth credentials without forwarding an MCP token into /api/v1. Both services must always use the same value.
MFA_ENCRYPTION_KEYStable random secret, at least 32 charactersProtects authenticator enrollment and challenges. Rotation invalidates enrolled authenticators.
MEDIA_SIGNING_SECRETStable random secret, at least 32 charactersSigns private media URLs. Rotation invalidates existing signed URLs.
SECRETS_ENCRYPTION_KEYStable random secret, at least 32 characters and different from JWT_SECRETEncrypts SMTP, storage, webhook, and integration credentials stored in the database.

KANERA_DEPLOYMENT_MODE defaults to self_hosted. Hosted mode and its Stripe, PostHog, plan-limit, and licensing variables are for Kanera-operated deployments and should remain unset on a self-hosted installation.

Compose supplies NODE_ENV=production and ANALYTICS_ENABLED=false. Leave ANALYTICS_PROVIDER, POSTHOG_PROJECT_KEY, POSTHOG_API_HOST, every STRIPE_*, HOSTED_*, and hosted-mode token unset. These settings do not turn a self-hosted installation into Kanera Cloud.

Public URLs and services

VariableDefaultSet it when
KANERA_ENVIRONMENTproduction in production ComposeYou need a different API-key prefix for development, test, or staging.
API_PUBLIC_URLWEB_ORIGINThe browser-facing app API uses a different public origin.
KANERA_PUBLIC_API_URLhttp://public-api:3001 in ComposeMCP or another internal process reaches the public API somewhere other than its Compose service address. This is an internal URL, not the browser-facing API origin.
PUBLIC_API_OAUTH_ISSUERhttp://localhost:3001You expose OAuth or the public API remotely; use its browser-reachable HTTPS origin.
MCP_SERVER_PUBLIC_URLhttp://localhost:3002/mcpYou expose remote MCP; use the complete public /mcp URL.
MCP_PUBLIC_URLDerived from MCP_SERVER_PUBLIC_URL by ComposeYou run the MCP service outside the bundled Compose wiring.
OAUTH_ISSUER_URLDerived from PUBLIC_API_OAUTH_ISSUER by ComposeYou run MCP outside the bundled Compose wiring.
API_PORT, PUBLIC_API_PORT, WORKER_PORT, MCP_PORT3000, 3001, 3003, 3002You run services outside Compose or need different internal listener ports.
API_TRUST_PROXY, PUBLIC_API_TRUST_PROXY, MCP_TRUST_PROXYfalse, false, trueA trusted reverse proxy supplies the real client IP. Never trust forwarded headers from arbitrary clients.

The browser connects to web; do not publish the main api service. See Services and Routing before exposing the public API or MCP.

Accounts and authentication

VariableDefaultPurpose
SIGNUPS_ENABLEDtrueSet false to stop public signup and new organisation creation. Existing organisation invitation links still work.
EMAIL_VERIFICATION_ENABLEDfalseRequire a six-digit email check for signup, invite signup, and email changes. Enable only after SMTP works.
AUTH_RATE_LIMIT_ENABLEDtrueEnable the per-IP brute-force throttle on unauthenticated auth routes.
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS10 / 60000Allowed auth attempts per window.
JWT_ACCESS_TTL / JWT_REFRESH_TTL_DAYS5m / 10Access-token and refresh-session lifetimes.
CLOUDFLARE_TURNSTILE_SITE_KEY / CLOUDFLARE_TURNSTILE_SECRET_KEYUnsetHosted signup protection. Leave unset for normal self-hosting.

Users configure their own authenticator under Profile settings -> Profile. Organisation admins can require it under Profile settings -> Organisation. See Profile and Security.

Public API and MCP limits

VariableDefaultPurpose
PUBLIC_API_RATE_LIMIT_ENABLEDtrueEnables public API and MCP request limits.
PUBLIC_API_IP_RATE_LIMIT_PER_MINUTE60Limit for unauthenticated discovery and invalid bearer formats.
PUBLIC_API_FAILED_KEY_RATE_LIMIT_PER_MINUTE10Per-IP limit for failed kanera_* key attempts.
PUBLIC_API_KEY_RATE_LIMIT_PER_MINUTE400Per-key request limit after successful authentication.
PUBLIC_API_UPLOAD_RATE_LIMIT_PER_MINUTE30Per-key attachment-upload limit.
PUBLIC_API_RATE_LIMIT_WINDOW_MS60000Rate-limit window shared by the public API and MCP.
MCP_BODY_MAX_BYTES1048576Maximum MCP request body.
MCP_REQUEST_TIMEOUT_MS30000Maximum time for an MCP request.
MCP_HEADERS_TIMEOUT_MS / MCP_KEEP_ALIVE_TIMEOUT_MS10000 / 5000MCP HTTP connection timeouts.
KANERA_API_KEYUnsetRequired only by the local stdio MCP bridge, not the HTTP MCP service.

Database, cache, and capacity

Compose supplies DATABASE_URL and REDIS_URL for the bundled PostgreSQL and Valkey services. Set them yourself only when running a process outside that network or using managed services.

VariableCompose defaultPurpose
DATABASE_SSLfalseEnable only when an external database requires SSL.
POSTGRES_BIND_PORT5433Loopback-only host port for bundled PostgreSQL.
API_REPLICAS / PUBLIC_API_REPLICAS / MCP_REPLICAS2 / 1 / 1Service process counts. Keep the worker at exactly one.
PG_POOL_MAX / WORKER_PG_POOL_MAX20 / 5Maximum database connections per app process and for the worker.
PG_IDLE_TIMEOUT_MS / PG_CONNECTION_TIMEOUT_MS30000 / 5000Pool idle and acquisition timeouts.
PG_STATEMENT_TIMEOUT_MS / SLOW_QUERY_LOG_MS30000 / 250Database query timeout and slow-query logging threshold.
NODE_OPTIONSUnsetOptional Node flags, such as a heap limit.
UV_THREADPOOL_SIZE16Native worker threads used by hashing, crypto, and image processing.
REALTIME_WEBSOCKET_COMPRESSION_ENABLEDtrueCompress larger Socket.IO WebSocket messages.
REALTIME_WEBSOCKET_COMPRESSION_THRESHOLD_BYTES1024Minimum realtime frame size to compress.
REALTIME_OUTBOX_POLL_MS500 in ComposeWorker fallback polling interval for realtime and webhook outbox rows.
USER_DISPLAY_CACHE_TTL_MS60000In-process cache lifetime for display-name lookups.

Raise replicas and pools together only after measuring capacity. See Updates and Scaling.

Files and object storage

VariableDefaultPurpose
UPLOADS_DIR/data/uploads in ComposeLocal upload directory. Bundled Compose fixes this path and persists it in kanera_uploads; change the volume mapping rather than .env.
ATTACHMENT_MAX_BYTES104857600Maximum uploaded attachment size in bytes.
S3_REGION / S3_BUCKETUnsetStart deployment-wide S3-compatible storage when supplied with credentials.
S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEYUnsetCredentials for the upload bucket. Both are required for environment-based S3.
S3_ENDPOINTUnsetCustom endpoint for MinIO, R2, or another S3-compatible provider. Setting it enables path-style requests.
S3_PUBLIC_URL_PREFIXUnsetOptional public or CDN prefix for stored objects.

Environment storage takes precedence over organisation storage configured in the app. See Storage and Backups before switching an installation that already has uploads.

Email, notifications, and integrations

VariableDefaultPurpose
SMTP_HOST, SMTP_USER, SMTP_PASSWORD, SMTP_FROM_EMAILUnsetDefault outbound SMTP connection and sender.
SMTP_PORT / SMTP_SECURITY587 / starttlsSMTP port and transport: starttls, tls, or none.
SMTP_FROM_NAMEKaneraSender display name.
SMTP_IDENTITY_DOMAINSender email domainEHLO and Message-ID domain.
INTERNAL_NOTIFICATION_EMAILSUnsetComma-separated recipients for plain-text signup and invite alerts. Requires environment SMTP.
KANERA_ALLOW_PRIVATE_NOTIFICATION_DESTINATIONSfalseAllow personal ntfy, Gotify, and webhook receivers on HTTP or private networks. Reserved and metadata addresses remain blocked.
ALERT_WEBHOOK_URLUnsetSlack-compatible destination for readiness, runtime, and Grafana alerts.
OPS_ALERTS_ENABLED / OPS_ALERT_THROTTLE_MStrue / 300000Enable and deduplicate operational alerts. Nothing is sent without a destination.
SLOW_REQUEST_LOG_MS2500Threshold for a slow-request warning in logs.
GITHUB_APP_ID, GITHUB_APP_SLUG, GITHUB_APP_PRIVATE_KEYUnsetOptional deployment-defined GitHub App for private link previews. Self-hosted admins can instead use the in-app manifest flow.
TRELLO_API_KEYUnsetLets Trello imports authenticate and copy attachments.

See Email and Notifications and Integrations and APIs.

Backups and retention

VariableDefaultPurpose
DB_BACKUPS_ENABLEDfalseEnable scheduled encrypted PostgreSQL backups to S3-compatible storage.
DB_BACKUP_ENCRYPTION_PASSPHRASEUnsetRequired when backups are enabled and required again to restore them.
DB_BACKUP_TIMES_UTC00:15,12:15,16:45Comma-separated daily UTC backup times.
DB_BACKUP_RETENTION_DAYS14Successful backup retention window.
DB_BACKUP_S3_PREFIXbackups/postgresObject prefix for database dumps.
DB_BACKUP_S3_BUCKET, DB_BACKUP_S3_REGION, DB_BACKUP_S3_ENDPOINTUpload-storage valuesOptional separate backup destination.
DB_BACKUP_S3_ACCESS_KEY_ID, DB_BACKUP_S3_SECRET_ACCESS_KEYUpload-storage valuesOptional separate backup credentials.
ACTIVITY_EVENT_RETENTION_DAYS730Activity history retention.
ADMIN_AUDIT_LOG_RETENTION_DAYS1095Management audit-log retention.
NOTIFICATION_READ_RETENTION_DAYS / NOTIFICATION_MAX_RETENTION_DAYS90 / 365Read-notification and absolute notification retention.
AUTH_TOKEN_RETENTION_DAYS30Grace period before expired or consumed auth artifacts are purged.
REALTIME_OUTBOX_RETENTION_DAYS / OUTBOX_STUCK_RETENTION_DAYS30 / 30Processed and permanently stuck outbox retention.

See Storage and Backups for backup requirements and restore planning.

Monitoring

VariableDefaultPurpose
METRICS_ENABLEDtrueRegisters Prometheus metrics endpoints. They return 404 without a valid token.
METRICS_TOKENUnsetBearer token, at least 16 characters, required for scraping.
COMPOSE_PROFILESUnsetInclude monitoring to start Grafana, Prometheus, Loki, Alloy, and exporters; include admin for the management portal.
COMPOSE_PROJECT_NAMEkaneraCompose identity used by Alloy to select this deployment's logs. Check docker compose ls on managed platforms.
GRAFANA_ADMIN_PASSWORDUnsetRequired when the monitoring profile is enabled.
MONITORING_BIND_IP127.0.0.1Host interface for Grafana and Prometheus. Use a private VPN address, never 0.0.0.0 in production.
GRAFANA_BIND_PORT / PROMETHEUS_BIND_PORT3000 / 9090Host ports for the two monitoring UIs.
PROMETHEUS_RETENTION / PROMETHEUS_RETENTION_SIZE30d / 5GBTime and disk ceilings for Prometheus data.
GRAFANA_ROOT_URLUnsetExternal Grafana URL when serving it through a proxy.
POSTGRES_EXPORTER_DSNBundled databaseOverride for an external PostgreSQL server.
REALTIME_EMIT_METRICS_ENABLEDfalseEnable sampled realtime payload metrics.
REALTIME_EMIT_METRICS_SAMPLE_RATE / REALTIME_EMIT_METRICS_MIN_BYTES0.01 / 0Realtime metrics sampling and minimum payload size.

Optional management portal

The management portal is separate from tenant settings and has its own authentication boundary. Enable it only when operators need cross-organisation administration or audited support sessions.

VariableDefaultPurpose
ADMIN_WEB_ORIGINhttp://localhost:4300Public origin and CORS boundary for the admin console.
ADMIN_API_PORT3002Internal admin API listener port when it runs outside the bundled wiring.
ADMIN_COOKIE_DOMAINUnsetCookie-domain override when the admin hostname is outside COOKIE_DOMAIN.
ADMIN_JWT_SECRETUnsetRequired for the admin API and must differ from JWT_SECRET.
ADMIN_EMAIL / ADMIN_PASSWORDUnsetSeed the first superadmin only while the admin-user table is empty. They do not reset an existing account.
ADMIN_JWT_ACCESS_TTL / ADMIN_JWT_REFRESH_TTL_DAYS15m / 7Admin access and refresh lifetimes.
ADMIN_LOGIN_RATE_LIMIT_MAX / ADMIN_LOGIN_RATE_LIMIT_WINDOW_MS5 / 300000Per-IP admin login throttle.
ADMIN_TRUST_PROXYfalseTrust the admin reverse proxy for real client IPs.
SUPPORT_SESSION_TTL_MINUTES60Short-lived support-session lifetime; maximum eight hours and no refresh token.

Keep the management portal private, use a separate hostname and secret, and review its audit log. The full deployment wiring is documented in DEPLOY.md and DOKPLOY_DEPLOY.md in the Kanera repository.

Apply and verify changes

Most changes require recreating the affected services:

docker compose config --quiet
docker compose up -d --build
docker compose ps

Check the relevant service logs after changing authentication, delivery, storage, API, MCP, or admin settings. A syntactically valid .env does not prove that external credentials or URLs work.