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

ScopeExamples
Server-owned (runtime-only from local settings.toml)[server.listen], [server.api], [server.web], [server.auth], [server.storage], [server.artifacts], [server.slatedb], [server.scheduler], [server.logging], [server.integrations], [features]
Shared run defaults (layered through .fabro/project.toml/workflow.toml)[run.model], [run.prepare], [run.sandbox], [run.checkpoint], [run.inputs], [run.pull_request], [run.git], [run.hooks], [run.agent]
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, or platform ingress in front of Fabro. Use [server.api].url and [server.web].url for those external HTTPS URLs.

Full reference

settings.toml
_version = 1

[server.listen]
type = "tcp"
address = "0.0.0.0:3000"

[server.api]
url = "https://fabro.example.com/api/v1"

[server.web]
enabled = true
url = "https://fabro.example.com"

[server.auth]
methods = ["dev-token", "github"]

[server.auth.github]
allowed_usernames = ["alice", "bob"]

[server.integrations.github]
app_id = "123456"
client_id = "Iv1.abc123"

[server.integrations.github.webhooks]
strategy = "tailscale_funnel"

[server.storage]
root = "/var/lib/fabro"

[server.artifacts]
provider = "s3"
prefix = "artifacts"

[server.artifacts.s3]
bucket = "my-fabro-data"
region = "us-east-1"

[server.slatedb]
provider = "s3"
prefix = "slatedb"
disk_cache = true

[server.slatedb.s3]
bucket = "my-fabro-data"
region = "us-east-1"

[server.scheduler]
max_concurrent_runs = 8

[server.logging]
level = "info"

# Run defaults — applied to every run unless overridden by workflow/project config
[run.model]
name = "claude-sonnet-4-5"
provider = "anthropic"
fallbacks = ["gemini", "openai"]

[[run.prepare.steps]]
script = "npm install"

[run.sandbox]
provider = "daytona"

[run.sandbox.daytona]
auto_stop_interval = 60

[run.sandbox.daytona.labels]
team = "platform"

[run.checkpoint]
exclude_globs = ["**/node_modules/**", "**/.cache/**"]

[run.inputs]
default_branch = "main"

[run.git.author]
name = "fabro-bot"
email = "fabro-bot@company.com"

[features]
session_sandboxes = true

CLI overrides

