mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-05 08:10:39 +00:00
Move GitHub webhook intake onto the main API router, add explicit server_url and tailscale_funnel strategies, and validate strategy requirements at config resolution. This also updates the API contract, generated client, and operator docs to match the new webhook model.
339 lines
13 KiB
Text
339 lines
13 KiB
Text
---
|
|
title: "Server Configuration"
|
|
description: "Server-owned settings.toml sections, CLI overrides, and environment variables"
|
|
---
|
|
|
|
## 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]`.
|
|
|
|
<Note>
|
|
Fabro only reads `settings.toml`. Older `server.toml`, `user.toml`, and `cli.toml` filenames are no longer part of the supported config surface.
|
|
</Note>
|
|
|
|
### Which sections are server-owned
|
|
|
|
| Scope | Examples |
|
|
|---|---|
|
|
| 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
|
|
|
|
```toml title="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-web.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.slatedb]
|
|
provider = "s3"
|
|
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:
|
|
|
|
| Flag | Default | Description |
|
|
|---|---|---|
|
|
| `--bind` | Resolved `[server.listen]`, falling back to `~/.fabro/fabro.sock` when `[server.listen]` is absent | Address to bind: `IP` or `IP:port` for TCP, or a path for Unix socket |
|
|
| `--web` | enabled | Enable the embedded web UI, browser auth routes, and web-only helper endpoints |
|
|
| `--no-web` | disabled | Disable the embedded web UI, browser auth routes, and web-only helper endpoints |
|
|
| `--foreground` | — | Run in the foreground instead of daemonizing |
|
|
| `--model` | — | Override default LLM model |
|
|
| `--provider` | — | Override default LLM provider |
|
|
| `--sandbox` | — | Override default sandbox provider |
|
|
| `--max-concurrent-runs` | `5` | Maximum concurrent run executions |
|
|
| `--config` | `~/.fabro/settings.toml` | Path to server config file |
|
|
|
|
CLI flags take precedence over `settings.toml` values. See [Run Configuration — Precedence](/execution/run-configuration#precedence) for the full resolution order.
|
|
|
|
### `[server.web]` section
|
|
|
|
Control the embedded SPA and browser-oriented routes.
|
|
|
|
| Key | Description | Default |
|
|
|---|---|---|
|
|
| `enabled` | Serve the embedded SPA, `/auth/*`, and the web-only helper endpoints under `/api/v1` | `true` |
|
|
| `url` | External web UI URL used for OAuth redirects | none (no implicit derivation from `server.listen`) |
|
|
|
|
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.auth]` section
|
|
|
|
Configure how users authenticate with the server.
|
|
|
|
| Key | Description | Default |
|
|
|---|---|---|
|
|
| `methods` | Ordered 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.
|
|
|
|
| Key | Description |
|
|
|---|---|
|
|
| `allowed_usernames` | GitHub 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.
|
|
|
|
| Key | Description | Default |
|
|
|---|---|---|
|
|
| `provider` | Object store backend: `local` or `s3` | `"local"` |
|
|
| `prefix` | Key prefix within the object store | `""` |
|
|
| `flush_interval` | How often to flush the write-ahead log | `"1ms"` |
|
|
| `disk_cache` | Enable a local disk cache for object store reads | `false` |
|
|
|
|
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.
|
|
|
|
```toml title="settings.toml"
|
|
[server.slatedb]
|
|
provider = "s3"
|
|
disk_cache = true
|
|
|
|
[server.slatedb.s3]
|
|
bucket = "{{ env.SLATEDB_BUCKET }}"
|
|
region = "us-east-1"
|
|
```
|
|
|
|
### 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 default server log level. Precedence: `FABRO_LOG` env var > `--debug` flag > `[server.logging].level` > `"info"`.
|
|
|
|
| Key | Description | Default |
|
|
|---|---|---|
|
|
| `level` | Log level: `error`, `warn`, `info`, `debug`, `trace` | `"info"` |
|
|
|
|
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`.
|
|
|
|
| Key | Description | Default |
|
|
|---|---|---|
|
|
| `name` | Git author name | `"fabro"` |
|
|
| `email` | Git 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]`.
|
|
|
|
```toml title="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]`:
|
|
|
|
```toml title="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.
|
|
|
|
| Key | Description |
|
|
|---|---|
|
|
| `exclude_globs` | Glob 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](/execution/run-configuration#runcheckpoint) for per-run configuration.
|
|
|
|
### `[features]` section
|
|
|
|
Toggle experimental or opt-in features. All features default to `false`.
|
|
|
|
| Key | Description |
|
|
|---|---|
|
|
| `session_sandboxes` | Enable 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
|
|
- `FABRO_JWT_PRIVATE_KEY` / `FABRO_JWT_PUBLIC_KEY`, provisioned during install for future CLI login flows
|
|
|
|
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`.
|
|
|
|
| Variable | Provider |
|
|
|---|---|
|
|
| `ANTHROPIC_API_KEY` | Anthropic (Claude) |
|
|
| `OPENAI_API_KEY` | OpenAI (GPT) |
|
|
| `GEMINI_API_KEY` or `GOOGLE_API_KEY` | Google (Gemini) |
|
|
| `KIMI_API_KEY` | Kimi |
|
|
| `ZAI_API_KEY` | Zai (GLM) |
|
|
| `MINIMAX_API_KEY` | Minimax |
|
|
| `INCEPTION_API_KEY` | Inception (Mercury) |
|
|
|
|
### Sandbox and tools
|
|
|
|
| Variable | Description |
|
|
|---|---|
|
|
| `DAYTONA_API_KEY` | Daytona cloud sandbox API key |
|
|
| `BRAVE_SEARCH_API_KEY` | Brave Search API key (for the `web_search` tool) |
|
|
|
|
### Server authentication
|
|
|
|
Fabro resolves these from `process env -> server.env`.
|
|
|
|
| Variable | Description |
|
|
|---|---|
|
|
| `FABRO_JWT_PRIVATE_KEY` | Ed25519 private key (base64-encoded PEM) for JWT signing |
|
|
| `FABRO_JWT_PUBLIC_KEY` | Ed25519 public key (base64-encoded PEM) for JWT verification |
|
|
| `SESSION_SECRET` | Session encryption secret (64-character hex string) |
|
|
|
|
### GitHub integration (optional)
|
|
|
|
| Variable | Description |
|
|
|---|---|
|
|
| `GITHUB_TOKEN` | GitHub 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`.
|
|
|
|
| Variable | Description |
|
|
|---|---|
|
|
| `GITHUB_APP_CLIENT_SECRET` | GitHub App client secret |
|
|
| `GITHUB_APP_WEBHOOK_SECRET` | GitHub App webhook secret |
|
|
| `GITHUB_APP_PRIVATE_KEY` | GitHub App private key (base64-encoded) |
|
|
|
|
### Slack integration (optional)
|
|
|
|
| Variable | Description |
|
|
|---|---|
|
|
| `FABRO_SLACK_APP_TOKEN` | Slack App-level token |
|
|
| `FABRO_SLACK_BOT_TOKEN` | Slack Bot token |
|
|
|
|
### Logging
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `FABRO_LOG` | `info` | Log level: `error`, `warn`, `info`, `debug` |
|