Configuration

Configuration

Configure the Tindra server through environment variables. The defaults below are the binary's defaults; the installer, Docker Compose, or managed hosting may supply different values. SDK variables such as SENTRY_ENVIRONMENT belong in the application sending telemetry, not the Tindra server.

Applying changes

For Docker Compose, add runtime variables to the tindra service's environment block and recreate the container with docker compose up -d. A value in Compose's .env file only reaches the container if the service references it or uses env_file.

For a directly run binary, set the process environment or a .env file in its working directory and restart the service. Existing process variables take precedence over .env at startup.

Use the literal strings true and false, quoted in YAML. Most boolean settings enable only for the exact value true; REQUIRE_MFA is enabled unless its value is exactly false. Numeric retention, rate, and row limits accept nonnegative integers; their documented 0 behavior is specific to each setting. Buffer sizes require positive integers and fall back to defaults for invalid or nonpositive values.

The advanced SIGHUP reload path only updates PROJECT_LIMIT, EVENT_LIMIT, and USER_LIMIT after reloading a local .env file. It does not reload SSO, retention, networking, or queue settings, and cannot change an existing container's environment. Recreate the container to apply Compose changes.

Required

Variable Description
DATABASE_URL Required Postgres connection string, e.g. postgres://user:password@host:5432/tindra?sslmode=disable for a private local database connection. Use your database's TLS settings for remote connections.
PUBLIC_URL Set to the externally reachable instance URL, e.g. https://tindra.example.com, for correct links, DSNs, and authenticator labels. It has no binary default.

Server

Variable Default Description
BIND_ADDR :8080 TCP address (host:port) or Unix socket path (unix:/run/tindra/tindra.sock).
SOCKET_MODE 0660 Unix socket permissions in octal. Quote values in Compose, e.g. SOCKET_MODE: "0660". Give the proxy access through matching ownership/group permissions; 0666 permits any local user to connect.
DATA_DIR /data Persistent file storage, including source maps and attachments. Must be writable at startup. The local-development .env.example uses ./data; Docker uses /data with UID/GID 65532.
LOG_LEVEL info Log verbosity: debug, info, warn, or error. Startup information remains visible at higher levels.
LOG_FORMAT Text output json enables JSON logs; unset or other values use text. Production Compose sets json.
COOKIE_SECURE false Set to true when the public URL uses HTTPS, including when TLS terminates at a reverse proxy.
CORS_ORIGIN Unset Allowed CORS origin when the API and UI are served from different origins.

Limits

Project, monthly event, user, log-row, and transaction-row caps are unlimited by default. Age retention and profile storage limits still apply.

Variable Default Description
RETENTION_DAYS 90 General telemetry age retention, including events, transactions, logs, uptime checks, and completed cron check-ins. 0 disables this age cleanup only.
PROJECT_LIMIT 0 Maximum projects per instance; 0 is unlimited.
EVENT_LIMIT 0 Maximum events ingested per month; 0 is unlimited.
USER_LIMIT 0 Maximum user accounts, including new accounts admitted through SSO; 0 is unlimited.
LOG_ROW_LIMIT 0 Instance-wide log row cap, enforced by periodically deleting globally oldest entries. 0 disables the cap.
TX_ROW_LIMIT 0 Instance-wide transaction row cap, enforced by periodically deleting globally oldest transactions and their child spans. 0 disables the cap.

Retention runs immediately at startup, then normally hourly. When a pass exhausts its deletion budget, the next catch-up pass runs after five minutes. Limits are cleanup policies, so stored rows or bytes can temporarily exceed a cap.

Row caps and profile policies run independently of RETENTION_DAYS, including when it is 0. Completed cron check-ins expire by completion time, with receipt time used for legacy records; running check-ins and monitor summaries are preserved. See Upgrades before changing retention on an existing instance.

Ingestion buffers

