# Configuration Reference

> Complete reference for all ServerBee server and agent configuration options.

URL: https://docs.serverbee.app/en/docs/configuration

ServerBee loads configuration with [Figment](https://github.com/SergioBenitez/Figment), which layers values from multiple sources. This page is a complete reference for every configuration option.

## Configuration Loading Priority [#configuration-loading-priority]

Server values are merged in this order, with later sources overriding earlier ones:

1. Built-in defaults
2. `/etc/serverbee/server.toml`
3. `/opt/serverbee/etc/server.toml` (the path used by the install script)
4. `server.toml` in the working directory
5. Environment variables prefixed with `SERVERBEE_`

The Agent uses built-in defaults, then `/etc/serverbee/agent.toml`, `agent.toml` in its working directory, and finally `SERVERBEE_` environment variables. The managed service uses `/opt/serverbee/etc` as its working directory, so its third source is `/opt/serverbee/etc/agent.toml`.

This lets you override effective settings at runtime without editing the TOML file. Compatibility-only fields, such as the Agent's `collector.interval`, are called out below.

## Environment Variable Mapping [#environment-variable-mapping]

Every TOML key maps directly to an environment variable: add the `SERVERBEE_` prefix, uppercase the key, and replace each level of nesting with `__` (double underscore). For example, `auth.secure_cookie` becomes `SERVERBEE_AUTH__SECURE_COOKIE`.

## Developer Workflow Env Vars [#developer-workflow-env-vars]

These variables drive local repo tooling and developer workflows. They are not Figment-backed runtime config for the server or agent binaries.

| Environment Variable              | Used By                             | Description                                                                                                                                                                            |
| --------------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_PROD_URL`              | `make db-pull`, `make web-dev-prod` | Production base URL used by the database pull script and the frontend prod-proxy workflow                                                                                              |
| `SERVERBEE_PROD_API_KEY`          | `make db-pull`                      | Admin-scoped API key for the production backup API. Do not reuse this for `make web-dev-prod`                                                                                          |
| `SERVERBEE_PROD_READONLY_API_KEY` | `make web-dev-prod`                 | Member-scoped API key injected by the frontend dev proxy for live production browsing                                                                                                  |
| `ALLOW_WRITES`                    | `make web-dev-prod`                 | Local opt-in override. Set to `1` to disable the proxy's read-method-only block. When set, the UI banner changes from the normal read-only warning to a stronger write-enabled warning |

These variables are intentionally scoped to local tooling. `ALLOW_WRITES` is not a server feature flag; it is an explicit local override for the frontend prod-proxy workflow only.

### Server Environment Variables [#server-environment-variables]

#### Quick Start [#quick-start]

<Callout type="info">
  There is no admin username/password environment variable. On first start (when no users exist) the server auto-creates an admin account with a randomly generated password and prints it once to the server/container logs as a highlighted credentials banner. Capture it from the logs, then on first login you are required to change this password and may optionally choose a different username.
</Callout>

| Environment Variable       | Default        | Description             |
| -------------------------- | -------------- | ----------------------- |
| `SERVERBEE_SERVER__LISTEN` | `0.0.0.0:9527` | Listen address and port |

#### Common [#common]

| Environment Variable                | Default                | Description                                                                                   |
| ----------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------- |
| `SERVERBEE_SERVER__DATA_DIR`        | `./data`               | Data directory for database and backups                                                       |
| `SERVERBEE_AUTH__MAX_SERVERS`       | `0`                    | Maximum servers allowed via enrollment (0 = no limit). Best-effort soft cap                   |
| `SERVERBEE_SERVER__TRUSTED_PROXIES` | private/loopback CIDRs | CIDR list of trusted reverse proxies. Defaults to RFC 1918 + loopback. Set to `[]` to disable |
| `SERVERBEE_SCHEDULER__TIMEZONE`     | `UTC`                  | Timezone for daily traffic aggregation (e.g. `Asia/Shanghai`)                                 |
| `SERVERBEE_LOG__LEVEL`              | `info`                 | Log level: `trace`, `debug`, `info`, `warn`, `error`                                          |
| `SERVERBEE_LOG__FILE`               | `""`                   | Log file path. Empty means stdout only                                                        |

#### Development Only [#development-only]

| Environment Variable       | Default | Description                                                                                                                                                                             |
| -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_DEV__DEMO_DATA` | `false` | Reset and seed the local synthetic demo dataset. Only allowed with `SERVERBEE_DATABASE__PATH=dev-demo.db`; creates `admin` / `admin123` and in-memory demo agents for local development |

#### OAuth (Optional) [#oauth-optional]

| Environment Variable                     | Default                          | Description                                            |
| ---------------------------------------- | -------------------------------- | ------------------------------------------------------ |
| `SERVERBEE_OAUTH__BASE_URL`              | `""`                             | Public server URL for constructing OAuth callback URLs |
| `SERVERBEE_OAUTH__ALLOW_REGISTRATION`    | `false`                          | Auto-create user accounts on first OAuth login         |
| `SERVERBEE_OAUTH__GITHUB__CLIENT_ID`     | --                               | GitHub OAuth App client ID                             |
| `SERVERBEE_OAUTH__GITHUB__CLIENT_SECRET` | --                               | GitHub OAuth App client secret                         |
| `SERVERBEE_OAUTH__GOOGLE__CLIENT_ID`     | --                               | Google OAuth client ID                                 |
| `SERVERBEE_OAUTH__GOOGLE__CLIENT_SECRET` | --                               | Google OAuth client secret                             |
| `SERVERBEE_OAUTH__OIDC__ISSUER_URL`      | --                               | OIDC provider issuer URL                               |
| `SERVERBEE_OAUTH__OIDC__CLIENT_ID`       | --                               | OIDC client ID                                         |
| `SERVERBEE_OAUTH__OIDC__CLIENT_SECRET`   | --                               | OIDC client secret                                     |
| `SERVERBEE_OAUTH__OIDC__SCOPES`          | `["openid", "email", "profile"]` | OAuth scopes to request                                |

#### GeoIP (Optional) [#geoip-optional]

| Environment Variable         | Default | Description                                                                                                                                                                            |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_GEOIP__MMDB_PATH` | `""`    | Path to a MaxMind-compatible MMDB file. Non-empty path enables this custom GeoIP database; otherwise admins can download the DB-IP Lite database from Settings → GeoIP Database        |
| `SERVERBEE_ASN__MMDB_PATH`   | `""`    | Path to a DB-IP Lite ASN / MaxMind GeoLite2-ASN MMDB file. Non-empty path enables traceroute ASN enrichment; otherwise admins can download DB-IP Lite ASN from Settings → ASN Database |

#### Resend (Email Notifications) [#resend-email-notifications]

| Environment Variable        | Default | Description                                                                                            |
| --------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
| `SERVERBEE_RESEND__API_KEY` | `""`    | Resend API key. Required for Email notifications. Sender domain must be verified at resend.com/domains |

#### Data Retention (Tuning) [#data-retention-tuning]

| Environment Variable                             | Default | Description                                              |
| ------------------------------------------------ | ------- | -------------------------------------------------------- |
| `SERVERBEE_RETENTION__RECORDS_DAYS`              | `7`     | Raw metric records retention in days                     |
| `SERVERBEE_RETENTION__RECORDS_HOURLY_DAYS`       | `90`    | Hourly aggregated records retention in days              |
| `SERVERBEE_RETENTION__GPU_RECORDS_DAYS`          | `7`     | GPU metric records retention in days                     |
| `SERVERBEE_RETENTION__PING_RECORDS_DAYS`         | `7`     | Ping probe records retention in days                     |
| `SERVERBEE_RETENTION__NETWORK_PROBE_DAYS`        | `7`     | Raw network probe records retention in days              |
| `SERVERBEE_RETENTION__NETWORK_PROBE_HOURLY_DAYS` | `90`    | Hourly network probe aggregates retention in days        |
| `SERVERBEE_RETENTION__AUDIT_LOGS_DAYS`           | `180`   | Audit log retention in days                              |
| `SERVERBEE_RETENTION__TRAFFIC_HOURLY_DAYS`       | `7`     | Traffic hourly records retention in days                 |
| `SERVERBEE_RETENTION__TRAFFIC_DAILY_DAYS`        | `400`   | Traffic daily records retention in days                  |
| `SERVERBEE_RETENTION__TASK_RESULTS_DAYS`         | `7`     | Task results retention in days                           |
| `SERVERBEE_RETENTION__DOCKER_EVENTS_DAYS`        | `7`     | Docker event records retention in days                   |
| `SERVERBEE_RETENTION__SERVICE_MONITOR_DAYS`      | `30`    | Service monitor records retention in days                |
| `SERVERBEE_RETENTION__SECURITY_EVENT_DAYS`       | `30`    | Security event records retention in days                 |
| `SERVERBEE_RETENTION__IP_QUALITY_EVENT_DAYS`     | `90`    | IP quality status-change event records retention in days |

#### Mobile (Optional) [#mobile-optional]

| Environment Variable            | Default   | Description                                        |
| ------------------------------- | --------- | -------------------------------------------------- |
| `SERVERBEE_MOBILE__ACCESS_TTL`  | `900`     | Mobile access token lifetime in seconds (15 min)   |
| `SERVERBEE_MOBILE__REFRESH_TTL` | `2592000` | Mobile refresh token lifetime in seconds (30 days) |

#### Firewall (Optional) [#firewall-optional]

Tier-2 guardrail for the [Firewall Blocklist](/en/docs/firewall) feature. CIDRs / IPs listed here are refused by `POST /api/firewall/blocks` even if an administrator tries to insert them. Tier 1 (hard-coded protected ranges: loopback, RFC 1918, link-local, multicast, unspecified) is always enforced.

| Environment Variable             | Default | Description                                                                                                                           |
| -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_FIREWALL__ALLOW_LIST` | `[]`    | CIDRs / IPs the server refuses to insert into `block_list`. Tier-2 guardrail layered on top of the hard-coded Tier-1 protected ranges |

#### IP Quality [#ip-quality]

By default, the Server calls [ipapi.is](https://ipapi.is/developers.html) anonymously (100 requests per client IP per UTC day). ServerBee uses the minimal response's proxy, VPN, datacenter, Tor, and abuse flags and derives an IP type, but no numeric risk score. A free account/API key provides 1,000 requests per day and the full response required for the 0–100 score. The Server falls back to [ip-api.com](https://ip-api.com) only when the primary request fails, including HTTP 429, not when a successful response lacks a score. See [IP Quality](/en/docs/ip-quality) for details and the fallback's non-commercial/HTTP warning.

| Environment Variable                           | Default      | Description                                                                                                      |
| ---------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_IP_QUALITY__RISK_PROVIDER`          | `"ipapi_is"` | Primary risk provider. One of: `none`, `ipapi_is`, `ip-api`.                                                     |
| `SERVERBEE_IP_QUALITY__RISK_PROVIDER_FALLBACK` | `"ip-api"`   | Fallback provider triggered on primary failure. Set to `none` to disable.                                        |
| `SERVERBEE_IP_QUALITY__IPAPI_IS__API_KEY`      | --           | Optional. A free account key provides 1,000 requests per day and the full response required for the 0–100 score. |
| `SERVERBEE_IP_QUALITY__IPAPI_IS__ENDPOINT`     | `""`         | Override for self-hosted mirrors or testing. Empty falls back to the built-in default `https://api.ipapi.is`.    |

<Callout type="info">
  **Migration from older versions:** Earlier releases supported four paid providers (Scamalytics, IPQualityScore, ProxyCheck, AbuseIPDB) configured via `SERVERBEE_IP_QUALITY__{SCAMALYTICS,IPQS,PROXYCHECK,ABUSEIPDB}__*`. These env vars are silently ignored. To restore equivalent functionality, fork or vendor the provider implementation from a tag prior to 2026-05-25.
</Callout>

#### Network Probe Anomaly Thresholds [#network-probe-anomaly-thresholds]

Average-latency cutoffs used to classify network-probe records returned by `/api/servers/{id}/network-probes/anomalies` and the `anomaly_count` field on the network-probe overview. Records strictly above `very_high_latency_ms` are tagged `very_high_latency`; records above `high_latency_ms` (and at or below the very-high cutoff) are tagged `high_latency`.

| Environment Variable                            | Default | Description                                                    |
| ----------------------------------------------- | ------- | -------------------------------------------------------------- |
| `SERVERBEE_NETWORK_PROBE__HIGH_LATENCY_MS`      | `500`   | Avg-latency cutoff (ms) for `high_latency` classification      |
| `SERVERBEE_NETWORK_PROBE__VERY_HIGH_LATENCY_MS` | `800`   | Avg-latency cutoff (ms) for `very_high_latency` classification |

#### Internal [#internal]

> These variables have sensible defaults and rarely need changing. Adjust them only when you have a specific requirement.

| Environment Variable                    | Default                                                 | Description                                                                                                                                          |
| --------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_DATABASE__PATH`              | `serverbee.db`                                          | SQLite database file path (relative to data\_dir)                                                                                                    |
| `SERVERBEE_DATABASE__MAX_CONNECTIONS`   | `10`                                                    | Maximum database connection pool size                                                                                                                |
| `SERVERBEE_AUTH__SESSION_TTL`           | `86400`                                                 | Session token TTL in seconds (default 24h)                                                                                                           |
| `SERVERBEE_AUTH__SECURE_COOKIE`         | `true`                                                  | Set the Secure flag on session cookies. Use `false` only when the browser accesses ServerBee over plain HTTP, such as direct IP quick-start installs |
| `SERVERBEE_RATE_LIMIT__LOGIN_MAX`       | `5`                                                     | Max login attempts per IP within 15-minute window                                                                                                    |
| `SERVERBEE_RATE_LIMIT__REGISTER_MAX`    | `10`                                                    | Max agent registrations per IP within 15-minute window. Admins can clear an active window from Settings → Rate limits                                |
| `SERVERBEE_UPGRADE__RELEASE_BASE_URL`   | `https://github.com/ZingerLittleBee/ServerBee/releases` | Base URL for agent upgrade release assets                                                                                                            |
| `SERVERBEE_UPGRADE__LATEST_VERSION_URL` | `""`                                                    | Optional custom URL for latest version API. If empty, uses GitHub API                                                                                |
| `SERVERBEE_UPGRADE__CHANNEL`            | `stable`                                                | Release channel used by the dashboard version check: `stable` or `beta`                                                                              |
| `SERVERBEE_FILE__MAX_UPLOAD_SIZE`       | `104857600`                                             | Maximum file upload size in bytes (default 100 MB)                                                                                                   |

### Agent Environment Variables [#agent-environment-variables]

Agent top-level keys use single underscore. Nested keys use `__` (double underscore).

#### Quick Start [#quick-start-1]

| Environment Variable        | Default       | Description                                                                                                                                                  |
| --------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SERVERBEE_SERVER_URL`      | -- (required) | Server HTTP base URL (e.g. `http://your-server:9527`). Agent appends API paths automatically                                                                 |
| `SERVERBEE_ENROLLMENT_CODE` | `""`          | One-time enrollment offer shown when a Server is added or re-enrollment begins. Single-use and short-lived (default 10 min). Only used when `token` is empty |

#### Common [#common-1]

| Environment Variable                             | Default              | Description                                                                                                                                                       |
| ------------------------------------------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_COLLECTOR__INTERVAL`                  | `3`                  | Compatibility-only field. The Agent currently ignores it and uses the Server's `Welcome.report_interval` value, which is fixed at 3 seconds                       |
| `SERVERBEE_COLLECTOR__ENABLE_GPU`                | `false`              | Enable NVIDIA GPU monitoring (requires a build with the `gpu` feature and an NVIDIA driver that provides NVML)                                                    |
| `SERVERBEE_COLLECTOR__ENABLE_TEMPERATURE`        | `true`               | Enable CPU temperature monitoring                                                                                                                                 |
| `SERVERBEE_FILE__ENABLED`                        | `false`              | Enable file management on this agent                                                                                                                              |
| `SERVERBEE_FILE__ROOT_PATHS`                     | `[]`                 | Allowed root paths (comma-separated, e.g. `/home,/var/log`). Empty rejects all file operations                                                                    |
| `SERVERBEE_CAPABILITIES__ALLOW`                  | `[]`                 | Capability keys to enable on top of the default set (`CAP_DEFAULT`), e.g. `["terminal","file"]`. See [Capabilities](/en/docs/capabilities)                        |
| `SERVERBEE_CAPABILITIES__DENY`                   | `[]`                 | Capability keys to strip from the default set. `deny` wins over `allow`. Unknown keys fail at startup                                                             |
| `SERVERBEE_CAPABILITIES__TEMPORARY_MAX_DURATION` | `24h`                | Max duration a single temporary capability grant can last (e.g. `30m`, `2h`, `1d`). See [Capabilities → Temporary grants](/en/docs/capabilities#temporary-grants) |
| `SERVERBEE_CAPABILITIES__STATE_DIR`              | `/var/lib/serverbee` | Directory where the agent persists `capability_grants.json` (must be writable by the agent)                                                                       |
| `SERVERBEE_IP_CHANGE__ENABLED`                   | `true`               | Enable periodic IP change detection                                                                                                                               |
| `SERVERBEE_LOG__LEVEL`                           | `info`               | Log level: `trace`, `debug`, `info`, `warn`, `error`                                                                                                              |
| `SERVERBEE_LOG__FILE`                            | `""`                 | Log file path. Empty means stdout only                                                                                                                            |

#### Internal [#internal-1]

> These variables have sensible defaults and rarely need changing. Adjust them only when you have a specific requirement.

| Environment Variable                    | Default                                                                                                      | Description                                                                                                                                                                                                                                                                 |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_TOKEN`                       | generated when empty                                                                                         | Agent run token. During enrollment the Agent generates and persists one before claim; an explicit environment override is used as provided and is not written to disk                                                                                                       |
| `SERVERBEE_FILE__MAX_FILE_SIZE`         | `1073741824`                                                                                                 | Max file size in bytes for read/download (default 1GB)                                                                                                                                                                                                                      |
| `SERVERBEE_FILE__DENY_PATTERNS`         | `*.key,*.pem,...`                                                                                            | Glob patterns for files the agent refuses to access                                                                                                                                                                                                                         |
| `SERVERBEE_IP_CHANGE__EXTERNAL_IP_URLS` | `["https://api.ipify.org","https://ifconfig.me/ip","https://icanhazip.com","https://checkip.amazonaws.com"]` | Ordered list of public IP services tried at startup and on every IP-change tick. First success wins. Required for agents behind NAT or in containers where interface enumeration can't see the routable IP. Set to `[]` to skip external lookups for air-gapped deployments |
| `SERVERBEE_IP_CHANGE__INTERVAL_SECS`    | `300`                                                                                                        | IP check interval in seconds (default 5 minutes)                                                                                                                                                                                                                            |

#### Upgrade (Agent) [#upgrade-agent]

| Environment Variable                          | Default                                                 | Description                                                                                                                                                                                                                                                                                                |
| --------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_UPGRADE__RELEASE_REPO_URL`         | `https://github.com/ZingerLittleBee/ServerBee/releases` | Pinned release source base URL the Agent downloads upgrades from. Any HTTPS host mirroring the GitHub releases path layout `{base}/download/v{version}/{asset}` and `{base}/download/v{version}/sha256sums.txt` works. Compile-time default is overridable via the `SERVERBEE_RELEASE_REPO` build-time env |
| `SERVERBEE_UPGRADE__RELEASE_CERT_SPKI_SHA256` | `""`                                                    | Optional TLS certificate SPKI pin for the release host. 64 lowercase hex chars = SHA-256 of the leaf cert SubjectPublicKeyInfo DER. Empty = disabled. If set, the Agent additionally pins the leaf cert SPKI after standard chain validation. Invalid (non-64/non-hex) values are rejected at startup      |

#### Security (Agent) [#security-agent]

Tunes the agent-side security event detectors (SSH login / brute force, port scan). Detection runs entirely on the agent; the server only stores events and evaluates alert rules. Configure per-host since traffic profiles differ.

| Environment Variable                                     | Default                       | Description                                                                                                    |
| -------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `SERVERBEE_SECURITY__ENABLED`                            | `true`                        | Master switch for all security detectors. When `false` the agent emits no `security_event` messages            |
| `SERVERBEE_SECURITY__SSH__WINDOW_SECONDS`                | `60`                          | Sliding window length (seconds) for SSH brute-force detection                                                  |
| `SERVERBEE_SECURITY__SSH__FAILED_THRESHOLD`              | `10`                          | Failed SSH attempts within the window that trigger an `ssh_brute_force` event. Queue clears after firing       |
| `SERVERBEE_SECURITY__PORT_SCAN__ENABLED`                 | `false`                       | Enable port-scan detection. Requires `conntrack` CLI installed (Linux)                                         |
| `SERVERBEE_SECURITY__PORT_SCAN__WINDOW_SECONDS`          | `30`                          | Sliding window length (seconds) for port-scan detection                                                        |
| `SERVERBEE_SECURITY__PORT_SCAN__DISTINCT_PORT_THRESHOLD` | `20`                          | Distinct destination ports hit by a single source IP within the window that trigger a `port_scan` event        |
| `SERVERBEE_SECURITY__DATA_DIR`                           | `/var/lib/serverbee/security` | Directory for the persistent `first_seen` store used to mark `ssh_login` events as new (user, IP) combinations |

## Server Configuration (server.toml) [#server-configuration-servertoml]

### `[server]` -- Core Server Settings [#server----core-server-settings]

| Key               | Type      | Default                | Description                                                                                                                       |
| ----------------- | --------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `listen`          | string    | `"0.0.0.0:9527"`       | IP address and port the server listens on                                                                                         |
| `data_dir`        | string    | `"./data"`             | Directory for database files and other persistent data                                                                            |
| `trusted_proxies` | string\[] | private/loopback CIDRs | CIDR ranges of trusted reverse proxies. Defaults to RFC 1918 + loopback ranges. Set to `[]` to disable X-Forwarded-For extraction |

### `[database]` -- Database Settings [#database----database-settings]

| Key               | Type   | Default          | Description                                      |
| ----------------- | ------ | ---------------- | ------------------------------------------------ |
| `path`            | string | `"serverbee.db"` | Database filename (relative to `data_dir`)       |
| `max_connections` | u32    | `10`             | Maximum number of connections in the SQLite pool |

### `[auth]` -- Authentication Settings [#auth----authentication-settings]

| Key             | Type | Default | Description                                                                                                    |
| --------------- | ---- | ------- | -------------------------------------------------------------------------------------------------------------- |
| `session_ttl`   | i64  | `86400` | Session cookie lifetime in seconds (24 hours)                                                                  |
| `max_servers`   | u32  | `0`     | Maximum servers allowed via enrollment (0 = no limit). Best-effort soft cap                                    |
| `secure_cookie` | bool | `true`  | Set the `Secure` flag on session cookies. Use `false` only when the browser accesses ServerBee over plain HTTP |

### `[dev]` -- Local Development [#dev----local-development]

| Key         | Type | Default | Description                                                                                                                                                                        |
| ----------- | ---- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `demo_data` | bool | `false` | Reset and seed the synthetic local development dataset. Guarded to `database.path = "dev-demo.db"` so it cannot accidentally run against normal local or production-copy databases |

### `[retention]` -- Data Retention [#retention----data-retention]

| Key                         | Type | Default | Description                                                            |
| --------------------------- | ---- | ------- | ---------------------------------------------------------------------- |
| `records_days`              | u32  | `7`     | Days to keep raw metric records                                        |
| `records_hourly_days`       | u32  | `90`    | Days to keep hourly aggregated records                                 |
| `gpu_records_days`          | u32  | `7`     | Days to keep per-GPU metric records                                    |
| `ping_records_days`         | u32  | `7`     | Days to keep ping probe records                                        |
| `network_probe_days`        | u32  | `7`     | Days to keep raw network probe records                                 |
| `network_probe_hourly_days` | u32  | `90`    | Days to keep hourly aggregated network probe records                   |
| `audit_logs_days`           | u32  | `180`   | Days to keep audit log entries                                         |
| `traffic_hourly_days`       | u32  | `7`     | Days to keep hourly traffic records                                    |
| `traffic_daily_days`        | u32  | `400`   | Days to keep daily traffic records                                     |
| `task_results_days`         | u32  | `7`     | Days to keep task execution results                                    |
| `docker_events_days`        | u32  | `7`     | Days to keep Docker event records                                      |
| `service_monitor_days`      | u32  | `30`    | Days to keep service monitor check records                             |
| `security_event_days`       | u32  | `30`    | Days to keep security event records (SSH login/brute force, port scan) |
| `ip_quality_event_days`     | u32  | `90`    | Days to keep IP quality status-change event records                    |

<Callout type="info">
  Raw metric records are written every 60 seconds and retained for 7 days by default. The hourly aggregator computes averages so you can keep 90 days of long-term trends without excessive storage. Tune these values to match your disk space and monitoring needs.
</Callout>

### `[scheduler]` -- Scheduler [#scheduler----scheduler]

| Key        | Type   | Default | Description                                                                                                                        |
| ---------- | ------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `timezone` | string | `"UTC"` | Timezone for daily traffic aggregation and billing cycle computation. Use IANA timezone names (e.g. `Asia/Shanghai`, `US/Eastern`) |

### `[rate_limit]` -- Rate Limiting [#rate_limit----rate-limiting]

| Key            | Type | Default | Description                                                                                                           |
| -------------- | ---- | ------- | --------------------------------------------------------------------------------------------------------------------- |
| `login_max`    | u32  | `5`     | Maximum login attempts per rate-limit window                                                                          |
| `register_max` | u32  | `10`    | Maximum agent registration attempts per rate-limit window. Admins can clear active windows via Settings → Rate limits |

### `[log]` -- Logging [#log----logging]

| Key     | Type   | Default  | Description                                              |
| ------- | ------ | -------- | -------------------------------------------------------- |
| `level` | string | `"info"` | Log verbosity: `trace`, `debug`, `info`, `warn`, `error` |
| `file`  | string | `""`     | Path to log file. If empty, logs go to stdout only       |

The log level can also be set via the `RUST_LOG` environment variable, which takes precedence.

### `[geoip]` -- GeoIP Lookup [#geoip----geoip-lookup]

| Key         | Type   | Default | Description                                                                                                                                                        |
| ----------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `mmdb_path` | string | `""`    | Path to a MaxMind-compatible MMDB file. Non-empty path enables this custom GeoIP database; if empty, the UI can download DB-IP Lite into the server data directory |

### `[asn]` -- ASN Lookup (Traceroute) [#asn----asn-lookup-traceroute]

| Key         | Type   | Default | Description                                                                                                                                                                                                                                           |
| ----------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mmdb_path` | string | `""`    | Path to a DB-IP Lite ASN / MaxMind GeoLite2-ASN MMDB file. Non-empty path enables this custom ASN database; if empty, the UI can download DB-IP Lite ASN into the server data directory. Used to label each traceroute hop with its autonomous system |

### `[resend]` -- Email Notifications [#resend----email-notifications]

| Key       | Type   | Default | Description                                                                                                                                                                                                                                        |
| --------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key` | string | `""`    | Resend API key ([resend.com/api-keys](https://resend.com/api-keys)). Required to use the Email notification channel. The `from` address on each email channel must belong to a domain verified at [resend.com/domains](https://resend.com/domains) |

### `[oauth]` -- OAuth / SSO [#oauth----oauth--sso]

| Key                  | Type   | Default | Description                                               |
| -------------------- | ------ | ------- | --------------------------------------------------------- |
| `base_url`           | string | `""`    | Public URL of your ServerBee instance (for callback URLs) |
| `allow_registration` | bool   | `false` | Create new user accounts on first OAuth login             |

### `[oauth.github]` -- GitHub OAuth [#oauthgithub----github-oauth]

| Key             | Type   | Default | Description                    |
| --------------- | ------ | ------- | ------------------------------ |
| `client_id`     | string | --      | GitHub OAuth App client ID     |
| `client_secret` | string | --      | GitHub OAuth App client secret |

### `[oauth.google]` -- Google OAuth [#oauthgoogle----google-oauth]

| Key             | Type   | Default | Description                |
| --------------- | ------ | ------- | -------------------------- |
| `client_id`     | string | --      | Google OAuth client ID     |
| `client_secret` | string | --      | Google OAuth client secret |

### `[oauth.oidc]` -- OpenID Connect [#oauthoidc----openid-connect]

| Key             | Type      | Default                          | Description                                                    |
| --------------- | --------- | -------------------------------- | -------------------------------------------------------------- |
| `issuer_url`    | string    | --                               | OIDC issuer URL (e.g., `https://auth.example.com/realms/main`) |
| `client_id`     | string    | --                               | OIDC client ID                                                 |
| `client_secret` | string    | --                               | OIDC client secret                                             |
| `scopes`        | string\[] | `["openid", "email", "profile"]` | OAuth scopes to request                                        |

### `[upgrade]` -- Agent Upgrade [#upgrade----agent-upgrade]

| Key                  | Type   | Default                                                   | Description                                                                                                                                                              |
| -------------------- | ------ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `release_base_url`   | string | `"https://github.com/ZingerLittleBee/ServerBee/releases"` | Base URL for agent upgrade release assets. The server appends `/download/v{version}/` to construct the asset download URL                                                |
| `latest_version_url` | string | `""`                                                      | Optional custom URL for latest version API. If empty, the server queries GitHub API to determine the latest version. Use this to override with a custom version endpoint |
| `channel`            | string | `"stable"`                                                | Release channel used by the dashboard version check. Set to `"beta"` to select the newest published GitHub prerelease                                                    |

### `[file]` -- File Upload (Server-side) [#file----file-upload-server-side]

| Key               | Type | Default     | Description                                        |
| ----------------- | ---- | ----------- | -------------------------------------------------- |
| `max_upload_size` | u64  | `104857600` | Maximum file upload size in bytes (default 100 MB) |

### `[mobile]` -- Mobile Authentication [#mobile----mobile-authentication]

| Key           | Type | Default   | Description                                                  |
| ------------- | ---- | --------- | ------------------------------------------------------------ |
| `access_ttl`  | i64  | `900`     | Mobile access token lifetime in seconds (default 15 minutes) |
| `refresh_ttl` | i64  | `2592000` | Mobile refresh token lifetime in seconds (default 30 days)   |

### `[push_relay]` -- Verified Mobile Setup [#push_relay----verified-mobile-setup]

| Key   | Type   | Default | Description                                                                                                               |
| ----- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| `url` | string | `""`    | Public Push Relay HTTPS URL. Empty disables notification registration. Apple signing keys stay exclusively in the Worker. |

Set `SERVERBEE_PUSH_RELAY__URL` to the final HTTPS Worker URL. “Verified” here means authenticated Server account, installation and session ownership; there is no App Attest or Relay grant. The app registers its token, APNs environment and per-installation content key with the Server over HTTPS. The Server encrypts content and sends token, environment, event identity, expiry and envelope to the Worker's public `POST /v1/send`. Local Server fixtures may use `http://127.0.0.1:<port>`; the app requires HTTPS and rejects redirects.

Worker-only bindings are `APNS_TEAM_ID`, `APNS_KEY_ID`, `APNS_TOPIC`, `APNS_ENVIRONMENTS` and the `APNS_PRIVATE_KEY` secret containing PKCS#8 PEM text. They never belong in Server configuration or the app. `APNS_TOPIC=app.serverbee` matches the official main app; never use the extension identifier `app.serverbee.notifications`. `APNS_ENVIRONMENTS=sandbox,production` allows both device environments; topic and APNs hosts are fixed by the Worker. There is no database, challenge/grant lifecycle, version/distribution policy or Bun/OpenSSL runtime. See [Cloudflare setup](/en/docs/push-relay#cloudflare-quick-setup).

The public endpoint accepts abuse risk: known valid tokens can receive junk/generic notifications, while arbitrary traffic or an attacker's own token can consume quota. Strict payload limits, bounded streaming reads, deadlines, concurrency and bounded isolate-local source/target rate limits are best-effort safeguards, not global admission or cost guarantees. Content keys and business plaintext never cross Relay.

The Server retains authenticated subscriptions, recipient checks, durable encrypted outbox/retry, and a 30-minute deadline from original event creation. Alert triggers/recoveries, administrator security-rule matches and owner-only final scheduled-task outcomes remain supported; task success is opt-in. Role/session/subscription/revision changes stop later eligible sends. Terminal ciphertext is erased, and accepted or in-flight notifications cannot be recalled. APNs acceptance is a provider receipt, not proof of device presentation. Shared app/NSE Keychain signing and live device acceptance still require separate verification. See [Mobile](/en/docs/mobile) and [Push Relay Operations](/en/docs/push-relay).

### `[firewall]` -- Firewall Blocklist Guardrail [#firewall----firewall-blocklist-guardrail]

| Key          | Type      | Default | Description                                                                                                                                                                                                                             |
| ------------ | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allow_list` | string\[] | `[]`    | CIDRs / IPs the server refuses to insert into `block_list`. Tier-2 guardrail on top of the hard-coded Tier-1 protected ranges (loopback + RFC 1918 + link-local + multicast + unspecified). See [Firewall Blocklist](/en/docs/firewall) |

### `[ip_quality]` -- IP Quality Risk Scoring [#ip_quality----ip-quality-risk-scoring]

By default, the Server calls [ipapi.is](https://ipapi.is/developers.html) anonymously (100 requests per client IP per UTC day). ServerBee uses the minimal response's proxy, VPN, datacenter, Tor, and abuse flags and derives an IP type, but no numeric risk score. A free account/API key provides 1,000 requests per day and the full response required for the 0–100 score. The Server falls back to [ip-api.com](https://ip-api.com) only when the primary request fails, including HTTP 429, not when a successful response lacks a score. Local baseline metadata is available only when a usable GeoIP MMDB is loaded. See [IP Quality](/en/docs/ip-quality) for details and the fallback's non-commercial/HTTP warning.

| Key                      | Type   | Default      | Description                                                               |
| ------------------------ | ------ | ------------ | ------------------------------------------------------------------------- |
| `risk_provider`          | string | `"ipapi_is"` | Primary risk provider. One of: `none`, `ipapi_is`, `ip-api`.              |
| `risk_provider_fallback` | string | `"ip-api"`   | Fallback provider triggered on primary failure. Set to `none` to disable. |

### `[ip_quality.ipapi_is]` -- ipapi.is [#ip_qualityipapi_is----ipapiis]

| Key        | Type   | Default | Description                                                                                                      |
| ---------- | ------ | ------- | ---------------------------------------------------------------------------------------------------------------- |
| `api_key`  | string | --      | Optional. A free account key provides 1,000 requests per day and the full response required for the 0–100 score. |
| `endpoint` | string | `""`    | Override for self-hosted mirrors or testing. Empty falls back to the built-in default `https://api.ipapi.is`.    |

### `[network_probe]` -- Anomaly Thresholds [#network_probe----anomaly-thresholds]

| Key                    | Type | Default | Description                                                              |
| ---------------------- | ---- | ------- | ------------------------------------------------------------------------ |
| `high_latency_ms`      | f64  | `500`   | Records above this average latency are classified as `high_latency`      |
| `very_high_latency_ms` | f64  | `800`   | Records above this average latency are classified as `very_high_latency` |

***

## Agent Configuration (agent.toml) [#agent-configuration-agenttoml]

### Top-Level Options [#top-level-options]

| Key               | Type   | Default      | Description                                                                                                                                                   |
| ----------------- | ------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `server_url`      | string | **required** | URL of the ServerBee server (e.g., `http://10.0.0.1:9527`)                                                                                                    |
| `token`           | string | `""`         | Agent authentication token. When enrollment is needed, the Agent generates and persists this token before claiming the offer; the Server stores only its hash |
| `enrollment_code` | string | `""`         | One-time enrollment offer from Add Server or the Server's Agent Authority actions (used only when `token` is empty; consumed on first successful claim)       |

### `[collector]` -- Metric Collection [#collector----metric-collection]

| Key                  | Type | Default | Description                                                                                                                  |
| -------------------- | ---- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `interval`           | u32  | `3`     | Compatibility-only field. The Agent currently ignores it and uses the Server's `Welcome.report_interval`, fixed at 3 seconds |
| `enable_gpu`         | bool | `false` | Enable NVIDIA GPU monitoring (requires a build with the `gpu` feature and an NVIDIA driver that provides NVML)               |
| `enable_temperature` | bool | `true`  | Enable CPU temperature sensor monitoring                                                                                     |

### `[file]` -- File Management [#file----file-management]

| Key             | Type      | Default                                                      | Description                                                                                                                                           |
| --------------- | --------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`       | bool      | `false`                                                      | Enable the file-management subsystem (path sandbox). The agent must also report the `file` capability — add `file` to the `[capabilities]` allow list |
| `root_paths`    | string\[] | `[]`                                                         | Restrict browsing to these directories. Empty array rejects all file operations                                                                       |
| `max_file_size` | u64       | `1073741824`                                                 | Maximum file size (bytes) for read and download operations (default 1 GB)                                                                             |
| `deny_patterns` | string\[] | `["*.key", "*.pem", "id_rsa*", ".env*", "shadow", "passwd"]` | Glob patterns for files the agent will refuse to access                                                                                               |

### `[capabilities]` -- Agent-Owned Capability Policy [#capabilities----agent-owned-capability-policy]

Capabilities are owned by the agent host. The agent starts from the default set (`CAP_DEFAULT = 1852`), applies `allow`/`deny` from this block, then applies any `--allow-cap`/`--deny-cap` CLI flags, and reports the result to the server. The server **cannot** override this. See [Capabilities](/en/docs/capabilities) for the full key list and enforcement model.

| Key                      | Type      | Default                | Description                                                                                                                                                                                                                            |
| ------------------------ | --------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allow`                  | string\[] | `[]`                   | Capability keys to enable on top of the default set, e.g. `["terminal", "file"]`. Valid keys: `terminal`, `exec`, `upgrade`, `ping_icmp`, `ping_tcp`, `ping_http`, `file`, `docker`, `security_events`, `firewall_block`, `ip_quality` |
| `deny`                   | string\[] | `[]`                   | Capability keys to strip from the default set. `deny` wins over `allow`. Unknown keys are rejected at startup                                                                                                                          |
| `temporary_max_duration` | string    | `"24h"`                | Maximum duration a single temporary capability grant can last (e.g. `30m`, `2h`, `1d`). Used by the host-local `serverbee-agent grant` CLI. See [Capabilities → Temporary grants](/en/docs/capabilities#temporary-grants)              |
| `state_dir`              | string    | `"/var/lib/serverbee"` | Directory where the agent persists `capability_grants.json` (the temporary-grants store). Must be writable by the agent                                                                                                                |

```toml
[capabilities]
allow = ["terminal", "file"]
deny = ["ip_quality"]
# Footgun guard for `serverbee-agent grant --for ...`; defaults to 24h.
temporary_max_duration = "24h"
state_dir = "/var/lib/serverbee"
```

### `[ip_change]` -- IP Change Detection [#ip_change----ip-change-detection]

| Key                | Type      | Default                                                                                                         | Description                                                                                                                                                                                                                                        |
| ------------------ | --------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`          | bool      | `true`                                                                                                          | Enable periodic IP change detection. Agent enumerates NIC addresses and reports changes                                                                                                                                                            |
| `external_ip_urls` | string\[] | `["https://api.ipify.org", "https://ifconfig.me/ip", "https://icanhazip.com", "https://checkip.amazonaws.com"]` | Ordered list of services that return the agent's public IP. Tried in sequence at startup and on every check; first success wins. Required for agents behind NAT or in containers. Set to `[]` to disable external lookups (air-gapped deployments) |
| `interval_secs`    | u64       | `300`                                                                                                           | IP check interval in seconds (default 5 minutes)                                                                                                                                                                                                   |

### `[security]` -- Security Event Detection [#security----security-event-detection]

| Key                                 | Type   | Default                         | Description                                                        |
| ----------------------------------- | ------ | ------------------------------- | ------------------------------------------------------------------ |
| `enabled`                           | bool   | `true`                          | Enable local security-event detection                              |
| `data_dir`                          | string | `"/var/lib/serverbee/security"` | Writable directory for detector state                              |
| `ssh.window_seconds`                | u32    | `60`                            | Sliding window for failed SSH-login detection                      |
| `ssh.failed_threshold`              | u32    | `10`                            | Failed SSH attempts in the window before reporting an event        |
| `port_scan.enabled`                 | bool   | `false`                         | Enable local port-scan detection                                   |
| `port_scan.window_seconds`          | u32    | `30`                            | Sliding port-scan detection window                                 |
| `port_scan.distinct_port_threshold` | u32    | `20`                            | Distinct destination ports in the window before reporting an event |

### `[log]` -- Logging [#log----logging-1]

| Key     | Type   | Default  | Description                                              |
| ------- | ------ | -------- | -------------------------------------------------------- |
| `level` | string | `"info"` | Log verbosity: `trace`, `debug`, `info`, `warn`, `error` |
| `file`  | string | `""`     | Path to log file. If empty, logs go to stdout only       |

### `[upgrade]` -- Upgrade Source (Agent) [#upgrade----upgrade-source-agent]

The agent downloads upgrades from a locally-pinned release source rather than trusting a URL from the server.

| Key                        | Type   | Default                                                   | Description                                                                                                                                                                                                                                                                                                                               |
| -------------------------- | ------ | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `release_repo_url`         | string | `"https://github.com/ZingerLittleBee/ServerBee/releases"` | Base URL for agent upgrade release assets. Must replicate the GitHub releases directory layout: `{base}/download/v{version}/{asset}` for binaries and `{base}/download/v{version}/sha256sums.txt` for checksum verification. The compile-time default is overridable via the `SERVERBEE_RELEASE_REPO` build-time env var                  |
| `release_cert_spki_sha256` | string | `""`                                                      | Optional TLS SPKI pin for the release host. Set to 64 lowercase hex characters (SHA-256 of the leaf certificate's SubjectPublicKeyInfo DER encoding). Empty disables pinning. If set, the agent additionally validates the leaf cert SPKI after standard chain validation. Invalid format (non-64-char or non-hex) is rejected at startup |

**Configuration precedence** (highest wins):

1. `--release-repo` CLI flag
2. `SERVERBEE_UPGRADE__RELEASE_REPO_URL` environment variable
3. `/etc/serverbee/agent.toml` or `agent.toml` `[upgrade]` section
4. Compile-time default (official GitHub releases URL)

<Callout type="info">
  The dashboard "latest version" check uses the Server-configured release source (`upgrade.release_base_url` / `upgrade.latest_version_url`). Those are separate Server-side settings used only for the dashboard's "latest version" lookup, and are distinct from the Agent's `[upgrade] release_repo_url`, which governs what the Agent actually downloads. For consistent upgrade behavior, point both the Server and the Agent at the same release repository unless you intentionally want them to track different sources.
</Callout>

**How to obtain the SPKI pin** for a release host certificate:

```bash
openssl x509 -in cert.pem -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256 -r | awk '{print $1}'
```

***

## Example: Minimal Server Configuration [#example-minimal-server-configuration]

```toml
[server]
data_dir = "./data"
```

Everything else uses sensible defaults. On first startup, ServerBee creates the `admin` user with a random password and prints it once to the server logs.

## Example: Production Server Configuration [#example-production-server-configuration]

```toml
[server]
listen = "127.0.0.1:9527"
data_dir = "/var/lib/serverbee"

[auth]
secure_cookie = true

[retention]
records_days = 14
records_hourly_days = 180

[geoip]
mmdb_path = "/var/lib/serverbee/GeoLite2-City.mmdb"

[asn]
mmdb_path = "/var/lib/serverbee/GeoLite2-ASN.mmdb"

[log]
level = "info"
file = "/var/log/serverbee/server.log"

[oauth]
base_url = "https://monitor.example.com"
allow_registration = false

[oauth.github]
client_id = "Iv1.abc123"
client_secret = "secret123"
```

## Example: Minimal Agent Configuration [#example-minimal-agent-configuration]

```toml
server_url = "http://your-server-ip:9527"
enrollment_code = "<one-time code from Add Server>"
```

## Example: Production Agent Configuration [#example-production-agent-configuration]

```toml
server_url = "https://monitor.example.com"
token = "<agent-generated persisted token>"

[collector]
enable_gpu = true  # Requires a GPU-enabled build and an NVIDIA driver that provides NVML
enable_temperature = true

[file]
enabled = true
root_paths = ["/home", "/var/log", "/etc"]
max_file_size = 1073741824
deny_patterns = ["*.key", "*.pem", "id_rsa*", ".env*", "shadow", "passwd"]

[ip_change]
enabled = true
# external_ip_urls defaults to a curated list of public IP services.
# Override only to point at internal mirrors or to disable (set to []).

[log]
level = "info"
file = "/var/log/serverbee/agent.log"
```
