Skip to content

Configuration reference

InfraInbox reads one typed configuration, built up in this order — each later source overrides the same setting from an earlier one:

  1. built-in defaults;
  2. a YAML file (--config <file>, or the file named by INFRAINBOX_CONFIG);
  3. environment variables — a few plain aliases (PUBLIC_URL, DATABASE_URL) first, then every INFRAINBOX_* variable, then the _FILE variant of any secret setting;
  4. command-line flags, such as serve --mode.

Every setting has an INFRAINBOX_ environment variable: its YAML path in upper case with dots turned into underscores, so database.url is INFRAINBOX_DATABASE_URL. A handful use a shorter alias instead (noted below). Secret settings (marked secret in the tables) also accept a _FILE variant that names a file to read the value from — prefer it over the plain variable for anything sensitive, since a plain environment variable is readable from docker inspect, a process listing, and the shell history of whoever set it.

To see the configuration InfraInbox actually loaded — every value, its source, and secrets redacted — run:

Terminal window
docker compose exec infrainbox /infrainbox config check

A YAML file mirrors the same nesting, for example:

auth:
password: enabled
require_mfa: owners
retention:
events: 30d

Durations are Go-style (90s, 15m, 24h) or a whole number of days (30d); 0 means “keep forever” where that’s meaningful.

Setting Default Meaning
INFRAINBOX_MODE self-hosted self-hosted or cloud. There is no reason to set this yourself — it’s what makes the same binary power InfraInbox Cloud, and a few settings below (outbound.allow_cgnat, insecure_http, the master key) are refused or required differently under cloud.
INFRAINBOX_PUBLIC_URL (alias PUBLIC_URL) required The address browsers and phones reach this server at, scheme and host (and port, unless 443). Sign-in, the pairing QR and every generated ingest URL are built from it.
INFRAINBOX_INGEST_URL same as public_url Base URL that generated source configurations (webhook targets, curl snippets) send events to. Only worth setting separately behind some unusual split-DNS setups.
INFRAINBOX_DATA_DIR /var/lib/infrainbox Where the master key and any generated TLS certificate live. Back it up with the database.
INFRAINBOX_LOG_LEVEL info debug, info, warn or error. Event and notification bodies are logged only at debug.
INFRAINBOX_SERVE_MODE all Which components this process runs: all (everything, the only sensible choice for a single self-hosted instance), or api/worker to split them across processes. Also settable as serve --mode.
INFRAINBOX_SERVE_STOP_GRACE 30s How long shutdown has to finish in-flight work before the process exits. Match your container platform’s stop grace period (Compose’s stop_grace_period: 30s already does).
INFRAINBOX_MIGRATIONS_AUTO true Apply pending database migrations automatically when the server starts. Turn this off only if you’d rather run infrainbox migrate up yourself as a separate step — with it off, serve refuses to start while migrations are pending.
Setting Default Meaning
INFRAINBOX_DATABASE_URL (alias DATABASE_URL) required, secret The PostgreSQL connection URL, e.g. postgres://infrainbox:pw@postgres:5432/infrainbox. Prefer INFRAINBOX_DATABASE_URL_FILE.
INFRAINBOX_DATABASE_APP_MAX_CONNS 20 Maximum connections used by the API/ingest side.
INFRAINBOX_DATABASE_WORKER_MAX_CONNS 10 Maximum connections used by delivery workers and the scheduler.
Setting Default Meaning
INFRAINBOX_MASTER_KEY (prefer _FILE) secret generated 32 bytes, base64 (openssl rand -base64 32). Encrypts every stored secret (destination credentials, push keys, and so on). Left unset, one is generated into <data_dir>/master.key on the first start of a fresh database — back it up, apart from the database dump.
INFRAINBOX_MASTER_KEY_PREVIOUS (prefer _FILE) secret Set during a key rotation: the key you’re rotating away from, while master_key holds the new one. See Backups and upgrades.
Setting Default Meaning
INFRAINBOX_HTTP_LISTEN :8443 (:8080 if tls is off) Address of the main listener.
INFRAINBOX_TLS on on: HTTPS, with cert_file/key_file or a generated self-signed certificate. off: plain HTTP behind a TLS-terminating proxy.
INFRAINBOX_TLS_CERT_FILE PEM certificate chain for the main listener.
INFRAINBOX_TLS_KEY_FILE PEM private key matching cert_file. Set both or neither.
INFRAINBOX_TLS_CA_FILE PEM CA certificate of a private CA; its pin is included in the pairing QR code.
INFRAINBOX_INSECURE_HTTP off private: also serve plain HTTP on the HTTPS port, to callers on private-IP ranges only (for LAN phones that can’t validate a private CA). Needs tls: on.
INFRAINBOX_HTTP_TRUSTED_PROXIES none (tls: on) / RFC 1918 + loopback (tls: off) IP addresses or CIDR ranges whose X-Forwarded-* headers are trusted for the client’s real IP and scheme. Set this to your reverse proxy’s own address — never a whole subnet — or every rate-limit bucket collapses into one. See TLS and reverse proxies.
INFRAINBOX_HTTP_TRUSTED_HOSTS (alias TRUSTED_HOSTS) none Extra hostnames (comma-separated, no scheme/port/wildcard) the dashboard and API answer to besides public_url’s. Anything else gets a 421.
INFRAINBOX_HTTP_READ_HEADER_TIMEOUT 10s Longest wait for a request’s headers.
INFRAINBOX_HTTP_READ_TIMEOUT 1m Longest time to read a whole request.
INFRAINBOX_HTTP_WRITE_TIMEOUT 1m Longest time to write a response (the live event stream is exempt).
INFRAINBOX_HTTP_IDLE_TIMEOUT 2m How long an idle keep-alive connection stays open.
INFRAINBOX_HTTP_MAX_HEADER_BYTES 65536 Largest request header block, in bytes.
Setting Default Meaning
INFRAINBOX_METRICS_LISTEN 127.0.0.1:9464 Address of the internal /metrics listener (Prometheus format). Not published by the compose file by default.
INFRAINBOX_METRICS_TOKEN secret Set this to also serve /metrics on the main, public listener, guarded by this bearer token, instead of only the internal one.