Several settings.toml settings can be overridden via fabro server start flags:
FlagDefaultDescription
--bindResolved [server.listen], falling back to ~/.fabro/fabro.sock when [server.listen] is absentAddress to bind: IP or IP:port for TCP, or a path for Unix socket
--webenabledEnable the embedded web UI, browser auth routes, and web-only helper endpoints
--no-webdisabledDisable the embedded web UI, browser auth routes, and web-only helper endpoints
--foregroundRun in the foreground instead of daemonizing
--modelOverride default LLM model
--providerOverride default LLM provider
--sandboxOverride default sandbox provider
--max-concurrent-runs5Maximum concurrent run executions
--config~/.fabro/settings.tomlPath to server config file
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.
KeyDescriptionDefault
enabledServe the embedded SPA, /auth/*, and the web-only helper endpoints under /api/v1true
urlRequired single canonical origin for the server. The browser UI and /auth/* routes use this origin, and it must be an absolute http(s) URL.http://localhost:3000
When enabled = false, the server still exposes the machine API and /health, but /, /auth/*, SPA client routes, /api/v1/auth/me, /api/v1/setup/*, and /api/v1/demo/toggle 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.

[server.auth] section

Configure how users authenticate with the server.
KeyDescriptionDefault
methodsOrdered list of enabled bootstrap methods: dev-token, github["dev-token"]
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.
KeyDescription
allowed_usernamesGitHub usernames allowed to complete OAuth login
The GitHub OAuth client ID still lives under [server.integrations.github].client_id.

[server.slatedb] section

Configure the embedded SlateDB key-value store used for run event storage.
KeyDescriptionDefault
providerObject store backend: local or s3"local"
prefixKey prefix within the object store""
flush_intervalHow often to flush the write-ahead log"1ms"
disk_cacheEnable a local disk cache for object store readsfalse
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
[server.slatedb]
provider = "s3"
disk_cache = true

[server.slatedb.s3]
bucket = "{{ env.SLATEDB_BUCKET }}"
region = "us-east-1"
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
[server.artifacts]
provider = "local"
prefix = "artifacts"

[server.artifacts.local]
root = "/var/lib/fabro/objects"

[server.slatedb]
provider = "local"
prefix = "slatedb"

[server.slatedb.local]
root = "/var/lib/fabro/objects"
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.

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], [features], and [server.scheduler] always come from the server machine’s own settings.toml or fabro server start flags. Merge rules follow the normative matrix: [run.inputs] replaces wholesale, [run.sandbox.env] and [run.sandbox.daytona.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.
KeyDescriptionDefault
levelLog level: error, warn, info, debug, trace"info"
destinationWhere server logs are written: file (rotated daily under <storage>/logs/) or stdout"file"
Level precedence: FABRO_LOG env var > --debug flag > [server.logging].level > "info". Destination precedence: FABRO_LOG_DESTINATION env var > [server.logging].destination > "file". stdout is incompatible with daemon mode — use fabro server start --foreground (which is what container images do). 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.
KeyDescriptionDefault
nameGit author name"fabro"
emailGit author email"fabro@local"

[server.integrations.github] section

Configure GitHub integration auth. strategy = "token" is the default and uses a stored GITHUB_TOKEN from the vault (with GH_TOKEN as a fallback). strategy = "app" enables the GitHub App flow and browser OAuth; webhook delivery is configured separately under [server.integrations.github.webhooks].
settings.toml
[server.integrations.github]
strategy = "token"
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
[server.integrations.github]
strategy = "app"
app_id = "123456"
client_id = "Iv1.abc123"
slug = "fabro-app"

[server.api]
url = "https://fabro-api.example.com"

[server.integrations.github.webhooks]
strategy = "server_url"
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.
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.
KeyDescription
exclude_globsGlob patterns for files to exclude from checkpoint commits (for example, ["**/node_modules/**"])
exclude_globs replaces across layers — the highest-precedence layer wins wholesale. See Run Configuration — Checkpoint for per-run configuration.

[features] section

Toggle experimental or opt-in features. All features default to false.
KeyDescription
session_sandboxesEnable session sandboxes in the web UI
The same [features] section can be set in .fabro/project.toml (project-level) to enable features per-project.

Secrets and environment variables

Fabro splits secrets into two scopes:
  • Server runtime secrets live in <data_dir>/server.env and resolve with precedence process env -> server.env.
  • Workflow-visible secrets live in <data_dir>/vaults/default/secrets.json (the vault). Anything stored in the vault may be used by workflows.
For the auth model above, the main server runtime secrets are:
  • SESSION_SECRET when the web UI is enabled
  • FABRO_DEV_TOKEN when "dev-token" auth is enabled
  • GITHUB_APP_CLIENT_SECRET when "github" auth is enabled
  • AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY when the install wizard or a manual config uses static S3 object-store credentials
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

Fabro’s built-in provider access resolves these from process env -> vault.
VariableProvider
ANTHROPIC_API_KEYAnthropic (Claude)
OPENAI_API_KEYOpenAI (GPT)
GEMINI_API_KEY or GOOGLE_API_KEYGoogle (Gemini)
KIMI_API_KEYKimi
ZAI_API_KEYZai (GLM)
MINIMAX_API_KEYMinimax
INCEPTION_API_KEYInception (Mercury)

Sandbox and tools

VariableDescription
DAYTONA_API_KEYDaytona cloud sandbox API key
BRAVE_SEARCH_API_KEYBrave Search API key (for the web_search tool)

Server authentication

Fabro resolves these from process env -> server.env.
VariableDescription
SESSION_SECRETSession encryption secret (64-character hex string)

Object store runtime secrets (optional)

Fabro resolves these from process env -> server.env.
VariableDescription
AWS_ACCESS_KEY_IDStatic AWS access key ID for S3-backed [server.slatedb] / [server.artifacts]
AWS_SECRET_ACCESS_KEYMatching static AWS secret access key
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)

VariableDescription
GITHUB_TOKENGitHub personal access token, stored by fabro install when strategy = "token". Also accepts GH_TOKEN as a fallback.

GitHub App extras (optional)

Fabro resolves these from process env -> server.env.
VariableDescription
GITHUB_APP_CLIENT_SECRETGitHub App client secret
GITHUB_APP_WEBHOOK_SECRETGitHub App webhook secret
GITHUB_APP_PRIVATE_KEYGitHub App private key (base64-encoded)

Slack integration (optional)

VariableDescription
FABRO_SLACK_APP_TOKENSlack App-level token
FABRO_SLACK_BOT_TOKENSlack Bot token

Logging

VariableDefaultDescription
FABRO_LOGinfoLog level: error, warn, info, debug
FABRO_LOG_DESTINATIONfileServer log destination: file or stdout (containers default to stdout)