# Configuration fabrica reads a single TOML file, layered over built-in defaults and overridable by the environment. A fully-commented starting point ships as [`fabrica.example.toml`](../fabrica.example.toml); copy it, keep only the keys you change, and validate with `fabrica config check`. ## Resolution order Sources are merged in the following order; a later source overrides an earlier one key-by-key: 1. Built-in defaults (every key has one — a bare config is valid). 2. `/etc/fabrica/fabrica.toml` 3. `$XDG_CONFIG_HOME/fabrica/fabrica.toml` (falls back to `$HOME/.config/fabrica/fabrica.toml`) 4. `--config ` passed on the command line 5. `FABRICA__*` environment variables Missing files are skipped silently, so the same binary serves a first-run machine and a fully-configured one. ### Environment overrides Environment variables are prefixed `FABRICA__` and nest with double underscores; single underscores inside a key are preserved: ``` FABRICA__SERVER__PORT=8080 # -> server.port FABRICA__INSTANCE__DEFAULT_BRANCH=trunk # -> instance.default_branch FABRICA__LOG__LEVEL=debug # -> log.level ``` ### Secret files (`*_file`) Any key ending in `_file` reads its value from that file and takes precedence over its inline sibling. This keeps secrets out of the config file for agenix / systemd-creds / Docker secrets: | Inline key | File key | Contents | | --------------- | ------------------ | ---------------------------- | | `auth.secret` | `auth.secret_file` | HS256 session-signing key | | `mail.password` | `mail.password_file` | SMTP password | A single trailing newline is trimmed from the file. Secrets are never logged, never appear in error messages, and render as `` in `fabrica config show`. ## Validation Validation is strict and fails fast with actionable messages: - **Unknown keys are an error.** A typo (`prot` for `port`, a misplaced section) aborts the load rather than being ignored. - `instance.url` must be a valid URL and must not have a trailing slash. - `instance.default_branch` must not be empty. - `storage.data_dir` and `storage.repo_dir` must exist or be creatable (they may be created on first run). - `mail.backend = "smtp"` requires `mail.host` and `mail.from`. Some conditions are **warnings** — printed to stderr but non-fatal: - `auth.cookie_secure = true` with a non-`https` `instance.url`: browsers will drop the session cookie. Use this only for local development. ## Sections Each section maps one-to-one to a `[table]` in the TOML file. See `fabrica.example.toml` for the default value and a comment on every key. | Section | Purpose | | ------------ | ------------------------------------------------------------- | | `[instance]` | Identity, canonical URL, default branch, anonymous access. | | `[server]` | HTTP bind address/port, proxy trust, body-size and drain limits. | | `[ssh]` | SSH bind address/port, host key path, advertised clone endpoint. | | `[storage]` | Data and repository directories on disk. | | `[database]` | Connection URL (`sqlite:`/`postgres:`) and pool size. | | `[auth]` | Session/token lifetimes, cookie settings, Argon2id cost, signing key. | | `[mail]` | Backend (`smtp`/`stdout`/`none`), sender, SMTP endpoint and encryption. | | `[ui]` | Theme, asset/theme directories, diff/highlight limits. | | `[git]` | `git` binary path and pack-transport limits. | | `[log]` | Level and format (`pretty`/`json`). | ## Commands - `fabrica config check` — validate the effective configuration and exit. Prints `configuration ok` and exits `0` on success; prints the problems and exits `1` otherwise. Warnings are printed but do not change the exit status. - `fabrica config show` — print the effective, merged configuration with secrets redacted. Add `--json` for machine-readable output. Both honour the global `--config ` flag.