Off by default self-hosted. Set otel.endpoint to export traces to a collector you run yourself (Jaeger, Grafana Tempo, and so on) — see Security and privacy for what this does and doesn’t send anywhere.

Setting Default Meaning
INFRAINBOX_OTEL_TRACES false (true if otel.endpoint is set) Export traces over OTLP.
INFRAINBOX_OTEL_ENDPOINT (alias OTEL_EXPORTER_OTLP_ENDPOINT) Your OTLP collector, e.g. https://otel.example.com:4318.
INFRAINBOX_OTEL_HEADERS (alias OTEL_EXPORTER_OTLP_HEADERS) secret Headers sent with every OTLP export, key=value pairs separated by commas — often an API key your collector wants.

How long data is kept before it’s purged. 0 keeps it forever; open incidents are never purged regardless of retention.incidents.

Setting Default Meaning
INFRAINBOX_RETENTION_EVENTS 30d Raw events (the first and last event of a retained incident are always kept).
INFRAINBOX_RETENTION_INCIDENTS 90d Resolved incidents, counted from resolution.
INFRAINBOX_RETENTION_DELIVERIES 30d Delivery attempt records.
INFRAINBOX_RETENTION_RAW_PAYLOADS 7d Raw inbound payloads kept for debugging.
INFRAINBOX_RETENTION_RAW_PAYLOADS_PER_SOURCE 20 Cap on raw payloads kept per source, on top of the age limit above.
INFRAINBOX_RETENTION_HEARTBEAT_PINGS_PER_MONITOR 100 Individual heartbeat pings kept per monitor.
INFRAINBOX_RETENTION_HEARTBEAT_AGGREGATES 90d Daily heartbeat summaries.
INFRAINBOX_RETENTION_IDEMPOTENCY_KEYS 1d How long a duplicate event with the same idempotency key is still recognized (minimum 24h).
INFRAINBOX_RETENTION_AUDIT 365d Audit log entries.
INFRAINBOX_RETENTION_EXPIRED_SESSIONS 30d Expired sessions and pairing tokens, counted from expiry.

