
# Environment Variables: Storage, AI, Email & Observability

Every service below is off, local, or frugal by default. You opt _out_ of the default posture by setting a variable — you never have to opt in to get a working app. Core app, server, database, and secret variables live on [Environment Variables](/en/docs/env-vars).

## Storage

The backend is operator-controlled so the same schema runs against a local disk in development and object storage in production — see [S3 Storage](/en/docs/integrate-s3-storage) for a worked setup.

| Variable                       | Default              | Description                                                                                                           |
| ------------------------------ | -------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `STORAGE_PROVIDER`             | auto                 | `s3` or `local`. Unset auto-selects: PostgreSQL `bytea` when `DATABASE_URL` is set, local files otherwise.            |
| `STORAGE_LOCAL_DIRECTORY`      | `<data dir>/storage` | Upload directory. Required when `STORAGE_PROVIDER=local`.                                                             |
| `STORAGE_S3_ENDPOINT`          | —                    | S3-compatible endpoint URL. Required for `s3`.                                                                        |
| `STORAGE_S3_BUCKET`            | —                    | Bucket name. Required for `s3`.                                                                                       |
| `STORAGE_S3_REGION`            | `us-east-1`          | Region.                                                                                                               |
| `STORAGE_S3_ACCESS_KEY_ID`     | —                    | Access key. Required for `s3`.                                                                                        |
| `STORAGE_S3_SECRET_ACCESS_KEY` | —                    | Secret key. Required for `s3`.                                                                                        |
| `STORAGE_S3_FORCE_PATH_STYLE`  | `false`              | Set `true` for MinIO and other path-style endpoints.                                                                  |
| `STORAGE_DEFAULT_ACCESS`       | `private`            | `public` serves every stored file without authentication.                                                             |
| `STORAGE_PUBLIC_PATHS`         | —                    | Comma-separated key prefixes served without authentication. Literal prefixes only; wildcards are rejected at startup. |
| `STORAGE_MAX_FILE_SIZE`        | —                    | Per-file upload cap, in bytes.                                                                                        |
| `STORAGE_MAX_TOTAL_SIZE`       | —                    | Total stored-bytes cap, in bytes.                                                                                     |
| `STORAGE_TEMP_CLEANUP_AFTER`   | `86400000` (24 h)    | Age at which automation temp files become eligible for removal, in milliseconds. `0` disables sweeping.               |

:::callout
**The bare `S3_*` names are deprecated.** `S3_ENDPOINT`, `S3_BUCKET`, and the rest are still accepted as aliases and log a one-time warning at startup. Rename them to `STORAGE_S3_*` — the legacy names are removed in the next major version.
:::

## AI

AI is disabled until `AI_PROVIDER` is set. An unrecognised value aborts the boot rather than failing silently later.

| Variable                  | Default          | Description                                                                                                                  |
| ------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `AI_PROVIDER`             | unset (disabled) | `anthropic`, `openai`, `mistral`, `google`, `ollama`, or `openai-compatible`. `gemini` is accepted as an alias for `google`. |
| `AI_API_KEY`              | —                | Provider API key. Required for every provider except `ollama`.                                                               |
| `AI_BASE_URL`             | provider default | Endpoint URL. Required for `ollama` and `openai-compatible`.                                                                 |
| `AI_MODEL`                | per provider     | Model identifier. Defaults to the provider's recommended model.                                                              |
| `AI_TEMPERATURE`          | provider default | Sampling temperature, 0 to 1 inclusive.                                                                                      |
| `AI_MAX_TOKENS`           | provider default | Maximum output tokens.                                                                                                       |
| `AI_EMBEDDING_MODEL`      | —                | Embedding model identifier.                                                                                                  |
| `AI_EMBEDDING_DIMENSIONS` | —                | Embedding vector dimensions.                                                                                                 |

Provider-specific aliases are read when the generic variable is absent: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `MISTRAL_API_KEY`, and `GOOGLE_API_KEY` stand in for `AI_API_KEY`; `OLLAMA_BASE_URL` stands in for `AI_BASE_URL`. The generic name always wins when both are set. See [AI Providers](/en/docs/ai-providers).

## Email (SMTP)

When `SMTP_HOST` is unset, email is disabled and sends are logged rather than delivered — Sovrium never silently falls back to a local mail catcher. See [Email Integration](/en/docs/integrate-email).

