Skip to main content

Config file

fabro server start reads ~/.fabro/settings.toml by default. This is the same file schema used by the CLI. On a same-machine setup, the CLI and server share one settings.toml. On a remote deployment, the server machine has its own settings.toml, and the client machine keeps a separate local settings.toml for CLI-only values such as [cli.target].
Fabro only reads settings.toml. Older server.toml, user.toml, and cli.toml filenames are no longer part of the supported config surface.

Which sections are server-owned

The CLI-only [cli.*] sections (including [cli.target]) belong in the client machine’s settings.toml. They tell CLI commands how to reach a server. The server process does not read [cli.*] for its own binding or routing. Fabro does not terminate inbound TLS directly. Bind [server.listen] to a Unix socket or plain TCP port, and terminate HTTPS or mTLS at a reverse proxy, load balancer, Tailscale Service, or platform ingress in front of Fabro. Use [server.api].url and [server.web].url for those external HTTPS URLs.

Full reference

settings.toml

CLI overrides

Several settings.toml settings can be overridden via fabro server start flags: CLI flags take precedence over settings.toml values. See Run Configuration — Precedence for the full resolution order.

[server.web] section

Control the embedded SPA and browser-oriented routes. When enabled = false, the server still exposes the machine API and /health, but /, /auth/*, SPA client routes, /api/v1/auth/me, and /api/v1/setup/* all return 404. server.web.url is not a secondary web host. Fabro supports a single public origin for API and web traffic. In local development that can be plain HTTP such as http://localhost:3000 or http://127.0.0.1:3000. In production, operators are responsible for terminating HTTPS upstream. When the external origin is assigned at deployment time, set FABRO_WEB_URL in the server process environment. It overrides server.web.url for the canonical browser/API origin and is the recommended control for Tailscale Services deployments.

[server.auth] section

Configure how users authenticate with the server. When "dev-token" is enabled, the API accepts Authorization: Bearer fabro_dev_... and the login page can authenticate with the dev token directly. When "github" is enabled, browser users can sign in with GitHub OAuth and receive a session cookie.

[server.auth.github] section

GitHub-specific auth policy. The GitHub OAuth client ID still lives under [server.integrations.github].client_id.

[server.sandbox.providers] section

Controls which sandbox providers the server may launch. Missing provider entries default to enabled = true for backward compatibility. Disabling a provider rejects new runs whose effective provider is disabled; dry-run Docker/Daytona runs use the local provider and are governed by server.sandbox.providers.local.enabled.
settings.toml

[server.slatedb] section

Configure the embedded SlateDB key-value store used for run event storage. When disk_cache = true, Fabro creates a cache directory at <storage_root>/cache/slatedb and configures SlateDB to cache object store bytes on local disk (16 GB max, 4 MB parts). This significantly reduces read latency and costs for S3-backed deployments. A warning is emitted if enabled with provider = "local" since the disk cache adds overhead when the object store is already local.
settings.toml
The browser install wizard’s Object store step manages both [server.slatedb] and [server.artifacts] together. Local disk uses the detected local object-store root, defaulting to <storage_root>/objects, with fixed prefixes slatedb and artifacts. AWS S3 writes one shared bucket with the same fixed prefixes.
Local disk object store
The wizard only covers AWS S3 bucket/region plus one of:
  • runtime credentials already supplied by the deployment environment
  • manually-entered AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
Advanced S3-compatible settings such as custom endpoint or path_style remain a manual configuration path. If you need MinIO, R2, or another S3-compatible backend, configure [server.slatedb] and [server.artifacts] directly in settings.toml. The runtime still honors those hand-edited values even though the browser wizard does not manage them.

SQLite state and migration backups

Shared relational state, including vault entries and server-managed definitions, lives at <storage_root>/db/fabro.sqlite3. Run events continue to use the [server.slatedb] object store. Before applying pending SQLite migrations, Fabro creates <storage_root>/db/fabro.sqlite3.pre-migration.bak with SQLite’s VACUUM INTO. Each migration run replaces the previous snapshot, so only the most recent pre-migration backup is retained. On the first compatible startup after upgrading from the file-backed vault, Fabro imports <storage_root>/vaults/default/secrets.json into SQLite. Existing SQLite rows win on name conflicts. After a successful import, the source file is renamed to secrets.json.imported-<timestamp>.bak. This temporary compatibility importer is scheduled for removal after 2026-10-11. Vault values and their migration backups retain Fabro’s plaintext-at-rest behavior. Protect the storage volume and backup file with the same access controls as the secrets they contain.

Run defaults

The [run.*] sections in settings.toml act as defaults for every run. On a same-machine setup, settings.toml is the shared machine-default layer under workflow.toml and .fabro/project.toml. On a remote setup, the client bundles workflow, project, and user config into the run manifest. The server then layers those bundled client configs over its own local defaults for run-shaped fields. Server-owned values like [server.storage], [server.api], [server.web], and [server.scheduler] always come from the server machine’s own settings.toml or fabro server start flags. Merge rules follow the normative matrix: TOML [run.inputs] tables replace wholesale, CLI -I / --input values replayed from run manifests merge per key at highest precedence, environment env and labels merge by key, [run.prepare.steps] replaces whole-list, and [[run.hooks]] merge by optional id. Most other fields use “higher-precedence wins” field-wise merging.

[server.logging] section

Configure the server log level and destination. Level precedence: FABRO_LOG env var > --debug flag > [server.logging].level > "info". Destination precedence: FABRO_LOG_DESTINATION env var > [server.logging].destination > command-mode default. stdout is incompatible with daemon mode — use fabro server start --foreground (which is what container images do). Default install-generated settings.toml omits destination so foreground mode streams logs to stdout without extra config. The CLI has its own [cli.logging] section.

[run.git.author] section

Customize the git author identity used for checkpoint commits. When not set, defaults to fabro / fabro@local.

[server.integrations.github] section

Configure GitHub integration auth. strategy = "token" is the default and uses a stored GITHUB_TOKEN from the vault. strategy = "app" enables the GitHub App flow and browser OAuth; webhook delivery is configured separately under [server.integrations.github.webhooks].
settings.toml
For GitHub App mode, set strategy = "app" and include app_id, client_id, and slug. Webhook delivery is configured under [server.integrations.github.webhooks]:
settings.toml
Fabro always serves the GitHub webhook handler at POST /api/v1/webhooks/github when GITHUB_APP_WEBHOOK_SECRET is configured. The strategy field controls how Fabro exposes that route and whether it mutates the GitHub App webhook URL on startup:
  • strategy = "server_url": recommended for production or any deployment with a stable public API URL. Fabro sets the GitHub App webhook URL to <server.api.url>/api/v1/webhooks/github on startup. Requires server.api.url and GITHUB_APP_WEBHOOK_SECRET.
  • strategy = "tailscale_funnel": opt-in for Tailscale-hosted machines without a stable public URL. Fabro runs tailscale funnel <server-port>, exposes the main server on that Funnel URL, and best-effort updates the GitHub App webhook URL to <funnel-url>/api/v1/webhooks/github. Requires a TCP listener and GITHUB_APP_WEBHOOK_SECRET.
  • strategy unset: Fabro still accepts signed webhook deliveries on /api/v1/webhooks/github when the secret is present, but it does not run tailscale funnel and does not update the GitHub App webhook URL.
Tailscale Services and Tailscale Funnel are different ingress features. Services are private to the tailnet and work well for Fabro’s web UI and CLI API access, but github.com cannot deliver webhooks to a private Service URL. Use tailscale_funnel, server_url, or another public relay when GitHub webhook delivery is required. Incoming webhooks are authenticated only by GitHub’s X-Hub-Signature-256 HMAC signature, not by Fabro’s bearer/session auth.

[run.checkpoint] section

Configure checkpoint behavior for all runs. exclude_globs replaces across layers — the highest-precedence layer wins wholesale. skip_git_hooks and commit_timeout use normal override semantics. See Run Configuration — Checkpoint for per-run configuration.

Secrets and environment variables

Fabro splits server-runtime secrets into two scopes:
  • Bootstrap secrets live in process env or <data_dir>/server.env and resolve with precedence process env -> server.env.
  • Optional integration secrets live in the server vault in the shared SQLite database. Anything stored in the vault may be used by workflows.
server.env is only for bootstrap/runtime values the server may need before optional integrations are loaded:
  • SESSION_SECRET when the web UI is enabled
  • FABRO_DEV_TOKEN when "dev-token" auth is enabled
  • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN when a manual config uses static S3 object-store credentials
server.env is not used for Slack, Daytona, Brave Search, LLM provider keys, GITHUB_TOKEN, or GitHub App private key/client secret/webhook secret. Configure those optional integrations with fabro secret set, fabro provider login, or fabro install. During startup, Fabro temporarily migrates recognized legacy optional integration secrets from process env or server.env into the vault. When a matching server.env entry can be safely removed, Fabro writes a hidden backup beside server.env first. Process env values cannot be cleaned up automatically, so remove those from your deployment environment after the vault contains the secret. Fabro no longer auto-loads .env files. Provider API keys are required for the models you want to use; everything else is optional.

LLM provider keys

Server-backed workflows resolve built-in provider credentials from exact-name vault tokens or OAuth entries. Add them with fabro provider login or fabro secret set:
fabro exec and direct library usage can opt into env-backed credential sources explicitly. Runs cannot: the Fabro server reads provider keys from the vault after the temporary startup migration, and workers start from a cleared environment that does not inherit provider keys.

Sandbox and tools

These optional server integrations are vault-only:

Server authentication

Fabro resolves these from process env -> server.env.

Object store runtime secrets (optional)

Fabro resolves these from process env -> server.env. The browser install wizard can write these into server.env for the AWS S3 manual-credential path. It does not support manual STS/session-token input; use runtime credentials instead for ECS, EC2 instance profiles, IRSA, or web-identity flows. For the narrowest production policy, scope access to one bucket and the slatedb/ and artifacts/ prefixes with s3:ListBucket plus s3:GetObject, s3:PutObject, and s3:DeleteObject. Prefer a dedicated IAM user or role for Fabro instead of reusing broad AWS credentials. If POST /install/finish fails after mutating server.env, the error response may include leftover_env_keys or removed_env_keys. For AWS object-store keys, treat removed_env_keys as informational: the prior managed key path was already cleared, so complete the retry before restart. If leftover_env_keys includes AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY, retry the install or remove the managed object-store lines from server.env before abandoning the host. Rotation is not required solely because finish failed after an atomic 0600 rewrite, but it remains the fallback if you no longer trust the host boundary.

GitHub integration (optional)

GitHub token mode is vault-only:

GitHub App extras (optional)

GitHub App mode stores these secrets in the vault. fabro install writes them automatically when it registers an app; do not put them in server.env.

Slack integration (optional)

Slack credentials are server-level secrets. Add [server.integrations.slack] to enable one Slack connection that is shared by human interview prompts and run lifecycle notifications. server.integrations.slack.default_channel is an optional literal channel name used only as the default destination for interview prompts; it does not interpolate {{ env.* }}. Lifecycle notifications use [run.notifications.<name>.slack].channel in run or workflow configuration. Fabro resolves these from the vault only. When [server.integrations.slack] is present and both credentials are present, startup logs Slack integration enabled and then the Slack Socket Mode connection status. If the Slack config table is absent or enabled = false, startup logs Slack integration disabled by server configuration. If the table is present but either credential is missing or empty, startup logs Slack integration disabled; missing credentials with the missing variable names.

Logging