# Server 安装配置

> ServerBee 服务端的安装、配置和运维指南。

URL: https://docs.serverbee.app/zh/docs/server

Server 是 ServerBee 的核心组件，负责接收 Agent 上报的数据、存储历史指标、评估告警规则、提供 Web 管理面板和 API 接口。

## 安装方式 [#安装方式]

### 安装脚本（推荐） [#安装脚本推荐]

最省事的方式是一键安装脚本。二进制模式会自动检测架构、下载二进制、生成配置、注册并启动 systemd 或 OpenRC 服务，并软链 `serverbee` 管理 CLI。Server 支持两种快速安装：

```bash
# 方式一：用 IP 安装（明文 HTTP），访问 http://<服务器IP>:9527
curl -fsSL https://raw.githubusercontent.com/ZingerLittleBee/ServerBee/main/deploy/install.sh | sudo sh -s -- server --method binary -y

# 方式二：用域名安装（自动 Caddy + HTTPS），访问 https://你的域名
curl -fsSL https://raw.githubusercontent.com/ZingerLittleBee/ServerBee/main/deploy/install.sh | sudo sh -s -- server \
  --method binary \
  --domain monitor.example.com --email admin@example.com -y
```

脚本安装后的目录布局：二进制在 `/opt/serverbee/bin/`，配置在 `/opt/serverbee/etc/server.toml`，数据在 `/opt/serverbee/data/`，管理 CLI 软链为 `/usr/local/bin/serverbee`。完整步骤见[快速安装](/zh/docs/quick-start)。

### 二进制安装（手动） [#二进制安装手动]