| Variable         | Default               | Description                                   |
| ---------------- | --------------------- | --------------------------------------------- |
| `SMTP_HOST`      | unset (disabled)      | SMTP server hostname.                         |
| `SMTP_PORT`      | `587`                 | SMTP server port.                             |
| `SMTP_SECURE`    | `false`               | Implicit TLS. Port 465 enables it regardless. |
| `SMTP_USER`      | —                     | Authentication username.                      |
| `SMTP_PASS`      | —                     | Authentication password.                      |
| `SMTP_FROM`      | `noreply@sovrium.com` | Sender address.                               |
| `SMTP_FROM_NAME` | `Sovrium`             | Sender display name.                          |

## MCP server

Off by default. The operator mounts the route; the schema decides what the tools may touch. See [MCP Integration](/en/docs/mcp-integration).

| Variable                    | Default                            | Description                                                                 |
| --------------------------- | ---------------------------------- | --------------------------------------------------------------------------- |
| `MCP_ENABLED`               | `false`                            | Master switch. The `/mcp` route is only mounted when true.                  |
| `MCP_TRANSPORT`             | `streamable-http`                  | `streamable-http` for remote clients, `stdio` for local IDE use.            |
| `MCP_MOUNT_PATH`            | `/mcp`                             | Route prefix under `streamable-http`.                                       |
| `MCP_AUTH_STRATEGY`         | `oauth2` when `auth` is configured | `token` or `oauth2`. Token mode reads the `MCP_TOKEN_*` variables.          |
| `MCP_TOKEN_ADMIN`           | —                                  | Bearer token granting the admin role. Minimum 32 characters.                |
| `MCP_TOKEN_MEMBER`          | —                                  | Bearer token granting the member role. Minimum 32 characters.               |
| `MCP_TOKEN_VIEWER`          | —                                  | Bearer token granting the viewer role. Minimum 32 characters.               |
| `MCP_RATE_LIMIT_PER_MINUTE` | `60`                               | Requests per token per minute.                                              |
| `MCP_RATE_LIMIT_PER_DAY`    | `5000`                             | Requests per token per day.                                                 |
| `MCP_AUDIT_ENABLED`         | `true`                             | Log every tool call to the audit trail.                                     |
| `MCP_EXPOSE_INTERNALS`      | `true`                             | Expose internal tables read-only to the admin role.                         |
| `MCP_CONFIRM_DESTRUCTIVE`   | `true`                             | Mark delete tools destructive so clients confirm instead of auto-approving. |

## Ecoconception

Frugal defaults you override to opt out. Eco posture is operator config and never appears in the app schema. [Ecoconception](/en/docs/ecoconception) explains what each lever costs and saves.

| Variable                     | Default          | Description                                                                                |
| ---------------------------- | ---------------- | ------------------------------------------------------------------------------------------ |
| `ECO_MODE`                   | `balanced`       | `strict`, `balanced`, or `lenient`. `on` and `auto` map to `balanced`, `off` to `lenient`. |
| `ECO_PAGE_CACHE`             | `on`             | In-memory cache for request-invariant page HTML.                                           |
| `ECO_IMAGE_FORMAT`           | `avif`           | Default transcoding format: `avif`, `webp`, `jpeg`, or `png`.                              |
| `ECO_INDEX_HEADER`           | `on`             | Emit the `X-Eco-Index` response grade (A–G).                                               |
| `ECO_LOW_DATA_DEFAULT`       | `off`            | `on`, `off`, or `respect-client` (honours `Save-Data` and reduced-data client hints).      |
| `ECO_AI_PROVIDER_PRECEDENCE` | `local-first`    | `local-first`, `cloud-first`, or `local-only`. Also accepts an ordered provider list.      |
| `ECO_AI_MAX_CARBON_CLASS`    | `G` (permissive) | Worst carbon class, `A`–`G`, an AI provider may have to be selected.                       |
| `ECO_RETENTION_PURGE_DAYS`   | no purge         | Platform-wide purge horizon for soft-deleted rows. Per-table retention still wins.         |
| `ECO_DESIGN_LAYER`           | `on`             | Emit the design-token override layer. Setting `off` falls back to inline defaults.         |
| `ECO_FORM_ANALYTICS`         | `on`             | Set `off` to stop recording form analytics events.                                         |

## Observability export

Every signal is off unless its gate is set, and a set-but-malformed value aborts the boot rather than degrading quietly. Point these at any Sentry-compatible or OTLP backend.