How many in-flight sends each worker allows per transport, so one slow provider doesn’t starve the others. (A few more of these keys exist in the configuration loader than are listed here — they belong to destinations this build doesn’t ship yet, so there’s nothing to point them at.)

Setting Default
INFRAINBOX_DELIVERY_CONCURRENCY_TELEGRAM 8
INFRAINBOX_DELIVERY_CONCURRENCY_SLACK 8
INFRAINBOX_DELIVERY_CONCURRENCY_DISCORD 8
INFRAINBOX_DELIVERY_CONCURRENCY_WEBHOOK 16
INFRAINBOX_DELIVERY_CONCURRENCY_PUSH 32
Setting Default Meaning
INFRAINBOX_PUSH_WEBPUSH_VAPID_KEY (prefer _FILE) secret auto The server’s Web Push signing key. auto generates one on first start and stores it encrypted in the database.
INFRAINBOX_PUSH_WEBPUSH_SUBJECT A contact for push services about this server’s traffic: mailto:you@example.com or an https:// URL.
INFRAINBOX_PUSH_RELAY_ENABLED true Advertise InfraInbox’s push relay to pairing devices (see Security and privacy).
INFRAINBOX_PUSH_RELAY_URL https://push.infrainbox.app The relay’s base URL.
INFRAINBOX_PUSH_APNS_ENABLED false Send to Apple Push Notification service directly, with your own key, instead of through the relay — for a self-built iOS client. Needs the three settings below.
INFRAINBOX_PUSH_APNS_KEY (prefer _FILE) secret The APNs authentication key (.p8, PEM).
INFRAINBOX_PUSH_APNS_KEY_ID The key’s 10-character key ID.
INFRAINBOX_PUSH_APNS_TEAM_ID Your Apple developer team ID.

InfraInbox mails account links — password reset, the confirmation of a changed address — through an SMTP relay you name: a mail provider’s SMTP endpoint, or a local MTA. Without smtp.host nothing is mailed: Forgot password? doesn’t appear, an email change is refused, and infrainbox admin reset-password is how a password gets reset. Mail goes out after the page has answered, so a slow relay never slows sign-in, and the server logs only which kind of mail went out, never the address or the link.

Setting Default Meaning
INFRAINBOX_SMTP_HOST The relay’s host name. Setting it turns account mail on.
INFRAINBOX_SMTP_PORT by tls The relay’s port; unset picks 587 for starttls, 465 for tls, 25 for none.
INFRAINBOX_SMTP_USERNAME The relay’s user name; empty sends without logging in.
INFRAINBOX_SMTP_PASSWORD (prefer _FILE) secret The relay’s password.
INFRAINBOX_SMTP_TLS starttls starttls (required, not optional), tls (TLS from the first byte) or none (plain text, for a relay on the same host or network only).
INFRAINBOX_SMTP_FROM The sender, e.g. InfraInbox <no-reply@example.com>. Required with a host.
INFRAINBOX_SMTP_ALERTS_HOST, _PORT, _USERNAME, _PASSWORD, _TLS, _FROM A separate relay and sender for alert mail, so alert volume can never hold up a password reset. Unset, alert mail uses the relay above.

To check the relay, run docker compose exec infrainbox /infrainbox config check, then use Forgot password? on the sign-in page with your own address.

Destinations, webhooks and test sends may always reach public addresses and, self-hosted, private (RFC 1918) ones. Loopback, link-local, multicast and cloud-metadata addresses are never allowed — see Security and privacy.

