Configuration reference
Marolum is configured entirely through environment variables. Secrets — the bootstrap password, backend definitions, database URLs, keys — are read from files whose paths those variables name, never from the variables themselves.
How configuration behaves
- Read once at startup. Changing any setting or file requires a restart. There is no live reload and no configuration API.
- Fail closed. An invalid value, a missing file, or a file that breaks the rules below stops startup with one sanitized log line. Nothing starts in a degraded mode.
- Booleans are exact.
trueorfalse, lowercase.1,yes, andTRUEare refused. - Paths are literal. Absolute, already normalized; no
~, no variables, no trailing slash. - Every replica is identical. On Enterprise PostgreSQL, all replicas start from the same settings and files.
File rules
Every file a setting names must:
- be a regular file reached without following a final symlink, with a non-symlinked parent;
- have a parent directory that is not writable by group or others (mode
0700is the norm); - not be writable by group or others (mode
0600); - be readable by UID 1000, the
nodeuser the container runs as.
Kubernetes Secret volumes and other projected mounts materialize files as symlinks and are rejected. Write files into a task-local volume from an init step instead; every environment guide shows the pattern.
Core
| Variable | Default | Purpose |
|---|---|---|
PORT |
8080 |
Listening port. The container listens on all interfaces; bind or route to it from outside |
MAROLUM_PUBLIC_ORIGIN |
unset | The HTTPS origin browsers use, without a path. Required for OIDC and SAML; harmless otherwise |
MAROLUM_ALLOW_HTTP |
false |
Loopback-only evaluation: uses the unprefixed marolum-session cookie without Secure so a browser on the same machine can sign in over http://127.0.0.1. Never set it on a network-reachable deployment |
Bootstrap administrator
| Variable | Default | Purpose |
|---|---|---|
MAROLUM_LOCAL_ADMIN_PASSWORD_FILE |
unset | File holding the first administrator's password (12–4096 characters). Read only when no account exists. Unset after first sign-in |
MAROLUM_LOCAL_ADMIN_USERNAME |
admin |
Username for that account. A lowercase letter, then up to 63 lowercase letters, digits, ., _, or -. Set before first startup |
MAROLUM_LOCAL_ADMIN_PASSWORD_ROTATE |
false |
One-shot lost-password rotation: re-reads the password file, replaces the named account's credential, revokes its sessions. Remove after one restart |
Backends
| Variable | Default | Purpose |
|---|---|---|
MAROLUM_BACKENDS_FILE |
unset | The validated JSON document listing backends to observe. Unset starts with no backends. Schema, limits, and examples: Connect a backend |
Backend credentials are not Marolum settings. The AWS SDK's default credential chain applies:
| Variable | Used when |
|---|---|
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN |
Static or exported credentials (laptop, Azure, VMware) |
AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN |
Web-identity federation (EKS IRSA, workload federation) |
AWS_PROFILE, with ~/.aws mounted at /home/node/.aws |
A named profile |
| none | ECS task role or EC2 instance profile |
NODE_EXTRA_CA_CERTS=/path/to/ca-bundle.pem adds a private CA for an S3-compatible endpoint or a
corporate proxy certificate. Certificate verification cannot be disabled.
Database
Exactly one database source applies. Setting more than one refuses startup.
| Variable | Default | Applies to | Purpose |
|---|---|---|---|
MAROLUM_SQLITE_PATH |
/data/marolum.db |
SQLite | Database file. Its parent directory must exist, be owned by UID 1000, mode 0700 |
MAROLUM_POSTGRES_URL |
unset | PostgreSQL | Connection URL for a fresh PostgreSQL installation |
MAROLUM_POSTGRES_URL_FILE |
unset | PostgreSQL | Same, read from a file. Preferred |
A SQLite installation adopted to PostgreSQL through the console keeps a UI-managed provider file in the data directory instead; do not also set a PostgreSQL variable. See PostgreSQL operations.
Replicas (Enterprise, PostgreSQL only)
| Variable | Default | Purpose |
|---|---|---|
MAROLUM_REPLICAS_MAX |
1 |
Ceiling the orchestrator may scale to, including rollout surge |
MAROLUM_POSTGRES_POOL_MAX |
1 |
Pooled connections per replica, beyond two dedicated sessions |
MAROLUM_POSTGRES_CONNECTION_HEADROOM |
10 |
Connections left for your own tools, backups, and monitoring |
MAROLUM_MIGRATION_WAIT_SECONDS |
300 |
How long a non-migrating replica waits for the migrating one |
Startup refuses with pool-topology-exceeds-server unless
replicas × (pool + 2) + headroom ≤ max_connections − reserved, and with
multi-replica-requires-postgresql when the ceiling is above 1 on SQLite.
Schema upgrades
| Variable | Default | Purpose |
|---|---|---|
MAROLUM_SCHEMA_UPGRADE_APPLY |
unset | Authorizes exactly the gated migration revision the refusal named. Remove afterwards |
MAROLUM_SCHEMA_UPGRADE_RECOVERY_DIRECTORY |
beside the database | Where the verified pre-migration copy is written (absolute, existing, not world-writable) |
See Gated migrations.
Licensing
An installation with none of these runs as Community.
| Variable | Purpose |
|---|---|
MAROLUM_LICENSING_SERVICE_URL |
Connected licensing endpoint (HTTPS) for Business and Enterprise |
MAROLUM_CONNECTED_LICENSE_DIR |
Protected directory for connected-license state. Required with the URL on SQLite; optional on PostgreSQL, where it seeds the shared licensing row on first start |
MAROLUM_OFFLINE_SITE_LICENSE_FILE |
The signed offline-site license document (Enterprise Advanced Security). No outbound calls |
On SQLite the two connected settings are set together or not at all; a non-HTTPS URL refuses startup. Activation itself happens in Administration → Licensing.
Federated sign-in (Business and Enterprise)
Business allows one OIDC or SAML connection; additional connections and trusted proxy require
Enterprise. Providers are registered in the console; their protocol settings are environment
variables. <KEY> is the issuer key uppercased with dashes changed to underscores (corp-idp →
CORP_IDP). MAROLUM_PUBLIC_ORIGIN is required for OIDC and SAML.
| Variable | Provider | Purpose |
|---|---|---|
MAROLUM_OIDC_<KEY>_CLIENT_ID |
OIDC | Authorization-code client id |
MAROLUM_OIDC_<KEY>_CLIENT_SECRET |
OIDC | Client secret |
MAROLUM_SAML_<KEY>_SSO_URL |
SAML | IdP HTTP-Redirect single sign-on URL |
MAROLUM_SAML_<KEY>_IDP_CERT |
SAML | IdP signing certificate (PEM) |
MAROLUM_SAML_<KEY>_NAMEID_FORMAT |
SAML | Optional; only urn:oasis:names:tc:SAML:2.0:nameid-format:persistent is accepted |
MAROLUM_TRUSTED_PROXY_<KEY>_SUBJECT_HEADER |
Trusted proxy | Header carrying the immutable subject |
MAROLUM_TRUSTED_PROXY_<KEY>_SHARED_SECRET |
Trusted proxy | ≥ 32-character secret the proxy presents in x-marolum-trusted-proxy-secret |
MAROLUM_TRUSTED_PROXY_<KEY>_DISPLAY_HEADER |
Trusted proxy | Optional header carrying a display label only |
Walkthroughs for common providers: Federated identity.
Optional capture and audit
| Variable | Purpose |
|---|---|
MAROLUM_TRANSCRIPT_KEY_FILE |
Canonical base64 of a random 32-byte key, outside /data. Enables transcript body storage. Back it up separately from the database |
MAROLUM_TRANSCRIPT_REDACTION_FILE |
Optional extra redaction rules: {"schemaVersion":1,"literals":[…],"patterns":[…]}, at most 64 KiB |
MAROLUM_TRANSCRIPT_POSTGRES_CAPACITY_FILE |
PostgreSQL only: the measured capacity report the supplied producer writes every five seconds; without a fresh report, capture stays closed |
MAROLUM_STATE_KEY_FILE |
Base64 32-byte key for opt-in whole-state retention. Losing it makes retained copies unrecoverable |
MAROLUM_AUDIT_SINK_ID |
Enterprise external audit sink: a stable lowercase UUID v4 for this receiver binding |
MAROLUM_AUDIT_SINK_URL |
The receiver's HTTPS URL, without user info, query, or fragment |
MAROLUM_AUDIT_SINK_SECRET_FILE |
File holding a dedicated 32–256-character printable ASCII signing secret |
The three audit-sink settings are set together on every replica or not at all. The URL and id are bound in the database on first configured startup and cannot be changed in this version; rotating the secret keeps the binding.
Email notifications
Email notification channels stay inactive until the deployment names an email provider. Channels, recipients, and rules are administered on the console's Notifications page. Adding a recipient emails that address a one-time verification code; notifications go only to verified recipients.
| Variable | Default | Purpose |
|---|---|---|
MAROLUM_EMAIL_PROVIDER |
unset | smtp to deliver through your own SMTP server, or managed for Dekglas-managed email (Business and above with a connected license). Unset keeps email inactive |
MAROLUM_SMTP_HOST |
unset | Required for smtp: your SMTP server's hostname or IPv4 address. ::1 is the only IPv6 address accepted |
MAROLUM_SMTP_FROM |
unset | Required for smtp: the sender address |
MAROLUM_SMTP_SECURITY |
starttls |
starttls (port 587), tls for implicit TLS (port 465), or none (port 25, loopback relay only) |
MAROLUM_SMTP_PORT |
by security mode | Overrides the port the security mode implies |
MAROLUM_SMTP_USERNAME |
unset | SMTP user name. Set it together with the password file or not at all |
MAROLUM_SMTP_PASSWORD_FILE |
unset | Absolute path of a protected regular file of at most 4 KiB holding the SMTP password. There is no inline password variable |
Both TLS modes require TLS 1.2 or later. STARTTLS is required rather than opportunistic: a server
that does not offer it is refused. none is for a relay on the same machine, so the host must be
localhost, 127.0.0.1, or ::1. Keep the password file outside the data directory and out of
images, command arguments, logs, and exports.
Email settings fail closed without stopping startup. An invalid value leaves the provider
unconfigured with the reason invalid-configuration: nothing is sent, the startup log records one
line without the values, and the Notifications page shows the reason. Marolum never applies
part of an email configuration.
Messages are plain text with no attachments. Connections use 10-second connect and greeting
timeouts and a 20-second socket timeout. Set MAROLUM_PUBLIC_ORIGIN to make the console link in
each message absolute; without it, messages name the console path instead.
managed takes no SMTP settings. Dekglas-managed email is not yet available: even an entitled
deployment that selects it reports the provider unavailable and sends nothing. Use your own SMTP
server.
Health and diagnostics endpoints
| Endpoint | Auth | Purpose |
|---|---|---|
GET /api/v1/health |
none | Process liveness |
GET /api/v1/readiness |
none | 200 after a bounded database query; 503 otherwise |
GET /api/v1/storage-health |
storage:health:read |
Write probe, free space, database file sizes, last durable write |
GET /api/v1/observation-polling |
storage:health:read |
Per-scheduler cycle counts, failure classes, backoff |
GET /api/v1/object-store-traffic |
storage:health:read |
S3 request, retry, and throttling counters |
GET /legal/eula |
none | The license text the image carries |
Diagnostic reports are per process and reset on restart. None contains backend identity or provider payloads.
Worked examples
SQLite on a VM (Community)
MAROLUM_LOCAL_ADMIN_PASSWORD_FILE=/run/marolum/admin-password # remove after first sign-in
MAROLUM_BACKENDS_FILE=/run/marolum/backends.json
MAROLUM_PUBLIC_ORIGIN=https://marolum.example.com
Credentials come from the instance profile; the database is at the default /data/marolum.db.
PostgreSQL, one replica (Business)
MAROLUM_BACKENDS_FILE=/run/marolum/backends.json
MAROLUM_POSTGRES_URL_FILE=/run/marolum/postgres-url
MAROLUM_PUBLIC_ORIGIN=https://marolum.example.com
MAROLUM_LICENSING_SERVICE_URL=https://licensing.dekglas.com
PostgreSQL, three replicas (Enterprise)
MAROLUM_BACKENDS_FILE=/run/marolum/backends.json
MAROLUM_POSTGRES_URL_FILE=/run/marolum/postgres-url
MAROLUM_PUBLIC_ORIGIN=https://marolum.example.com
MAROLUM_LICENSING_SERVICE_URL=https://licensing.dekglas.com
MAROLUM_REPLICAS_MAX=3
MAROLUM_POSTGRES_POOL_MAX=2
MAROLUM_POSTGRES_CONNECTION_HEADROOM=10
MAROLUM_OIDC_CORP_IDP_CLIENT_ID=…
MAROLUM_OIDC_CORP_IDP_CLIENT_SECRET=…
Requires 3 × (2 + 2) + 10 = 22 non-reserved PostgreSQL connections.
Loopback evaluation on a laptop
MAROLUM_LOCAL_ADMIN_PASSWORD_FILE=/run/marolum/admin-password
MAROLUM_BACKENDS_FILE=/run/marolum/backends.json
MAROLUM_ALLOW_HTTP=true
AWS_ACCESS_KEY_ID=…
AWS_SECRET_ACCESS_KEY=…
AWS_SESSION_TOKEN=…
This is the Quickstart shape and nothing else.
Earlier environment names
Earlier builds used LUMAFT_* environment variables. Configure the documented MAROLUM_*
names before upgrading; do not rely on the temporary compatibility adapter. Keep the existing
SQLite file's exact path in MAROLUM_SQLITE_PATH (including /data/dekglas.db if that is your
installation's file). A product rename is not a database migration.