| Variable                              | Default                        | Description                                                                   |
| ------------------------------------- | ------------------------------ | ----------------------------------------------------------------------------- |
| `SENTRY_DSN`                          | unset (off)                    | Gates error reporting. Format `<scheme>://<key>@<host>/<project_id>`.         |
| `SENTRY_ENVIRONMENT`                  | `NODE_ENV`, else `development` | Environment label attached to events.                                         |
| `SENTRY_TRACES_SAMPLE_RATE`           | unset (off)                    | Performance sampling rate in (0,1]. `0` disables. Needs a DSN.                |
| `OTEL_EXPORTER_OTLP_ENDPOINT`         | unset (off)                    | Base OTLP URL. Logs POST to `<base>/v1/logs`, metrics to `<base>/v1/metrics`. |
| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`    | derived from base              | Full logs URL, used verbatim.                                                 |
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | derived from base              | Full metrics URL, used verbatim.                                              |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`  | unset (off)                    | Arms trace export. The base endpoint alone does not.                          |
| `OTEL_EXPORTER_OTLP_HEADERS`          | —                              | Export headers as `k=v,k2=v2`.                                                |
| `OTEL_SERVICE_NAME`                   | app name                       | `service.name` resource attribute.                                            |
| `OTEL_METRIC_EXPORT_INTERVAL`         | `10000`                        | Metrics poll interval, in milliseconds.                                       |
| `OTEL_TRACES_SAMPLER`                 | `parentbased_traceidratio`     | Sampler name. An unknown name aborts the boot.                                |
| `OTEL_TRACES_SAMPLER_ARG`             | `0.1`                          | Sampling ratio in [0,1] for ratio-based samplers.                             |
| `LOG_LEVEL`                           | `info`                         | `debug`, `info`, `warn`, or `error`. `NODE_ENV=development` implies `debug`.  |

## Static builds

Read by `sovrium build` when generating a static site.

| Variable                      | Default  | Description                                                     |
| ----------------------------- | -------- | --------------------------------------------------------------- |
| `SOVRIUM_OUTPUT_DIR`          | `./dist` | Output directory.                                               |
| `SOVRIUM_BASE_URL`            | —        | Base URL for sitemap entries and canonical links.               |
| `SOVRIUM_BASE_PATH`           | —        | Path prefix for subdirectory deployments.                       |
| `SOVRIUM_DEPLOYMENT`          | —        | `github-pages` or `generic`.                                    |
| `SOVRIUM_LANGUAGES`           | —        | Comma-separated language codes to build.                        |
| `SOVRIUM_DEFAULT_LANGUAGE`    | —        | Default language code.                                          |
| `SOVRIUM_GENERATE_SITEMAP`    | `false`  | Generate `sitemap.xml`.                                         |
| `SOVRIUM_GENERATE_ROBOTS`     | `false`  | Generate `robots.txt`.                                          |
| `SOVRIUM_GENERATE_MANIFEST`   | `false`  | Generate a PWA `manifest.json`.                                 |
| `SOVRIUM_HYDRATION`           | `false`  | Enable client-side hydration.                                   |
| `SOVRIUM_BUNDLE_OPTIMIZATION` | —        | `split` or `none`.                                              |
| `SOVRIUM_PUBLIC_DIR`          | —        | Static-asset directory to copy. `none` disables static serving. |

## Demo instances

Renders a banner marking an instance as a throwaway demo. Off unless explicitly enabled, so a production deployment can never announce itself as disposable by accident.

| Variable                | Description                                                                                 |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| `SOVRIUM_DEMO_NOTICE`   | Master switch. `on`, `true`, `1`, or `yes` enables the notice; anything else leaves it off. |
| `SOVRIUM_DEMO_NAME`     | Template display name shown in the panel title.                                             |
| `SOVRIUM_DEMO_URL`      | Target of the notice's call to action.                                                      |
| `SOVRIUM_DEMO_EMAIL`    | Display-only sign-in email. Never sourced from `AUTH_ADMIN_EMAIL`.                          |
| `SOVRIUM_DEMO_PASSWORD` | Display-only sign-in password. Never sourced from `AUTH_ADMIN_PASSWORD`.                    |

## Next

- [Environment Variables](/en/docs/env-vars) — app, server, database, and secrets.
- [Buckets Overview](/en/docs/buckets-overview) — declaring the buckets these storage variables back.
- [AI Overview](/en/docs/ai-overview) — what an AI provider unlocks in the schema.
- [Ecoconception](/en/docs/ecoconception) — the reasoning behind the `ECO_*` defaults.