Setting Default Meaning
INFRAINBOX_OUTBOUND_ALLOW_CGNAT false Also allow carrier-grade NAT addresses (100.64.0.0/10) — needed if a destination lives on a Tailscale tailnet reached that way.
INFRAINBOX_OUTBOUND_ALLOW_ULA false Also allow IPv6 unique local addresses (fc00::/7).
Setting Default Meaning
INFRAINBOX_AUTH_PASSWORD enabled Who may sign in with a password: enabled (everyone), admins_only, or disabled. infrainbox admin reset-password always works regardless, so a broken identity provider never locks you out.
INFRAINBOX_AUTH_REQUIRE_MFA none Who must set up a second factor: none, owners (workspace owners and instance admins), or all.
INFRAINBOX_AUTH_PASSWORD_HASH_PROFILE default Argon2id cost: default (fine down to a Raspberry Pi / 1 GB host) or large (bigger hosts).
INFRAINBOX_AUTH_PASSWORD_HASH_MEMORY_BUDGET_MIB 128 Total memory concurrent password hashing may use; sign-ins beyond it wait briefly, then get rate-limited.
INFRAINBOX_AUTH_ADMIN_EMAIL Seeds the first instance administrator’s email at start, for an unattended install. Only applies while the instance has no user yet.
INFRAINBOX_AUTH_ADMIN_PASSWORD_FILE secret, file only The seeded administrator’s password. There’s deliberately no plain-variable form for this one.

Each entry in auth.providers is an OpenID Connect provider (Authentik, Keycloak, Authelia, Pocket ID and the like) or GitHub that people can sign in through. It’s a list, so it lives in the config file:

auth:
providers:
- id: authentik # part of the callback URL; keep it stable
type: oidc # oidc or github
name: Authentik # the button's label (default: the id; "GitHub" for github)
issuer: https://auth.example.com/application/o/infrainbox/
client_id: infrainbox
client_secret_file: /run/secrets/oidc # optional for oidc (a public client uses PKCE); required for github
auto_create: allowed_domains # off (default), invite, allowed_domains or on
allowed_email_domains: [example.com]
scopes: [groups] # extra scopes; openid, email and profile are always asked for
  • Callback URL. Register https://infrainbox.example.com/v1/auth/oidc/<id>/callback at the provider, built from INFRAINBOX_PUBLIC_URL. For GitHub, that’s the callback of a GitHub OAuth App.

  • Who gets an account. A first sign-in creates an account only if auto_create allows it: off never (an administrator creates or invites the person first), invite for an address with a pending invite, allowed_domains for a verified address in allowed_email_domains, on always. The first administrator is always created with the setup link: until setup is done, no provider creates an account.

  • Matching. An account is found by the provider’s own subject, never by email, so an address changed at the provider can’t take over someone else’s account.

  • Keep ids stable. Changing a provider’s issuer or type under an id that already has accounts stops the server from starting. Add the new provider under a new id instead.

  • Plain HTTP. An http:// issuer passes the server’s checks but logs a warning on every start: the provider’s keys and tokens then travel unencrypted. The dashboard’s sign-in page only sends the browser to an https:// authorization address, so the provider’s own pages must be served over HTTPS.

  • GitHub and sensitive actions. GitHub can’t re-confirm a sensitive action; someone who signs in only with GitHub is asked to add a passkey or TOTP for that.

  • Check it. infrainbox admin idp test <id> fetches the provider’s discovery document and signing keys and says what’s wrong.

  • On the sign-in page. Each provider gets a “Continue with ” button under the password form; with auth.password: disabled the buttons are all there is. An account with TOTP is asked for its code after the provider, as after a password. A refused sign-in comes back with one plain reason — no account and auto_create doesn’t allow one, the address belongs to an account the identity isn’t linked to, the provider couldn’t be reached — and the details are in the audit log only.

  • On the setup page. The first administrator can be your identity at a provider instead of a password: open the setup link, fill in the workspace, and choose “Continue with ”. The setup token is spent when the provider sends you back.

One OpenID Connect provider can also come from the environment, for an install without a config file. Its id is oidc, and it’s on when the issuer is set:

Setting Default Meaning
INFRAINBOX_OIDC_ISSUER The issuer URL, exactly as the provider’s discovery document states it.
INFRAINBOX_OIDC_CLIENT_ID The client ID registered at the provider.
INFRAINBOX_OIDC_CLIENT_SECRET_FILE secret, file only The client secret. Leave it unset for a public client.
INFRAINBOX_OIDC_NAME SSO The button’s label.
INFRAINBOX_OIDC_AUTO_CREATE off As auto_create above.
INFRAINBOX_OIDC_ALLOWED_EMAIL_DOMAINS Comma-separated, as allowed_email_domains above.