从 [GitHub Releases](https://github.com/ZingerLittleBee/ServerBee/releases) 下载对应平台的预编译二进制并自行运行：

```bash
chmod +x serverbee-server
./serverbee-server
```

### Docker [#docker]

```bash
docker run -d \
  --name serverbee-server \
  -p 9527:9527 \
  -v serverbee-data:/data \
  -e MALLOC_ARENA_MAX=2 \
  ghcr.io/zingerlittlebee/serverbee-server:1.0.0-beta.4
```

### 源码编译 [#源码编译]

```bash
# 先构建前端（会嵌入到 Server 二进制中）
cd apps/web && bun install && bun run build && cd ../..

# 构建 Server
cargo build --release -p serverbee-server
```

## 配置文件 [#配置文件]

Server 按以下顺序读取 TOML 配置，靠后的来源会覆盖靠前的：

1. `/etc/serverbee/server.toml`（系统级）
2. `server.toml`（工作目录）
3. 以 `SERVERBEE_` 为前缀的环境变量

<Callout type="info">
  通过安装脚本部署时，配置文件位于 `/opt/serverbee/etc/server.toml`，数据目录为 `/opt/serverbee/data/`（脚本会显式写入这些路径，覆盖下方的内置默认值）。`/etc/serverbee`、`/var/lib/serverbee` 是旧版布局，仅在历史安装中出现，脚本会自动迁移。
</Callout>

下面的 `server.toml` 列出最常用的配置项及其默认值。完整选项见[配置参考](/zh/docs/configuration)。

```toml
[server]
listen = "0.0.0.0:9527"        # 监听地址和端口
data_dir = "./data"            # 数据库及其他数据文件的存储目录
trusted_proxies = []           # 默认为内网/回环 CIDR；设为 [] 表示禁用

[database]
path = "serverbee.db"          # 数据库文件名（相对于 data_dir）
max_connections = 10           # SQLite 连接池最大连接数

[auth]
session_ttl = 86400            # Session 过期时间，单位秒（默认 24 小时）
max_servers = 0                # 新接入服务器的软上限（0 表示不限制）
secure_cookie = true           # 是否给 Session Cookie 设置 Secure 标记（纯 HTTP 本地调试需关闭）

[retention]
records_days = 7               # 分钟级指标保留天数
records_hourly_days = 90       # 小时级聚合指标保留天数
gpu_records_days = 7           # GPU 指标保留天数
ping_records_days = 7          # Ping 探测记录保留天数
audit_logs_days = 180          # 审计日志保留天数
network_probe_days = 7         # 网络探测记录保留天数
network_probe_hourly_days = 90 # 小时级网络探测聚合保留天数
traffic_hourly_days = 7        # 流量小时记录保留天数
traffic_daily_days = 400       # 流量日记录保留天数
task_results_days = 7          # 任务执行结果保留天数
docker_events_days = 7         # Docker 事件记录保留天数
service_monitor_days = 30      # 服务监控记录保留天数

[rate_limit]
login_max = 5                  # 每个时间窗口内最大登录尝试次数
register_max = 10              # 每个窗口内最大 Agent 注册尝试次数（Railway 覆盖为 3）

[scheduler]
timezone = "UTC"               # 每日流量聚合所用时区（如 Asia/Shanghai）

[log]
level = "info"                 # 日志级别：trace / debug / info / warn / error
file = ""                      # 日志文件路径（留空仅输出到 stdout）

[upgrade]
release_base_url = "https://github.com/ZingerLittleBee/ServerBee/releases"  # Agent 升级的基础 URL

[geoip]
mmdb_path = ""                 # MaxMind GeoLite2-City.mmdb 路径（非空即启用 GeoIP）

[oauth]
base_url = ""                  # ServerBee 实例的公网 URL
allow_registration = false     # 是否允许首次 OAuth 登录时自动创建用户

[oauth.github]
client_id = ""
client_secret = ""

[oauth.google]
client_id = ""
client_secret = ""

[oauth.oidc]
issuer_url = ""
client_id = ""
client_secret = ""
scopes = ["openid", "email", "profile"]
```

## 环境变量 [#环境变量]

每个配置项都可以通过环境变量设置：前缀 `SERVERBEE_`，层级用 `__`（双下划线）分隔。环境变量的优先级高于配置文件。

```bash
# server.listen
export SERVERBEE_SERVER__LISTEN="0.0.0.0:9527"

# retention.records_days
export SERVERBEE_RETENTION__RECORDS_DAYS=14

# oauth.github.client_id
export SERVERBEE_OAUTH__GITHUB__CLIENT_ID="your-github-client-id"

# geoip.mmdb_path（路径非空即启用 GeoIP）
export SERVERBEE_GEOIP__MMDB_PATH="/path/to/GeoLite2-City.mmdb"
```

## 数据库 [#数据库]

ServerBee 使用 SQLite 存储所有持久化数据。首次启动时会自动在 `data_dir` 下创建数据库文件。

以下 SQLite pragma 会自动设置：

| Pragma         | 取值     | 作用             |
| -------------- | ------ | -------------- |
| `journal_mode` | WAL    | 提高并发读性能        |
| `synchronous`  | NORMAL | 兼顾安全性与速度       |
| `busy_timeout` | 5000ms | 数据库被锁时最多等待 5 秒 |
| `foreign_keys` | ON     | 强制外键引用完整性      |

启动时自动运行数据库迁移，无需手动维护表结构。

## 初始管理员账户 [#初始管理员账户]

Server 首次启动时，如果 `users` 表为空，会自动创建管理员账户。这里没有用户名/密码环境变量：密码始终随机生成，并以醒目的凭据横幅在 Server/容器日志中打印一次。

```
========================================
  ServerBee initial admin credentials
  Username: admin
  Password: aB3xK9mP2qR5
========================================
```

请从日志中获取该密码。首次登录时你将被要求修改它，并可在此时选择一个新的用户名。

<Callout type="warn">
  自动生成的密码只在日志中显示一次。请在日志轮转前记录下来，并在首次登录时完成强制改密，再将 Server 暴露到公网。
</Callout>

## Agent 接入 [#agent-接入]

添加 Server 是一个幂等的 onboarding 操作。`POST /api/servers` 必须携带 `onboarding_request_id`，并在同一个事务中创建 Server 配置、标签、默认探测目标、Agent Authority 事件和一个绑定到该 Server 的 enrollment offer。使用相同 request ID 和相同输入重试会返回已有 Server。重放响应绝不会再次返回明文 code，但可以标识当前 outstanding offer，管理员随后可精确替换该 offer。

Enrollment offer 绑定到具体 Server，单次使用且短时有效（默认 10 分钟）。它的终态只有 `consumed`、`revoked`、`replaced` 和 `expired`，进入终态后不能恢复为 outstanding。明文 code 仅在新建或替换 offer 时返回一次。

Agent 在 claim offer 前自行生成并持久化 run token，然后通过 `POST /api/agent/register` 提交 proposed token。Server 只保存哈希，并且只返回 `server_id`。如果 HTTP 结果不明确，Agent 会先用已暂存的 token 尝试 WebSocket，再决定是否重新 claim。

Server 的 `agent_authority.status` 只有 `claimed` 与 `unclaimed`，它与 Agent 当前是否在线相互独立。Server 详情 API 和 UI 会展示 Agent Authority 状态及 outstanding offer。你可以用 `auth.max_servers` 限制新 Server onboarding，并用 **Clean up unconnected** 清理从未初始化的离线占位条目。

## 重新接入与吊销 [#重新接入与吊销]

已 claimed 的 Agent 需要更换 run token 时，在 Server 详情页使用 **Agent 重新接入**：

1. **Graceful** 保留现有 authority，同时发出 enrollment offer。新 claim 完成前，当前 Agent 可继续运行。
2. **Emergency** 立即吊销现有 authority、隔离旧连接，并在同一状态转换中发出 enrollment offer。

每个 Server 同时最多有一个 outstanding offer。替换或吊销必须指定界面中可见的准确 offer ID，过期页面因此不能覆盖较新的 offer。吊销 Agent Authority 是独立的破坏性操作，它会使当前 run token 失效并断开 Agent，但不会顺手生成新 offer。

所有 Agent Authority 状态转换都会记录不含密钥的事件。即使 Server 记录已删除，历史事件仍会保留。

## GeoIP 设置 [#geoip-设置]

启用 Agent 地理位置识别：

1. 下载免费的 [MaxMind GeoLite2-City](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data) MMDB 数据库（需要免费的 MaxMind 账号）
2. 将 `GeoLite2-City.mmdb` 文件放到服务器上的某个可访问路径
3. 在配置中启用：

```toml
[geoip]
mmdb_path = "/path/to/GeoLite2-City.mmdb"
```

启用后，Agent 连接时 Server 会自动把其 IP 解析为所在地区和国家代码。

## OAuth 设置 [#oauth-设置]

ServerBee 支持通过 GitHub、Google 以及任意 OpenID Connect 提供商进行第三方登录。

### 前置条件 [#前置条件]

把 `oauth.base_url` 设为 ServerBee 实例的公网 URL，用于拼接回调地址：

```toml
[oauth]
base_url = "https://serverbee.example.com"
allow_registration = true  # 设为 true 时，首次 OAuth 登录会自动创建账户
```

### GitHub [#github]

1. 前往 [GitHub Developer Settings](https://github.com/settings/developers) 创建一个 OAuth App
2. 回调地址设为 `https://serverbee.example.com/api/auth/oauth/github/callback`
3. 把凭据填入配置：

```toml
[oauth.github]
client_id = "your-client-id"
client_secret = "your-client-secret"
```

### Google [#google]

1. 在 [Google Cloud Console](https://console.cloud.google.com/apis/credentials) 创建 OAuth 凭据
2. 回调地址设为 `https://serverbee.example.com/api/auth/oauth/google/callback`
3. 把凭据填入配置：

```toml
[oauth.google]
client_id = "your-client-id"
client_secret = "your-client-secret"
```

### 通用 OIDC [#通用-oidc]

适用于任意 OpenID Connect 提供商（如 Keycloak、Authentik、Authelia）：

```toml
[oauth.oidc]
issuer_url = "https://auth.example.com/realms/main"
client_id = "serverbee"
client_secret = "your-client-secret"
scopes = ["openid", "email", "profile"]
```

## 反向代理 [#反向代理]

<Callout type="info">
  不想手动配反向代理的话，安装脚本可以全自动完成这件事：安装时加 `--domain monitor.example.com --email admin@example.com`，或对已装好的 Server 执行 `sudo serverbee domain setup --domain monitor.example.com --email admin@example.com`。脚本会校验 DNS、装好 Caddy、写 Caddyfile 并签发 HTTPS 证书，同时把 `auth.secure_cookie` 设为 `true`。下面的手动配置仅在你想自己掌控反向代理时才需要。
</Callout>

在反向代理后运行时，必须正确转发 WebSocket 连接。

### Nginx [#nginx]

```nginx
server {
    listen 443 ssl http2;
    server_name serverbee.example.com;

    ssl_certificate     /etc/ssl/certs/serverbee.pem;
    ssl_certificate_key /etc/ssl/private/serverbee.key;

    location / {
        proxy_pass http://127.0.0.1:9527;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}
```

<Callout type="info">
  较大的 `proxy_read_timeout` 和 `proxy_send_timeout` 对 WebSocket 连接很重要。不配置的话，Nginx 可能过早关闭空闲连接，导致 Agent 和终端会话断开。
</Callout>

### Caddy [#caddy]

Caddy 会自动处理 HTTPS 证书和 WebSocket 代理，配置更加简洁：

```txt title="Caddyfile"
monitor.example.com {
    reverse_proxy 127.0.0.1:9527
}
```

配置反向代理后，Agent 应使用 `https://` 协议连接：

```toml title="agent.toml"
server_url = "https://monitor.example.com"
```

更多反向代理配置（含 Traefik）请参阅[部署指南](/zh/docs/deployment)。

## 后台任务 [#后台任务]

Server 会自动运行多个后台任务：

| 任务             | 间隔  | 作用                    |
| -------------- | --- | --------------------- |
| RecordWriter   | 60s | 把缓存的 Agent 上报写入数据库    |
| OfflineChecker | 10s | 检测停止上报的 Agent（30s 阈值） |
| Aggregator     | 每小时 | 将原始记录聚合为小时级汇总         |
| Cleanup        | 每小时 | 按保留策略清理过期记录           |
| SessionCleaner | 定期  | 清理过期的用户 Session       |
| AlertEvaluator | 60s | 评估所有启用的告警规则           |

所有任务自动启动，无需手动配置。

<Cards>
  <Card title="Agent 安装配置" href="/zh/docs/agent" />

  <Card title="完整配置参考" href="/zh/docs/configuration" />

  <Card title="部署指南" href="/zh/docs/deployment" />
</Cards>