Variable Default Description
INGEST_BUFFER_SIZE 10000 Capacity of each event, transaction, and log queue, measured in items.
PROFILE_BUFFER_SIZE 500 Profile queue capacity, measured in compressed profile items. Pending profiles also have a fixed 128 MiB byte limit.

These queues live in memory and retry eligible failed database writes within bounded attempts and deadlines. They do not survive a process crash. Events and transactions can be rejected when their queues are full; logs and profiles are best effort and can be dropped. A successful envelope response is not a guarantee that every item has reached storage.

Keep stop_grace_period: 75s in Compose to allow HTTP shutdown and bounded queue draining. Forced termination can lose pending data. Queue size is separate from database row/storage limits.

Profiles

Profiles use their own retention window and compressed-storage budget. See Profiling.

Variable Default Description
PROFILE_RETENTION_DAYS 7 Days to retain profiles. 0 disables profile age cleanup, but the storage budget still applies.
PROFILE_STORAGE_LIMIT_MB 2048 Instance-wide compressed profile storage budget in megabytes. Periodic cleanup removes oldest profiles first when exceeded. 0 disables the budget.

To disable all profile cleanup, both profile limits must be 0. Increasing these limits does not restore previously deleted profiles.

Rate limiting

Variable Default Description
RATE_LIMIT_LOGIN 10 Maximum login attempts per IP per 15 minutes. Password-reset requests use a separate per-IP budget with the same limit. 0 disables these rate limits.
RATE_LIMIT_ENVELOPE 300 Maximum envelope POSTs per authenticated project per minute. The client key determines the project, not the URL identifier. 0 disables.

Networking

Variable Default Description
TRUSTED_PROXIES Unset Comma-separated proxy IPs/CIDRs allowed to supply client-address headers, e.g. 10.0.0.10,10.0.0.11. Trust only actual proxies; leave empty for a directly exposed instance.
WEBHOOK_ALLOW_PRIVATE_IPS false Allow alert webhook, Slack, Discord, Microsoft Teams, and passthrough DSN requests to private/internal destinations.
UPTIME_ALLOW_PRIVATE_IPS false Allow uptime probes to private/internal destinations. Independent of webhook policy.

For a trusted immediate peer, Tindra walks X-Forwarded-For from right to left to the first untrusted address. A malformed supplied chain is not replaced with X-Real-IP; that fallback is considered only when no forwarded chain is supplied. Invalid entries in TRUSTED_PROXIES are skipped with a warning. See Reverse proxy.

Outbound address checks apply when connecting, including resolved addresses. Source-code enrichment always blocks internal destinations regardless of either opt-in. Uptime probes do not follow redirects; configure their expected status codes accordingly.

Security

Variable Default Description
REQUIRE_MFA true Require local MFA enrollment before normal session access, for both password and SSO users. false makes enrollment optional, but enrolled users still verify their authenticator at login.

MFA enforcement restricts session-authenticated API access until enrollment. Project bearer tokens authenticate independently. See Authentication.

Internal

Variable Default Description
STATS_API_KEY Unset Operator bearer credential for GET /api/stats and GET /metrics. Unset disables both endpoints. It is separate from project API tokens.
DISABLE_VERSION_CHECK false Set to true to disable the update check. Otherwise the server contacts https://www.tindra.sh/version-update-check every six hours and displays available updates in Settings > Overview.
BILLING_URL Unset Billing portal link shown in settings and event-limit banners when configured.
SKIP_AUTO_MIGRATE false Advanced: skip startup migrations. You must apply the target binary's migrations before serving traffic. See Upgrades.

/metrics exposes Prometheus ingestion counters and queue gauges using Authorization: Bearer <STATS_API_KEY>. It returns 404 when disabled and 401 for incorrect credentials. Its authentication does not need a database connection, so a database outage does not itself hide queue metrics. Counters reset when the process restarts.

The JSON status endpoint /api/instance/ingestion instead requires a user session with manage_projects; neither an operator metrics key nor a project API token grants that session permission.

Email

Set EMAIL_PROVIDER to enable outbound email for alerts and invitations. Leave it unset to disable email entirely.

