配置系统
要改端口、开关插件、换数据库时,你会碰到两份配置文件。先记住:
config.yaml:框架全局配置(数据库、日志、安全、插件目录等),首次启动自动生成;core_plugins.yaml:官方插件配置中心,集中管理core_plugins/下每个官方插件的开关与配置。
也可以在启动时传入自定义的全局配置路径:python main.py /path/to/config.yaml。
修改后是否要重启,取决于改的是哪一段(Web 后台保存时会直接告诉你):
| 配置段 | 生效方式 |
|---|---|
log | 即时生效(日志级别当场切换) |
framework.blackbox | 即时生效(开关与内存上限) |
security.rate_limit | 即时生效(限速器按新参数重建);蜜罐 / 人机验证仍需重启 |
plugin.hot_reload | 即时生效;plugin.heartbeat_interval 需重启 |
database / web / onebot / ssl / event_queue / observability 等 | 需重启(连接、端口、证书、路由在启动时创建) |
PUT /api/config/yaml/<section> 的响应里带 data.notes(已即时生效的项)与 data.restart_required,细节见可观测性与运维接口。
官方插件配置中心 core_plugins.yaml(重点)
先记住一句话:开关看 core_plugins.yaml,参数看 config.yaml。
| 你要改什么 | 改哪个文件 |
|---|---|
插件启用/禁用(enabled) | core_plugins.yaml(唯一权威) |
| WebUI 端口/监听地址 | config.yaml 的 web: 段 |
| OneBot 端口/接入令牌 | config.yaml 的 onebot: 段 |
http_api / http_inject 的地址端口令牌 | config.yaml 的对应段 |
| 各接入端的凭证(telegram token、discord token…) | core_plugins.yaml 的插件块 |
判定口径很简单:config.yaml 里已经有同名键的,以 config.yaml 为准;core_plugins.yaml 只补 config.yaml 没有的键。
启动时平台内核会自动同步(见 framework/config.py 的 _autoload_core_plugins):
- 扫描
core_plugins/目录,得到"已安装"的官方插件; - 为已安装但 yaml 里缺失的插件补上默认配置块(
enabled一律 false,发现即禁用); - 收敛重叠键:
config.yaml已有同名键的,从core_plugins.yaml中删除, 并在日志里写明"已收敛到 config.yaml 的 X 段"——两处都能改、只有一处生效是最大的坑; - 删除 yaml 里已经不再安装的插件块(卸载后配置块自动消失);
- 有变化就自动回写
core_plugins.yaml(无需手动维护); - 把每个插件的
enabled合并进config['core_plugins'],把插件私有键合并进对应段。
因此代码里既有的 fw.config.get('onebot')、fw.config.get('web') 等读法保持不变,对插件透明。
一份开箱即用的 core_plugins.yaml 形如(只放开关和插件私有键):
core_plugins:
onebot_adapter:
enabled: false # 端口/令牌在 config.yaml 的 onebot 段
webui:
enabled: false # 端口/监听地址在 config.yaml 的 web 段
session:
enabled: false # 默认关闭,需改为 true 启用;多轮会话(ctx.wait_for/create_session)
scheduler:
enabled: false # 默认关闭,需改为 true 启用;定时任务(ctx.task)
http_inject: # 参数在 config.yaml 的 http_inject 段
enabled: false
ws_client: # 出站 WebSocket 接入端(默认关闭,外连安全)
enabled: false
url: ws://127.0.0.1:9000/ws
bot_name: ws_client
token: ''
reconnect_interval: 5 # 断线重连的初始间隔;之后逐次翻倍
reconnect_max_interval: 60 # 退避上限
reconnect_jitter: 0.25 # 抖动比例,错开多实例的重试时刻
max_queue: 256
qq_official: # QQ 官方机器人(默认关闭,需 AppID/AppSecret)
enabled: false
app_id: ''
app_secret: ''
bot_name: qq_official
intents: 100663296 # QQ 官方默认意图(群/单聊等事件)
reconnect_interval: 5
telegram: # Telegram(默认关闭,需 Bot Token)
enabled: false
token: ''
bot_name: telegram
polling_timeout: 30
discord: # Discord(默认关闭,需 Bot Token)
enabled: false
token: ''
bot_name: discord
intents: 37377 # GUILDS|GUILD_MESSAGES|DIRECT_MESSAGES|MESSAGE_CONTENT
reconnect_interval: 5
http_api: # 参数在 config.yaml 的 http_api 段
enabled: false把某个插件的 enabled 改为 true 即启用,重启后生效。关闭某个服务后,依赖它的能力 (如会话、定时、API 调用)会不可用。默认开启的只有 echo / help / scheduler / webui 四个(见 DEFAULT_ENABLED_CORE_PLUGINS);其余官方插件默认关闭,需要哪个就把对应 enabled 改为 true。其中 http_api、http_inject、ws_client、 qq_official、telegram、discord 涉及开端口、凭证或主动外连,更需注意安全,需显式开启。
提示:旧版本把开关写在
config.yaml → core_plugins的写法仍能被识别(向后兼容,首次合并时迁移), 但开关请统一写到core_plugins.yaml;端口/令牌这类参数请写到config.yaml。
协议接入(OneBot 11,来自 onebot_adapter)
开关在 core_plugins.yaml,端口与令牌在 config.yaml 的 onebot: 段——分两处,各管各的:
# core_plugins.yaml —— 只管开关
core_plugins:
onebot_adapter:
enabled: true
# config.yaml —— 管运行参数
onebot:
listen_host: 0.0.0.0 # 反向 WebSocket 监听地址
listen_port: 6830 # WebSocket 服务端端口(等 OneBot 实现端反向连入)
access_token: "" # 接入令牌,公网部署必须设置非空强随机值如果你在
core_plugins.yaml的onebot_adapter块里写了listen_port, 它会在启动时被移出并提示"已收敛到 config.yaml 的 onebot 段"——以config.yaml为准。
ZCBOT 作为 WebSocket 服务端,由 NapCat / Lagrange 等 OneBot 实现端反向连接。 客户端怎么配、连接怎么验证、插件里怎么发图片 / @ / 做群管,见 对接 IM 平台。 不用 OneBot 时可整体关闭该插件,改用 http_inject / scheduler 或自写接入端, 见 最佳实践。
Web 管理后台(来自 webui)
# core_plugins.yaml → core_plugins.webui(合并后主配置段为 web)
web:
host: 127.0.0.1 # 监听地址;0.0.0.0 = 监听所有网卡(公网可访问,务必配合令牌/白名单)
port: 8080 # 监听端口
session_timeout: 3600 # 登录会话超时时长(秒),同时也是会话 Token 有效期
enabled: false # 由 core_plugins.webui.enabled 合并而来(默认 false)
official_sidebar: true # 是否显示官方默认侧边栏菜单
sidebar: # 自定义左侧栏(也可在后台「设置 → 侧边栏」调整)
order: [] # 官方菜单显示顺序(键名,留空用默认顺序)
hidden: [] # 隐藏的官方菜单项(键名)后台 REST 接口(/api/**)与后台页面共用这个端口;另有独立的 http_api 插件(默认 1145、默认关闭)用于对外集成,两者区别见 README「接口令牌」一节。
左侧栏支持自定义显示:官方项用 web.sidebar(或后台「设置 → 侧边栏」)选择显示/隐藏并调整顺序; 插件用 ctx.webui(..., sidebar=True) 注册的入口会自动出现在侧边栏。
SSL / TLS(HTTPS / WSS)
开启后 Web 管理后台走 https、OneBot 反向 WS 走 wss(两者共用同一份证书):
ssl:
enabled: false
cert: "" # 证书链文件;支持绝对路径,或相对项目根目录(如 certs/fullchain.pem)
key: "" # 私钥文件;同上- 证书路径支持相对(相对
config.yaml所在目录)与绝对两种写法。 - 也可在后台「设置 → SSL / TLS」中修改并保存;改动需重启框架生效。
- 后台页面按当前协议自动显示接入地址(https →
wss://),见「连接设置」页。 - 启用 SSL 后 Web 后台由 werkzeug 提供 TLS(waitress 本身不支持 TLS);未启用时仍用 waitress。
独立对外 HTTP API(来自 http_api,默认关闭)
先在 core_plugins.yaml 把 http_api.enabled 置为 true:
core_plugins:
http_api:
enabled: true
host: 127.0.0.1 # 仅本机访问更安全
port: 1145 # HTTP API 端口
token: "" # 调用令牌;留空则首次自动生成
allow_db: false # 是否开放数据库网关 db/query、db/execute(默认关闭)权限说明:HTTP API 用单一共享 token 认证(
?token=xxx),allow_db: true后db/query/db/execute可执行任意 SQL(含写库/删表),没有表级或角色级粒度。默认关闭; 确有需要时再开启,并务必:① 固定token;② 仅绑定内网host;③ 尽量用只读账号/反向代理限权。
数据库(config.yaml)
# SQLite(默认,零配置,数据落在单文件)
# 注意:仅适合小环境与开发环境;多群/高并发/多进程等大环境请用下方 MySQL
database:
type: sqlite
path: data/zcbot.db
# MySQL(大环境推荐:多群、高并发、多进程部署)
database:
type: mysql
host: 127.0.0.1
port: 3306
user: root
password: ""
database: zcbot选型提醒:sqlite 是给小环境/开发环境用的默认值,不适合大环境; 上生产、群多了、并发高了就切 mysql。详见 数据库。
插件 SQL 统一写 %s 占位、AUTOINCREMENT 自增,平台内核自动适配方言, 详见 数据库。
插件相关(config.yaml)
plugin:
dir: plugins # 用户插件代码目录
heartbeat_interval: 60 # 心跳间隔(秒):检测文件变化并重跑 register
auto_install_deps_on_startup: true # 启动/加载时自动安装插件缺失依赖
max_memory_mb: 64 # 单插件估算内存上限(MB),连续超限自动卸载心跳 ≠ 完全重载
心跳只对改动过的插件重新执行 register(ctx),不会重新 import 代码。 修改了函数体逻辑后,请在 Web 面板点「重载」走 unload + load, 原理见 插件加载与模块机制。
终端交互与运维面板(config.yaml)
框架内置交互式终端(stdin)与运维面板命令 tui(原 core_plugins/ops 官方插件已删除, 能力全部内置)。终端命令 restart / reload(rl) / shell(sh) / dbdump / tui 无需任何插件即可用。
terminal:
enabled: true # false = 不启动终端交互(stdin 非 TTY 时本会自动跳过)
panel_autostart: false # 框架启动后自动进入 tui 面板(退出后回到普通终端)
panel_refresh: 1.0 # 面板刷新间隔(秒,最小 0.2)
panel_default_view: monitor # 面板初始页:monitor/overview/plugins/messages/system
# 运维命令行为(可选,缺省即生效)
ops:
shell_timeout: 10 # shell 命令超时(秒)
max_output: 4000 # 命令输出截断长度tui:进入交互式运维面板(状态总览 / 插件管理重载 / 消息与系统日志 / 运维操作), 方向键或数字导航,SGR 鼠标点击两段式确认,框架停机时面板自动退出。restart:os.execv原地重启框架(双进程的 host 角色会拒绝,请走核心进程或 Web 面板/api/restart)。dbdump:复用tools/export_db_snapshot.py导出数据库快照。
日志(config.yaml)
log:
level: INFO # DEBUG / INFO / WARNING / ERROR
format: text # text(给人看)/ json(JSON Lines,便于采集器解析)
file: data/logs/zcbot.log # 日志文件
log_raw_message: true # 记录收到的原始消息
log_sent_message: true # 记录发出的消息
coalesce: true # 重复错误自动合并(防刷屏)
coalesce_window: 10 # 合并窗口(秒)
coalesce_level: WARNING # 参与合并的最低级别插件内用 ctx.log() 或标准 logging 输出,会自动带插件名前缀。
format: json 的字段说明、附加结构化字段的写法,见 可观测性与运维接口。改完不用重启,级别与格式都即时生效。
入站可靠性与限流(config.yaml)
reliability:
dedup_window: 300 # 重放去重窗口(秒),0=禁用
rate_limit:
enabled: false # 默认关闭
window: 60
global_per_min: 0 # 0=不限
group_per_min: 0
user_per_min: 0
action: skip # skip | notify
notify_text: "消息过于频繁,请稍后再试。"dedup_window 拦的是「同一接入端 + 同一 message_id」的重复投递(断线重连、客户端重推),正常使用几乎不会误伤,所以默认开;限流阈值带业务属性(大群与小群差一个数量级),框架不替部署方拍板,默认关。语义与边界见 可靠性与限流。
出站闸门(config.yaml)
outbound:
rate_limit:
enabled: true # 默认开启:阈值明显高于正常业务、低于平台惩罚线
window: 60
global_per_min: 180 # 全局每分钟上限,0=不限
group_per_min: 30 # 单群每分钟上限,0=不限
user_per_min: 20 # 单用户私聊每分钟上限,0=不限
max_wait: 5.0 # 单次发送最多等多久(秒),超过即放弃并返回失败
retry:
enabled: true
attempts: 1 # 额外重试次数(0=不重试)
backoff: 0.4 # 首次重试前等待(秒),之后翻倍只作用于发送类动作,get_* 查询动作原样直通。超限时等待而非丢弃(发送是插件的明确意图),等不到才返回 retcode=-4 的失败结构;重试只覆盖 -3 本地通道异常,-2 超时不重试(超时不代表没送达,重试会产生重复消息)。该段支持热应用,改完保存即生效。详见 可靠性与限流。
定时任务(config.yaml)
scheduler:
# local(默认,跟随系统时区)/ utc / IANA 名(Asia/Shanghai)
# 容器里 TZ 通常是 UTC,写 0 9 * * * 会在北京时间 17:00 才执行
timezone: local
task_timeout: 300 # 单任务超时(秒),0=不限;超时只是不再等待,线程仍会跑完
slow_task_threshold: 10 # 耗时超该值打 warning(秒),0=不告警
workers: 4 # 同步 handler 专用线程池大小启动时会打印实际生效的时区(带偏移),例如 定时任务时区: 本地时区 (UTC+08:00)。详见 定时任务。
事件循环看门狗(config.yaml)
framework:
loop_watchdog:
enabled: true # 常驻守护线程,开销可忽略
interval: 0.25 # 采样间隔(秒)
threshold: 0.5 # 延迟超该值判定为阻塞(秒)
stall_wait: 3 # 回调多久没执行判定为循环完全卡死(秒)阻塞调用会让整个机器人停摆且日志无异常,看门狗负责在这种情况下吭声并指出卡在哪一行。 启动期(装依赖/建表/加载插件)自动暂停告警,避免每次启动刷 warning。详见 可观测性与运维。
旧配置文件的缺段补齐
从新版本升级后,config.yaml 里不会有新版本引入的段(如 observability、reliability、outbound、scheduler、database.migrations)。框架加载时会把缺失的顶层段用默认值补进内存,并在日志里列出补了哪些段:
配置文件缺少新版本引入的配置段,已用默认值生效(未改写文件):observability, reliability, outbound, scheduler。两条规则:已存在的段一律不覆盖(用户值优先);不改写你的配置文件(YAML dump 会吃掉注释与排版),需要调整时按默认配置自己补写。
只补顶层段
补齐只针对整段缺失。如果 config.yaml 里已经有 scheduler:(哪怕只有一个 enabled), 新增的子键(timezone、task_timeout)不会被写进去 —— 但代码读取时会用默认值兜底, 功能正常。想在面板里看到这些键,需要手动补写。
系统状态展示(config.yaml)
system:
show_cpu: true # 面板展示 CPU 状态
show_disk: true # 面板展示磁盘状态
status_interval: 30 # 状态采样间隔(秒)GitHub 加速(config.yaml)
github_proxy: "" # 插件更新走的 GitHub 代理前缀,留空直连(内置多镜像回退)从 GitHub 拉取插件更新较慢时,可填镜像代理地址。
安全配置(config.yaml)
security:
fake_token_len: 8 # 蜜罐探针(假令牌)长度
real_token_len: 8192 # 真实认证 Token 长度
nonce_len: 16 # 防重放 Nonce 长度
nonce_expiry: 60 # Nonce 有效期(秒)
fake_response_msg: "你上钩了!但这里只是蜜罐,请去 GitHub 点个 Star。"
blacklist_enabled: true # 启用黑名单
whitelist_ips: # 白名单 IP(仅这些 IP 可访问管理接口)
- "127.0.0.1"公网部署清单
onebot_adapter.access_token设为强随机值;2)webui.host保持127.0.0.1或放在反代/防火墙之后;3) 首次登录后立刻修改默认管理员密码;- 按需配置
security.whitelist_ips;5) 不需要对外的http_api/http_inject保持关闭。
插件元信息(plugin.yaml)
放在插件目录(安装时会迁移到 data/plugins_dat/<插件名>/), 声明元信息、依赖与更新源;其中版本/作者等字段会覆盖 __plugin_meta__:
name: 我的插件
version: 1.0.0
author: 你的名字
description: 插件描述
priority: 50
dependencies: # Python 依赖(也可用 requirements.txt,二者会合并)
python:
- requests>=2.28
- Pillow>=10.0
github: # 在线更新源
repo: owner/repo
branch: main
sub_path: plugins/my_plugin插件 Web 配置(_conf_schema.json)
让插件在 Web 面板可视化配置,值存入数据库,代码用 ctx.get_config 读取:
{
"api_key": {"type": "string", "default": "", "description": "API 密钥", "hint": "在第三方平台获取"},
"timeout": {"type": "number", "default": 30, "description": "请求超时(秒)"},
"enabled": {"type": "bool", "default": true, "description": "是否启用"},
"mode": {
"type": "select", "default": "auto", "description": "工作模式",
"options": [
{"label": "自动", "value": "auto"},
{"label": "手动", "value": "manual"}
]
}
}api_key = ctx.get_config("api_key", default="")
all_cfg = ctx.get_all_config()代码目录与数据目录
| 目录 | 内容 | 是否随插件更新覆盖 |
|---|---|---|
plugins/<名>/ | 插件代码 | 是 |
data/plugins_dat/<名>/ | 插件配置、缓存、用户数据(ctx.get_data_dir()) | 否,长期保留 |
运行期要持久化的文件一律写到数据目录,避免更新插件时丢失。