Per-workspace quotas. 0 means no limit, which is the self-hosted default for all of them.

Variable Default Meaning
INFRAINBOX_QUOTAS_EVENTS_PER_DAY 0 Events a workspace may ingest per UTC day. Past it, ingest answers HTTP 429 with Retry-After until midnight UTC.
INFRAINBOX_QUOTAS_SOURCES 0 Sources a workspace may have.
INFRAINBOX_QUOTAS_MONITORS 0 Heartbeat monitors a workspace may have.
INFRAINBOX_QUOTAS_DESTINATIONS 0 Destinations, not counting the built-in push one.
INFRAINBOX_QUOTAS_MEMBERS 0 Members of a workspace.
INFRAINBOX_QUOTAS_DELIVERIES_PER_DAY 0 Notifications a workspace may have sent per UTC day, across every destination. Re-notify and fallback sends count. Past it, a notice is recorded skipped with reason quota rather than sent.
INFRAINBOX_QUOTAS_DELIVERIES_PER_DESTINATION_PER_DAY 0 The same, for any one destination on its own.
INFRAINBOX_QUOTAS_NEW_WORKSPACE_DELIVERIES_PER_DAY 0 A lower daily notification total for a workspace’s first seven days. A per-workspace override wins over it.
INFRAINBOX_QUOTAS_WORKSPACES 0 Workspaces one account may own. It does not limit the workspaces somebody is invited into.

Creating one more of something past its limit answers HTTP 409 quota_exceeded. infrainbox admin workspaces limits <workspace> shows one workspace’s limits, and its flags (--events-per-day, --deliveries-per-day, --sources, … and --clear) override the defaults for that workspace alone. Every workspace’s counts against its limits are on its Usage and limits panel.

Per-instance token buckets; a request beyond the limit gets HTTP 429 with Retry-After. Each row is INFRAINBOX_RATELIMIT_<NAME>_PER_MINUTE and ..._BURST.

Bucket Default (per minute / burst) Applies to
INGEST_KEY 600 / 300 One source’s ingest key.
INGEST_WORKSPACE 3000 / 1000 A whole workspace’s ingest traffic.
AUTH_FAILURES 30 / 20 Failed credentials, per client IP.
MANAGEMENT 1200 / 200 The management API, per signed-in user.
PUBLIC 120 / 60 Unauthenticated routes (/v1/info, sign-in pages), per client IP.
DESTINATION_TEST / DESTINATION_TEST_WORKSPACE 6 / 3 and 30 / 10 “Send test” on a destination.
TELEGRAM_DISCOVER 30 / 10 The Telegram chat-discovery poll while setting up that destination.
SOURCE_TEST 6 / 3 “Test” on a source.
HEARTBEAT_MONITOR 60 / 10 Pings to one heartbeat monitor.
AUTH_LOGIN 30 / 15 POST /v1/auth/login, per client IP.
AUTH_TOTP 30 / 15 TOTP code verification.
AUTH_REAUTH 30 / 15 Step-up re-authentication.
AUTH_SETUP 20 / 10 First-run setup.
AUTH_SIGNUP 10 / 10 Cloud sign-up, and opening a link that confirms an address, per client IP.
AUTH_RESET 10 / 10 Asking for a password reset link, and using one, per client IP.
AUTH_MAIL 1 / 3 Account mail to one address or account — reset links, re-sent confirmations — whoever asks.

dev.telegram_api_url, dev.apns_url, dev.fcm_url and dev.relay_url point delivery transports at a local test double, and dev.github_url does the same for GitHub sign-in, instead of the real provider. They exist for InfraInbox’s own CI and are refused outright if mode is cloud. Don’t set these on a real instance — doing so sends provider traffic (including credentials) to whatever URL you named, and the server logs a warning every time it starts with one set.