# Configuration (https://docs.vitrinka.ai/operator/configuration)



## How configuration works [#how]

The server reads deployment defaults from environment variables at startup; a change needs a restart. Some settings can be overridden after startup: saved SMTP configuration applies to the next email, and workspace AI settings take precedence over the deployment backend. Validation varies by setting; use the values in the reference and check startup logs after changes.

The [configuration reference](/reference/env) lists registered variables, defaults and meanings. This page covers the main deployment choices.

## Core [#core]

| Variable                        | Default                      | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VITRINKA_ADDR`                 | `:8080`                      | Listen address.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `BASE_URL`                      | `http://127.0.0.1:8080`      | The public URL; must be https for cookies to carry `Secure` and for HSTS to ship.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `DATA_DIR`                      | `./data`                     | The control database, every workspace database, filesystem blobs and the blob cache.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `VITRINKA_MASTER_KEY`           | —                            | **Required** with `VITRINKA_KEYS_PROVIDER=env`. 64 hex chars; seals application secrets and doubles as the deployment key when `VITRINKA_KEK` is unset. Under `openbao`, set it for one boot so it is adopted into the key store, then remove it.                                                                                                                                                                                                                                                                                                                                 |
| `VITRINKA_KEK`                  | falls back to the master key | 64 hex chars; the key every workspace data key is wrapped under — [Encryption](/security/encryption#envelope).                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `VITRINKA_SEAL_STRICT`          | `off`                        | `on` refuses legacy plaintext rows and objects instead of reading them through — flip after `seal-existing -verify` passes.                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `MAX_SET_MB`                    | `200`                        | Request body limit and unpacked-size limit per set.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `VITRINKA_SESSION_TTL`          | `720h`                       | Absolute session lifetime, enforced server-side. The enterprise bundle's compose sets `12h`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `VITRINKA_SESSION_IDLE`         | `0`                          | Idle timeout; `0` disables it, anything set must be at least `5m` and shorter than the lifetime. The enterprise bundle's compose sets `30m`.                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `VITRINKA_WAITLIST`             | unset                        | `1` holds every new account until it is approved in `/admin`; a pending invitation counts as approval, and existing accounts always sign in — [the first admin](/operator/install#admin).                                                                                                                                                                                                                                                                                                                                                                                         |
| `VITRINKA_OPS_ORG`              | unset                        | Slug of the organization that runs the install. Its admins — and platform admins, always — manage the deployment-wide settings: the mailer, SSO email-domain claims, turning forced SSO on while claims are on, deployment-managed SSO connections, and the trackers, AI backends and AI endpoints that may reach your internal network ([Outbound targets](/operator/connectors#outbound)). Unset means platform admins alone. It grants no data access — [the first admin](/operator/install#admin).                                                                            |
| `VITRINKA_SSO_DOMAINS`          | `off`                        | `on` lets organizations claim email domains for home-realm routing and per-domain forced SSO — [SSO](/operator/sso#domains).                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `VITRINKA_SSO_PRIVATE_NETWORKS` | unset                        | Comma-separated CIDRs an SSO connection may reach besides public addresses, for an identity provider on your own network; only a deployment-managed connection reaches them — [SSO](/operator/sso#private).                                                                                                                                                                                                                                                                                                                                                                       |
| `VITRINKA_SSO_CA`               | unset                        | A private CA for your identity provider's certificate, as a PEM file path or the PEM text, trusted beside the system roots by the SSO client alone — [SSO](/operator/sso#private).                                                                                                                                                                                                                                                                                                                                                                                                |
| `VITRINKA_BREAK_GLASS`          | `owners`                     | Who may take the forced-SSO emergency door `?local=1`: `off`, `owners` (of the forcing organization) or `all` — [SSO](/operator/sso#breakglass).                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `VITRINKA_TRUSTED_PROXIES`      | unset                        | Comma-separated CIDRs of your reverse proxy, whose `X-Real-Ip` the rate limiter and every audit row trust for the client address (a bare address needs its `/32`); loopback is always trusted, and from any other peer the header is ignored and the connection's own address is used — [Installing](/operator/install#proxy).                                                                                                                                                                                                                                                    |
| `AIR_GAP`                       | unset                        | `1` blanks every integration that reaches the public internet, turns link-card previews off and confines the admin-configured targets that are left — issue trackers, a workspace AI backend, an organization's AI endpoint — to internal addresses, and only those deployment authority saved; SSO reaches only the internal ranges `VITRINKA_SSO_PRIVATE_NETWORKS` lists, and MCP clients register without a client-ID metadata document; S3, SMTP, the capture and transcription sidecars and the metrics listener stay reachable — [Air-gapped deployment](/security/airgap). |
| `LICENSE_FILE`                  | `DATA_DIR/license.json`      | Where the server looks for the vendor-signed licence. The enterprise bundle's compose sets `/run/license/license.json`. No file means the unrestricted evaluation posture; a file that is present but unusable refuses the boot — [Licensing](/security/licensing).                                                                                                                                                                                                                                                                                                               |

## Blob storage [#blobs]

| Variable                                  | Default  | Notes                                                                                                                               |
| ----------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `BLOB_BACKEND`                            | `fs`     | `fs` or `s3`.                                                                                                                       |
| `S3_ENDPOINT` `S3_REGION` `S3_BUCKET`     | —        | Required if `BLOB_BACKEND=s3`. The bucket is created if missing and validated at startup.                                           |
| `S3_ACCESS_KEY_ID` `S3_SECRET_ACCESS_KEY` | —        | Credentials for that bucket.                                                                                                        |
| `VITRINKA_S3_SSE`                         | `aes256` | Server-side encryption requested from the bucket: `aes256`, `kms:<key id>` or `off`. Objects are client-side ciphertext either way. |
| `BLOB_CACHE_MAX_GB`                       | `20`     | S3 only: a read-through cache under `DATA_DIR/blobcache`, pre-warmed at boot, oldest-first eviction. `0` disables it.               |
| `CLAMD_ADDR`                              | unset    | A clamd address turns on fail-closed malware scanning of every blob write — [Storage](/security/storage#malware).                   |

## Key store and audit export [#keys]

Both are off by default and make no outbound call until you turn them on — the full contract, the boot check, the migration and the failure behaviour are in [Encryption and keys](/security/encryption#keystore).

| Variable                                                                                                                                                                                                                        | Default                    | Notes                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VITRINKA_KEYS_PROVIDER`                                                                                                                                                                                                        | `env`                      | `env` keeps the KEK in the environment; `openbao` holds it in an OpenBao transit key the server only ever talks to.                                                                                                              |
| `VITRINKA_OPENBAO_ADDR` `VITRINKA_OPENBAO_MOUNT` `VITRINKA_OPENBAO_KEY` `VITRINKA_OPENBAO_ROLE_ID` `VITRINKA_OPENBAO_SECRET_ID` `VITRINKA_OPENBAO_CA`                                                                           | `transit` · `vitrinka-kek` | The transit engine: address, mount, key name, AppRole credential and a private CA (a PEM file path or the PEM text itself, starting with `-----BEGIN`). `VITRINKA_OPENBAO_TOKEN` is the development-only alternative to AppRole. |
| `VITRINKA_DEK_REVERIFY`                                                                                                                                                                                                         | `15m`                      | How often every open workspace's data key is re-verified against the key store; a revoked key stops serving within this window.                                                                                                  |
| `VITRINKA_AUDIT_EXPORT`                                                                                                                                                                                                         | `off`                      | `dir` or `s3` exports the audit trail every `VITRINKA_AUDIT_EXPORT_EVERY` (`5m`) as a hash-chained, signed JSONL stream — [Audit export](/security/encryption#audit-export).                                                     |
| `VITRINKA_AUDIT_EXPORT_DIR`                                                                                                                                                                                                     | `DATA_DIR/audit-worm`      | The write-once directory for `dir` — the air-gapped choice.                                                                                                                                                                      |
| `VITRINKA_AUDIT_EXPORT_S3_ENDPOINT` `VITRINKA_AUDIT_EXPORT_S3_REGION` `VITRINKA_AUDIT_EXPORT_S3_BUCKET` `VITRINKA_AUDIT_EXPORT_S3_PREFIX` `VITRINKA_AUDIT_EXPORT_S3_ACCESS_KEY_ID` `VITRINKA_AUDIT_EXPORT_S3_SECRET_ACCESS_KEY` | —                          | The object-lock bucket for `s3` and a put-only credential.                                                                                                                                                                       |
| `VITRINKA_AUDIT_EXPORT_RETAIN_DAYS`                                                                                                                                                                                             | unset                      | `s3` only: Object Lock retention stamped on each batch; unset keeps every batch. Ignored by `dir`.                                                                                                                               |

## Retention, headers and the share host [#posture]

| Variable                          | Default       | Notes                                                                                                                                                  |
| --------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `VITRINKA_RETENTION_GRACE`        | `720h`        | How long a deleted session stays recoverable before the sweeper purges it.                                                                             |
| `VITRINKA_RETENTION_SWEEP`        | `1h`          | How often the sweeper runs; never under `1m`.                                                                                                          |
| `VITRINKA_CSP`                    | `report-only` | `enforce` promotes the full content security policy from reporting to enforcement — [Headers and CSP](/security/headers#csp).                          |
| `VITRINKA_FRAME_ANCESTORS`        | unset         | Origins allowed to embed workspace pages; empty means `'self'`.                                                                                        |
| `VITRINKA_SHARE_ORIGIN`           | unset         | A dedicated host for share links that never accepts sessions or tokens.                                                                                |
| `VITRINKA_RECORDER_FULL_FIDELITY` | `deny`        | `allow` lets a workspace's recorder policy switch redaction off entirely — a self-host escape hatch — [Full fidelity](/security/redaction#fidelity).   |
| `VITRINKA_REFERENCE_ORIGINS`      | unset         | Space-separated exact HTTPS origins that may read private reference collections with the browser session; applies only to `/api/v1/reference-library`. |

## Plans and metering [#metering]

| Variable                                                                                               | Default | Notes                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VITRINKA_METERED`                                                                                     | unset   | `1` enforces each organization's plan — storage, seats, boards per workspace — as set in `/admin`; a new organization starts on Free. Unset, and without Stripe billing, every organization runs on Enterprise limits: 500 GiB of pooled storage, unlimited seats and 250,000 active boards per workspace. The stored plan is kept and applies again once metering is on. Any other value refuses the boot. |
| `STRIPE_API_KEY` `STRIPE_WEBHOOK_SECRET` `STRIPE_PRICE_STARTER` `STRIPE_PRICE_PRO` `STRIPE_PRICE_TEAM` | —       | All five set ⇒ billing active, and plans are metered too. A partial set, or a placeholder value, refuses the boot. All unset ⇒ billing routes are unmounted. `STRIPE_PACKS` optionally lists prepaid AI packs.                                                                                                                                                                                              |

`AIR_GAP=1` blanks Stripe, so an air-gapped install meters plans only with `VITRINKA_METERED=1`. The boot log says which applies: `metering on: VITRINKA_METERED`, `metering on: Stripe configured` or `metering off: self-hosted`.

## Observability [#observability]

Every signal but the process log is off until you point it somewhere, and nothing leaves the host on its own.

| Variable                      | Default     | Notes                                                                                                                                                                                                                                                                                 |
| ----------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VITRINKA_LOG_FORMAT`         | `text`      | The process log on stderr; the enterprise bundle's compose sets `json` for a log shipper. Either way only opaque ids reach it — never an email, name, IP, user agent, query string, header or payload.                                                                                |
| `VITRINKA_LOG_LEVEL`          | `info`      | `debug`, `info`, `warn` or `error`.                                                                                                                                                                                                                                                   |
| `VITRINKA_METRICS_ADDR`       | unset (off) | A second, metrics-only listener serving Prometheus `/metrics` (e.g. `:9464`). It sits outside the licence gate and the session layer, so keep it on your private network and never publish it through the proxy — the bundle's compose maps no port for it.                           |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | unset (off) | OTLP/HTTP endpoint that receives traces (e.g. `http://otel-collector:4318`).                                                                                                                                                                                                          |
| `VITRINKA_TRACE_SAMPLE`       | `0.1`       | Head sampling ratio from `0` to `1`, decided per request before anything is known about it. A collector's tail policy chooses only among the exported share, so keeping every slow or failed trace needs `1`.                                                                         |
| `SENTRY_DSN`                  | unset (off) | Error reports from the server and, through the same-origin `/api/v1/telemetry` tunnel, from the browser — browsers never talk to Sentry themselves. Headers, cookies, bodies and IPs are scrubbed before anything is sent, and the user is an opaque id. Point it at your own Sentry. |

`AIR_GAP=1` blanks `SENTRY_DSN` and `OTEL_EXPORTER_OTLP_ENDPOINT` at boot. The metrics listener stays, because it only answers scrapes on your own network.

## Integrations [#integrations]

Configure only the integrations you need. Some also require workspace or project settings — see [Connectors](/operator/connectors).

| Variable                                                                                                                             | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AI_BACKEND_URL` `AI_BACKEND_TOKEN`                                                                                                  | The AI backend behind the run view and chat; the token is sent upstream as a bearer. Legacy spellings `EVE_API_URL` / `EVE_API_TOKEN` still work.                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `EVE_URL` `EVE_SECRET`                                                                                                               | The AI channel for board mentions and review passes, over HMAC-signed pushes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `GITHUB_APP_ID` `GITHUB_APP_PRIVATE_KEY` `GITHUB_APP_SLUG` `GITHUB_APP_CLIENT_ID` `GITHUB_APP_CLIENT_SECRET` `GITHUB_WEBHOOK_SECRET` | The GitHub App: commit pills, per-workspace repository connect, pull-request webhooks, sign in with GitHub (`GITHUB_LOGIN=1`).                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `PLANE_API_URL` `PLANE_API_TOKEN` `PLANE_WORKSPACE`                                                                                  | All three set ⇒ Plane integration active: one upserted comment per set on the referenced issue.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `VITRINKA_CAPTURE_URL` `VITRINKA_CAPTURE_TOKEN`                                                                                      | A browserless/chrome screenshot sidecar you run (e.g. `http://capture:3000`) for link-card previews, press renders, document PDF export, diagram PNG export and the stills of web-recorder sessions (replayed from the recorded DOM stream, with no network access). Unset, link cards fall back to `og:image` metadata, and a web-recorder session's board fails to build until it is set. A link preview hands it only a page on a host vetted as public, and discards a shot whose page loaded a response from a non-public address — [what leaves the host](/security/airgap#egress). |
| `VITRINKA_STT_URL`                                                                                                                   | The whisper.cpp sidecar the bundle's `stt` profile runs (`http://vitrinka-stt:8080`) for server-side meeting transcription — [Connectors](/operator/connectors#stt).                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `VITRINKA_LISTENER_TTL`                                                                                                              | Default `90`. Seconds a listener lease survives between heartbeats before its in-flight work reverts.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

## Mail [#mail]

One mailer per install, set in **Settings → Organization → Email**, from the CLI (`vitrinka admin smtp`) or from the environment: as SMTP (`SMTP_HOST`, `SMTP_PORT`, `SMTP_TLS`, `SMTP_USER`, `SMTP_PASSWORD`, `SMTP_CA_FILE`, `EMAIL_FROM` — authentication over cleartext is refused at boot) or as `RESEND_API_KEY`. A saved configuration wins over the environment, and only deployment authority saves one — [Mail and notifications](/operator/mail). Web push needs `VAPID_PUBLIC_KEY` and `VAPID_PRIVATE_KEY`; set `VAPID_SUBSCRIBER` to your own `mailto:`, because the default is a placeholder.

```bash
vitrinka admin smtp --help
```
