> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# 配置说明

CBCTF 从内置默认值和 `config.yaml` 读取配置。Helm 会把 values 渲染成 `/app/config.yaml`，优先级高于内置默认值。

启动前请准备可读的配置文件，默认路径为 `config.yaml`，也可通过 `-c <文件>` 指定。使用 Helm 时通过 values 配置；应用设置不支持用环境变量覆盖。

以下项目需通过部署配置修改：

- PostgreSQL/GORM 配置：`gorm.*`
- Redis 连接信息：`redis.*`
- 数据存储目录：`path`
- Gin 监听地址和端口：`gin.host`、`gin.port`
- 运行时共享 PVC：`k8s.shared_volume_claim`（空值回退到 `{namespace}-shared-volume`）

可在线修改的运行设置在首次启动时采用配置文件中的初始值，之后通过「系统管理」维护。升级 Helm values 不会覆盖已经保存的在线设置，在线修改也不会写回配置文件。

数据库和任务日志级别分别使用 `gorm.log.level`、`asynq.log.level`。平台日志的查看与长期留存见[监控与日志](/admin/monitoring.md)。

## 保存与生效

在「系统管理」保存后，不同设置的生效时机如下：

| 设置                                              | 生效时机                                 |
| ----------------------------------------------- | ------------------------------------ |
| 注册开关、默认分组、公开地址、Webhook/作弊白名单                    | 当前平台实例的后续操作使用新值                      |
| 抓包开关、worker 镜像、生成器池容量、FRP 镜像等                   | 后续新建工作负载使用；已有实例不自动重建                 |
| Gin 模式、可信代理、CORS、上传限制、全局限流；任务并发；Kubernetes 命名空间 | 需要在后台执行「重启」                          |
| 固定部署配置                                          | 修改文件/values 后重新创建 Pod；后台重启不会重新读取配置文件 |

多副本部署需要让各副本重新加载配置。迁移命名空间时，请同时准备目标命名空间的授权、PVC，并安排已有靶机与生成器的清理；Helm 部署通常使用 Release 所在命名空间。

图片、题目附件和题解分别通过 `gin.upload.picture`、`gin.upload.challenge`、`gin.upload.writeup` 设置大小上限。

## 常用配置项

| 配置项                          | 说明                                         | 示例                          |
| ---------------------------- | ------------------------------------------ | --------------------------- |
| `host`                       | 平台对外访问地址，用于根路径跳转、邮件链接、OAuth 回调等，不要带尾部 `/`  | `https://ctf.example.com`   |
| `path`                       | 数据根目录，存放附件、动态附件、流量文件、GeoIP 数据库等            | `./data`                    |
| `gin.mode`                   | Gin 模式                                     | `release`                   |
| `gin.host`                   | HTTP 监听地址                                  | `0.0.0.0`                   |
| `gin.port`                   | HTTP 监听端口                                  | `8000`                      |
| `gin.proxies`                | 可信代理 IP 或 CIDR                             | `10.244.0.0/16`             |
| `gin.upload.picture`         | 图片上传大小限制，单位 MiB                            | `8`                         |
| `gin.upload.challenge`       | 题目附件上传大小限制，单位 MiB                          | `8`                         |
| `gin.upload.writeup`         | 题解上传大小限制，单位 MiB                            | `8`                         |
| `gin.ratelimit.global`       | 全局每分钟限流                                    | `100`                       |
| `gin.ratelimit.whitelist`    | 跳过限流的 IP 或 CIDR                            | `127.0.0.1`                 |
| `gin.origins`                | 允许的浏览器请求 Origin，用于跨域请求与认证 cookie 判断        | `https://ctf.example.com`   |
| `gin.jwt.secret`             | JWT 签名密钥，生产环境必须替换默认值                       | `change-me-long-random`     |
| `gin.metrics.whitelist`      | 允许访问 `/metrics` 的 IP 或 CIDR                | `10.0.0.0/8`                |
| `gin.pprof.whitelist`        | 允许访问 `/debug/pprof/*` 的 IP 或 CIDR          | `127.0.0.1`                 |
| `gorm.postgres.host`         | PostgreSQL 地址                              | `postgres.cbctf.svc`        |
| `gorm.postgres.port`         | PostgreSQL 端口                              | `5432`                      |
| `gorm.postgres.user`         | PostgreSQL 用户名                             | `cbctf`                     |
| `gorm.postgres.pwd`          | PostgreSQL 密码                              | `example-postgres-password` |
| `gorm.postgres.db`           | PostgreSQL 数据库名                            | `cbctf`                     |
| `gorm.postgres.sslmode`      | 布尔值，`false` 为 `disable`，`true` 为 `require` | `false`                     |
| `redis.host`                 | Redis 地址                                   | `redis.cbctf.svc`           |
| `redis.port`                 | Redis 端口                                   | `6379`                      |
| `redis.pwd`                  | Redis 密码                                   | `example-redis-password`    |
| `registration.enabled`       | 是否允许公开注册                                   | `true`                      |
| `registration.default_group` | 新用户默认分组 ID，`0` 表示不指定                       | `0`                         |