Common

Variable Description
EMAIL_PROVIDER One of: smtp, postmark, brevo, ahasend, lettermint, cloudflare
EMAIL_FROM Required when EMAIL_PROVIDER is set; sender address, e.g. alerts@example.com.
EMAIL_FROM_NAME Optional Brevo sender display name; defaults to EMAIL_FROM.

SMTP

Variable Description
SMTP_HOST SMTP server hostname
SMTP_PORT Defaults to 587 (STARTTLS); use 465 for implicit TLS.
SMTP_USERNAME SMTP username
SMTP_PASSWORD SMTP password

Postmark

Variable Description
POSTMARK_API_KEY Server API token from the Postmark dashboard

Brevo

Variable Description
BREVO_API_KEY API key from the Brevo dashboard

AhaSend

Variable Description
AHASEND_API_KEY API key from your AhaSend account

Lettermint

Variable Description
LETTERMINT_API_KEY API key from the Lettermint dashboard

Cloudflare Email Routing

Variable Description
CLOUDFLARE_EMAIL_API_TOKEN Cloudflare API token with Email Routing write permissions
CLOUDFLARE_ACCOUNT_ID Your Cloudflare account ID

OAuth / SSO

All values below are unset by default. Configure the callback base and the complete settings for at least one provider before restarting. See Authentication for admission, verified-email linking, Microsoft setup, MFA, and recovery.

Variable Description
OAUTH_REDIRECT_BASE Public URL used to construct OAuth callbacks.
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET GitHub OAuth app credentials.
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET Google OAuth client credentials.
MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET Microsoft application credentials.
MICROSOFT_TENANT Required concrete Directory tenant UUID for Microsoft; shared tenant aliases are unsupported.
AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET Auth0 domain and application credentials.
ZITADEL_ISSUER_URL, ZITADEL_CLIENT_ID, ZITADEL_CLIENT_SECRET Zitadel issuer and application credentials.
OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET Generic OIDC issuer and client credentials.
OIDC_PROVIDER_NAME Defaults to oidc; determines provider identity, callback path, and login label.

A nonempty callback base, client ID/secret, issuer URL, or Auth0 domain selects SSO-only authentication even if discovery fails. Local password login, password invitation acceptance, and reset redemption stay disabled until SSO configuration is intentionally removed and the server restarted. A provider name or Microsoft tenant alone is not a complete SSO configuration.

Docker Compose example

This is a service fragment; see Self-Hosting for the full stack. Supply a URL-safe database password through Compose's .env file and keep it consistent with the Postgres service.

services:
  tindra:
    stop_grace_period: 75s
    environment:
      DATABASE_URL: "postgres://tindra:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD}@postgres:5432/tindra?sslmode=disable"
      PUBLIC_URL: https://tindra.example.com
      BIND_ADDR: ":8080"
      DATA_DIR: /data
      COOKIE_SECURE: "true"
      RETENTION_DAYS: "90"
      PROFILE_RETENTION_DAYS: "7"
      PROFILE_STORAGE_LIMIT_MB: "2048"
      EMAIL_PROVIDER: smtp
      EMAIL_FROM: alerts@example.com
      SMTP_HOST: mail.example.com
      SMTP_PORT: "587"
      SMTP_USERNAME: alerts@example.com
      SMTP_PASSWORD: "${SMTP_PASSWORD:?Set SMTP_PASSWORD}"

POSTGRES_PASSWORD and PORT are inputs to the production Compose example, not Tindra binary settings. The password is required and has no built-in fallback; PORT defaults to 8080. Production Postgres is not published to the host, and the old POSTGRES_PORT mapping is no longer used. stop_grace_period is a Compose setting, not an environment variable.

Monitor ingestion health

Use Ingestion Monitoring for authenticated Prometheus scrapes, queue and write metrics, and a recovery checklist when accepted data is not appearing. Pending in-memory data is not part of a database backup.