## 异步任务配置

Redis 同时用于缓存和 Asynq 任务队列。以下配置影响后台任务并发：

| 配置项                       | 说明               | 示例        |
| ------------------------- | ---------------- | --------- |
| `asynq.log.level`         | Asynq 日志级别       | `warning` |
| `asynq.queues.victim`     | 靶机启动、停止各自的任务并发   | `8`       |
| `asynq.queues.traffic`    | 靶机流量解析任务并发       | `2`       |
| `asynq.queues.generator`  | 动态附件生成器启停任务并发    | `3`       |
| `asynq.queues.attachment` | 附件 worker 分发并发上限 | `32`      |
| `asynq.queues.email`      | 邮件任务并发           | `10`      |
| `asynq.queues.webhook`    | Webhook 任务并发     | `15`      |
| `asynq.queues.image`      | 图片处理任务并发         | `10`      |

当靶机启动、附件生成或邮件发送堆积时，先检查 Redis 状态和任务日志，再根据资源情况调整对应队列并发。

## Kubernetes 配置

| 配置项                       | 说明                                   | 示例                                  |
| ------------------------- | ------------------------------------ | ----------------------------------- |
| `k8s.namespace`           | 靶机、生成器等资源所在命名空间                      | `cbctf`                             |
| `k8s.shared_volume_claim` | 平台和运行时工作负载共用的 PVC；部署参数，后台不修改         | `cbctf-data`                        |
| `k8s.capture`             | 流量捕获 sidecar 镜像                      | `ghcr.io/domcyrus/rustnet:latest`   |
| `k8s.capture_enabled`     | 是否创建抓包容器及相关挂载                        | `true`                              |
| `k8s.priority_class_name` | 普通 Pod 使用的已有 PriorityClass，当前不应用到 VM | `""`                                |
| `k8s.worker_image`        | 含 `/app/worker` 的独立 worker 镜像        | `ghcr.io/0rays/cbctf-worker:latest` |
| `k8s.generator_pool_size` | 每比赛、每动态题的 generator 目标池容量            | `2`                                 |
| `k8s.frp.on`              | 是否启用 FRP 暴露靶机端口                      | `false`                             |
| `k8s.frp.frpc`            | FRP client 镜像                        | `ghcr.io/fatedier/frpc:v0.69.0`     |
| `k8s.frp.nginx`           | FRP 辅助 Nginx 镜像                      | `nginx:latest`                      |
| `k8s.frp.frps`            | FRPS 地址、端口、token、端口池                 | `host: frps.example.com`            |

抓包开关、Pod PriorityClass、worker 镜像和生成器池容量均可在「系统管理 → Kubernetes 配置」中查看和修改，保存到数据库后供后续新建实例及补池使用。已有实例不会自动重建或缩容，其他平台副本需重新加载配置。

预热、调度、缓存与回收机制见[工作负载调度](/deploy/workloads.md)。启用 FRP 时使用 ClusterIP，否则使用 NodePort。

## Helm 与配置文件的关系

Helm 会把以下值渲染进 ConfigMap：

| Values                   | 说明       |
| ------------------------ | -------- |
| `cbctf.gin.jwt.secret`   | JWT 签名密钥 |
| `postgres.auth.password` | 数据库密码    |
| `redis.auth.password`    | Redis 密码 |

上述值保存在应用配置 ConfigMap 中，请妥善限制其访问权限。镜像仓库拉取凭据另由 Secret 管理。

## 首次启动行为

- 自动准备平台所需的数据表和初始设置
- 提供默认品牌、角色、分组、定时任务和第三方登录配置
- 管理员组中没有用户时，创建 `admin` 账号并在日志中输出初始密码；首次登录后请修改密码

## 在线配置

管理后台会展示固定部署参数；PostgreSQL/GORM、Redis、数据目录、Gin 监听地址和监听端口只能通过部署配置修改。

GeoLite2-City 数据库可通过管理后台上传，保存到 `{path}/GeoLite2-City.mmdb`。

固定部署参数修改后需要重新创建 Pod。`registration.default_group: 0` 表示不指定注册用户组；应先到 RBAC 页面查看实际分组 ID，再选择普通用户分组，避免新用户没有参赛权限。

## 安全配置建议

:::warning

- 生产环境不要使用默认 `gin.jwt.secret`
- 数据库、Redis、SMTP、OAuth、FRP token 使用强密码或随机密钥
- `host`、Ingress 域名应与用户访问地址一致，`gin.origins` 应包含前端页面的实际 `Origin`
- 部署在反向代理后时正确设置 `gin.proxies`
- `/metrics` 只允许 Prometheus 或可信来源访问
- 只将必要的目标加入 `webhook.whitelist`
  :::
