AstrBot × NapCat 完整部署文档

AstrBot × NapCat 完整部署文档

用 Docker 部署 AstrBot 与 NapCat 打通 QQ:AstrBot 开 6199 反向 WebSocket 并设 Token,NapCat 用 host 网络连 ws://127.0.0.1:6199/ws 。文档还含官方流程对照与踩坑复盘,并提醒:6099 是 NapCat 网页、6199 是接口,「适配器已被关闭」并非失败,两个端口无需暴露公网。

AstrBot × NapCat 完整部署文档(合一版)

本文档由原先的 5 份文档合并而成,只需下载这一个文件

环境:某云服务器(RHEL 系 Linux) | AstrBot 4.28.1(Docker)| NapCat(Docker)整理日期:2026-09-21

怎么读

  • 照着做 → 直接跳到 第二部分
  • 遇到问题 → 跳到 第五部分
  • 想了解为什么和官方不一样 → 看 第四部分

⚠️ 先记住三个最容易踩的坑

  1. 6199 是 AstrBot 的接口(NapCat 填它);6099 是 NapCat 的网页(浏览器开它)
  2. 看到「适配器已被关闭」不代表失败——只有「适配器已连接」才是成功
  3. 两个端口都不需要对公网放行(同机通信走 127.0.0.1

总目录

部分内容什么时候看
第一部分阅读指南导航
第二部分我的实际部署流程照着做时
第三部分官方标准流程查官方原话
第四部分差异对比理解原因
第五部分踩坑复盘与勘误出问题时

第一部分 · 阅读指南

本目录共 5 份文档,每份只讲一件事。按需要挑着看,不用全读。

📖 我应该看哪一份?

我想……看这份有用程度
照着做一遍,把 QQ 机器人跑起来01 · 我的实际部署流程⭐⭐⭐最有用
了解官方文档是怎么写的02 · 官方标准流程⭐ 参考
知道我和官方差在哪、为什么03 · 差异对比⭐⭐ 理解原因
知道踩了哪些坑、怎么避04 · 踩坑复盘⭐⭐⭐避坑必读

🗂️ 四份文档的分工

text
00-阅读指南.md                    ← 你正在看的(导航)
│
├── 01-我的实际部署流程.md          【操作手册】
│     从零到跑通,照着敲就行。
│     内容:我要做什么、敲什么命令、怎么验证、怎么收尾
│
├── 02-官方标准流程.md              【资料存档】
│     官方文档的忠实摘要,方便日后对照。
│     内容:官方网页上写了什么
│
├── 03-我与官方方案的区别.md        【答疑】
│     为什么我用的方法和官方不一样。
│     内容:9 项差异 + 每项的原因和取舍
│
└── 04-踩坑复盘与官方文档勘误.md    【排错手册】
      卡在"验证"这一步的真实原因,附源码证据。
      内容:官方文档的 3 个缺口 + 排错顺序

🚀 只想快速跑通?三步走

  1. 打开 01 · 我的实际部署流程
  2. 照着「阶段 3」的命令逐条执行
  3. 遇到问题 → 转 04 · 踩坑复盘 的排错表

⚠️ 三条最容易踩的坑(先记住)

正确做法
6099 / 6199 分不清6199是 AstrBot 的接口(NapCat 填它);6099是 NapCat 的网页(浏览器开它)
看到「适配器已被关闭」就以为失败❌ 这不是失败。只有"适配器已连接"才代表成功
把 6099/6199 暴露到公网同机通信走 127.0.0.1两个端口都不需要公网放行

🏷️ 文档中的标记约定

标记含义
已验证可行
⚠️需要留意
错误做法 / 已排除
🔴🟡🟢严重度:高 / 中 / 低

📌 环境速记

  • 服务器:一台云服务器(RHEL 系 Linux),文中统一用 你的服务器IP 代指
  • AstrBot:Docker 部署,容器名 astrbot,WebUI 端口 6185
  • NapCat:Docker 部署,容器名 napcat,数据目录 /data/napcat
  • 文档整理日期:2026-09-21

第二部分 · 我的实际部署流程

**这份文档的定位:从零到跑通,照着敲就行。**全部命令均已在真实环境验证通过 ✅

环境:某云服务器(RHEL 系 Linux) | AstrBot 4.28.1(Docker)| NapCat(Docker)日期:2026-09-21

〇、成果总览

最终运行状态:

text
NAMES     IMAGE                          STATUS
napcat    mlikiowa/napcat-docker:latest  Up
astrbot   soulter/astrbot:latest         Up

平台配置:

平台 ID类型用途
default_botqq_officialQQ 官方机器人
weixin_personalweixin_oc个人微信机器人
mybotaiocqhttp本文接入的 NapCat(真实 QQ 号)

一、整体架构(先看懂这张图)

text
┌─────────────────┐        反向 WebSocket          ┌──────────────────┐
│    NapCat       │  ───────────────────────────►  │    AstrBot       │
│  (OneBot v11)   │   ws://127.0.0.1:6199/ws       │  (aiocqhttp)     │
│  --network host │  ◄───────────────────────────  │  容器 172.17.0.3 │
└────────┬────────┘        Token 鉴权              └──────────────────┘
         │
         │ 登录 QQ
         ▼
      QQ 服务器

🔑 谁是客户端,谁是服务端?

角色说明
AstrBot服务端,监听 6199,等着别人来连
NapCat客户端,主动去连 AstrBot 的 6199
NapCat WebUINapCat 自己的管理网页,端口 6099

⚠️ 两个端口千万别搞混

端口是谁的谁访问它
6199AstrBot 的接口NapCat去连它
6099NapCat 的网页你的浏览器打开它

二、阶段 0:部署 AstrBot 本体

参考官方页面:https://docs.astrbot.app/deploy/astrbot/docker.html

本环境已完成 ✅

text
# 拉取镜像
docker pull soulter/astrbot:latest

# 启动(端口按需调整)
docker run -d --name astrbot --restart always \
  -p 6185:6185 \
  -v /data/astrbot/data:/AstrBot/data \
  soulter/astrbot:latest

确认部署成功:

text
docker ps | grep astrbot
# 浏览器访问 http://你的服务器IP:6185 进入 WebUI

💡 AstrBot WebUI 端口默认 6185,容器内数据目录是 /AstrBot/data,对应宿主机 /data/astrbot/data(本文档后续会用到这个路径)。

三、阶段 1:接入已有平台

在 WebUI → 平台配置 中创建:

平台类型说明
QQ 官方机器人qq_official填 AppID / Secret
个人微信机器人weixin_oc按官方指引扫码

本环境已完成 ✅(这两个与本文主题无关,略过)

四、阶段 2:接入真实 QQ 号(本次任务)

参考官方页面:https://docs.astrbot.app/platform/aiocqhttp.html

4.1 在 AstrBot WebUI 创建 OneBot v11 平台

WebUI → 平台配置 → 添加平台 → 选 aiocqhttp

配置项建议值说明
ID任意,如 mybot仅用于区分实例
反向 WebSocket 主机地址0.0.0.0监听所有网卡
反向 WebSocket 端口6199默认值
Token随机字符串(建议 32 位)⚠️ 强烈建议设置
启用

生成随机 Token:

text
openssl rand -hex 32

生成后填进上面,并记牢——后面 NapCat 要填一模一样的。

点击 保存

⚠️ 注意:点"保存"后日志里会出现 aiocqhttp 适配器已被关闭这不代表失败,只是旧实例被正常重载。详见 04 · 踩坑复盘

4.2 确认 AstrBot 正在监听 6199

text
sudo ss -ltnp | grep 6199

应看到 LISTEN 状态。

五、阶段 3:NapCat 部署与配置(核心)

5.0 执行方式说明(本次实际用的)

本次实际是通过 deploy_napcat.sh 脚本执行的,脚本全文见 附录 A。脚本会自动完成 5.1~5.3 的全部动作(建目录 → 拉镜像 → 起容器),并打印后续指引。

下面把脚本做的事拆开写一遍——一是方便理解每一步在干什么,二是万一不想用脚本,可以手工照着敲。

⚠️ 踩到的一个小坑:脚本放错目录

text
❌ bash deploy_napcat.sh
   → bash: deploy_napcat.sh: No such file or directory
   (文件被放在了 / 根目录,而执行时不在那个目录下)

✅ mv deploy_napcat.sh /root/ && cd /root && bash deploy_napcat.sh
   → 成功

正确做法:把脚本放到 /root//data/ 下,执行前先 cd 到那个目录。

定位三步:

text
pwd                                        # 我在哪个目录
ls -l                                      # 这里有这个文件吗
find / -name "deploy_napcat*" 2>/dev/null  # 全盘找一下

标准执行流程:

text
# 1. 把脚本传到 /root/ 或 /data/
# 2. 执行
cd /root
sudo bash deploy_napcat.sh

脚本执行后会做的事(对照下面的手工步骤):

脚本步骤对应本文
环境检查(docker / root 权限)
端口占用检查(只查不杀)5.1 前置
同名容器保护(存在会问你 y/N)5.3 前置
创建目录 /data/napcat/{config,qq}5.1
读取 AstrBot 的端口和 Token(只印长度,不印明文4.1 校验
拉取镜像5.2
启动容器5.3
打印后续操作指引5.4~5.7

💡 卸载:sudo bash deploy_napcat.sh --uninstall(只删容器,保留数据目录)

5.1 创建数据目录

text
sudo mkdir -p /data/napcat/config /data/napcat/qq
sudo chown -R 1000:1000 /data/napcat

目录规范:与 AstrBot 做邻居,统一放 /data/ 下,一服务一目录,便于备份。

5.2 拉取镜像

text
sudo docker pull mlikiowa/napcat-docker:latest

5.3 启动容器

text
sudo docker run -d --name napcat --restart always --network host \
  -e NAPCAT_UID=1000 -e NAPCAT_GID=1000 \
  -v /data/napcat/config:/app/napcat/config \
  -v /data/napcat/qq:/app/.config/QQ \
  mlikiowa/napcat-docker:latest

参数说明:

参数作用
--name napcat容器名,后续运维都用它
--restart always开机/崩溃自动重启
--network host用宿主机网络,方便直接连 127.0.0.1:6199
NAPCAT_UID/GID容器内运行用户,需与数据目录属主一致
-v .../config配置文件持久化
-v .../qqQQ 登录态持久化(别丢,丢了要重新扫码)

确认容器状态:

text
sudo docker ps | grep napcat

5.4 登录 QQ

text
sudo docker logs -f napcat

日志里会出现登录二维码登录链接,用手机 QQ 扫码登录。

5.5 打开 NapCat WebUI

⚠️ 这一步是本流程的关键难点,官方文档没有说明服务器环境下怎么访问。

方式 A:SSH 隧道(最安全,推荐)

你自己的电脑上执行(不是 FinalShell 的服务器窗口!):

text
ssh -L 6099:127.0.0.1:6099 root@你的服务器IP

保持窗口不关,本机浏览器访问:

text
http://127.0.0.1:6099/webui

方式 B:临时放行公网(用完立刻关闭)

  1. 云控制台 → 安全组 → 添加入站规则:
    text
    TCP:6099  来源=你的本机IP/32  允许   ← ⚠️ 绝不要填 0.0.0.0/0
    
  2. 浏览器访问 http://你的服务器IP:6099/webui
  3. 配置完成后立刻删除这条规则

方式 C:FinalShell 内置隧道

连接列表右键 → 隧道/端口转发 → 本地 6099 → 目标 127.0.0.1:6099

5.6 获取 WebUI 登录 Token

text
sudo docker logs napcat 2>&1 | grep -i -A2 "token\|webui"

部分版本默认 Token 为 napcat,可先试这个。

5.7 配置反向 WebSocket(最关键一步)

进入 网络配置 → 新建 → 类型选「WebSocket 客户端」(注意是客户端,不是服务器):

字段填写内容说明
启用打开不开等于白配
开启 Debug排查问题时再开
名称任意,如 astrbot
URLws://127.0.0.1:6199/ws⚠️ 结尾的 /ws不能丢
上报自身消息❌ 保持关闭开了可能自问自答刷屏
消息格式ArrayAstrBot 要求
TokenAstrBot 里设置的那个⚠️ 两边必须完全一致
心跳间隔100030000官方建议 1000(恢复更快)
重连间隔100030000同上
SSL 证书验证保持默认ws://不走 TLS

填完点击 保存

⚠️ 最容易错的两个地方:

  1. URL 漏掉结尾的 /ws
  2. Token 复制时带了多余空格或换行

六、验证是否成功

✅ 唯一可靠的判据:看日志

AstrBot WebUI → 数据与日志 → 日志,出现:

text
aiocqhttp(OneBot v11) 适配器已连接。

看到这句 = 成功。

🔧 辅助判据:看 TCP 连接状态

在 AstrBot 容器内(或宿主机)执行:

text
python3 - <<'PY'
import socket, struct
st={'01':'ESTABLISHED','06':'TIME_WAIT','0A':'LISTEN'}
ip=lambda h: socket.inet_ntoa(struct.pack('<L', int(h,16)))
for line in open('/proc/net/tcp').readlines()[1:]:
    p=line.split()
    lp=int(p[1].split(':')[1],16); rp=int(p[2].split(':')[1],16)
    if lp==6199 or rp==6199:
        print(f"{ip(p[1].split(':')[0])}:{lp} <-> {ip(p[2].split(':')[0])}:{rp}  {st.get(p[3],p[3])}")
PY

判读标准:

现象含义处理
只有 0.0.0.0:6199 LISTENNapCat 还没连上检查 NapCat 配置是否已启用
反复出现 TIME_WAIT源端口不断变化NapCat 在重连但被拒绝⚠️几乎肯定是 Token 不匹配
持续 ESTABLISHED(同一源端口)成功了继续下一步

本次部署就是靠这个方法定位到"Token 填错"的根因。

七、功能测试

  1. 另一个 QQ 号私聊机器人 → 应正常回复
  2. 或建个小群,把机器人拉进去 @ 一下
  3. 群里不响应 → 检查 AstrBot 的唤醒设置 / 唤醒前缀

八、安全收尾(必做)

8.1 关掉公网端口

原理: NapCat 与 AstrBot 在同一台机器上,通信走 127.0.0.1 回环,不经过公网网卡,所以:

text
NapCat ──► 127.0.0.1:6199 ──► Docker 端口映射 ──► AstrBot 容器
              ↑
        走回环,不受安全组/防火墙"外网规则"约束

操作清单:

  • 云控制台安全组:删除 60996199 的入站规则
  • 服务器防火墙(firewalld):sudo firewall-cmd --remove-port=6099/tcp --permanent && sudo firewall-cmd --reload
  • 服务器防火墙(ufw):sudo ufw delete allow 6099/tcp
  • 发条消息确认机器人仍然正常回复

以后要改 NapCat 配置,用 SSH 隧道即可:

text
ssh -L 6099:127.0.0.1:6099 root@你的服务器IP

8.2 权限隔离检查

WebUI → 平台配置 → 管理员

  • 只有名单内的用户 ID 才能调用 Agent 工具(执行命令、读写文件)
  • 新接入的 QQ 号默认不在名单里 → 别人无法通过机器人执行系统命令 ✅
  • /sid 指令查询某用户的 ID

🔒 建议:管理员名单只放你自己,并保持 provider_settings.computer_use_require_admin = True(默认即是)。

8.3 备份提醒

务必把 /data/napcat/qq 纳入备份——里面是 QQ 登录态,丢了要重新扫码。

九、日常运维命令

text
# 查看日志(实时)
sudo docker logs -f napcat

# 查看最近 50 行
sudo docker logs --tail 50 napcat

# 重启 / 停止 / 启动
sudo docker restart napcat
sudo docker stop napcat
sudo docker start napcat

# 查看容器状态
sudo docker ps | grep napcat

# 删除容器(不动数据目录)
sudo docker rm -f napcat

# 完全卸载(含数据,需重新扫码)
sudo rm -rf /data/napcat

数据目录说明:

路径内容
/data/napcat/configNapCat 配置
/data/napcat/qqQQ 登录态(重点备份对象)

十、端口速查表

本机同时运行多个服务,端口需注意冲突:

端口服务容器是否需要公网放行
6185AstrBot WebUIastrbot建议不放行(用隧道)
6199AstrBot 反向 WS 接口astrbot不需要
6099NapCat WebUInapcat不需要(用隧道)
其他app-server / nginx / mysql按需

检查端口占用:

text
sudo ss -ltnp | grep -E "6099|6199|6185"

🆘 出问题了?

去 04 · 踩坑复盘与官方文档勘误 的排错速查表。

附录 A:一键部署脚本

保存为 deploy_napcat.sh,放到 /root//data/ 下执行:

text
cd /root && sudo bash deploy_napcat.sh

卸载:sudo bash deploy_napcat.sh --uninstall

脚本的设计要点

特性说明
零依赖docker run,不需要 Compose
端口检查只查不杀发现 6099 被占用只提示,不动别人的服务
同名容器保护已存在 napcat会先问 y/N,绝不擅自删除
不打印 Token 明文只显示长度,避免密钥进入终端历史/日志
可覆盖参数BASE_DIR/NAME/IMAGE/WEBUI_PORT等均可用环境变量覆盖
支持卸载--uninstall只删容器,保留数据目录

脚本的"零影响"承诺

  • 只创建 /data/napcat/ 一个目录
  • 只管理 napcat 一个容器
  • 不碰你已有的镜像缓存、网络、数据卷、其他容器

想反悔:

text
docker rm -f napcat && rm -rf /data/napcat

第三部分 · 官方标准流程

**这份文档的定位:官方文档写了什么,忠实记录,方便日后对照。**内容全部来自 AstrBot 官方文档正文,未做推测性转述。

来源:

  • https://docs.astrbot.app/deploy/astrbot/docker.html
  • https://docs.astrbot.app/platform/aiocqhttp.html
  • https://docs.astrbot.app/use/computer.html

摘录日期:2026-09-21 | 对照版本:AstrBot 4.28.1

一、Docker 部署 AstrBot

官方页面:https://docs.astrbot.app/deploy/astrbot/docker.html

📌 具体步骤以该页面为准,命令可能随版本更新。本文不重复抄录,仅记录关键结论。

要点:

  • 使用 Docker 部署 AstrBot 本体
  • WebUI 默认端口 6185
  • 容器内数据目录 /AstrBot/data,需映射到宿主机持久化
  • 部署完成后通过浏览器访问 WebUI 管理面板

二、接入 OneBot v11(aiocqhttp)

官方页面:https://docs.astrbot.app/platform/aiocqhttp.html

页面开头的 TIP

如果您打算将 AstrBot 接入 QQ,推荐使用 QQ 官方机器人(WebSockets),由 QQ 官方推出,更稳定,支持一键扫码登录。

关于 OneBot 的说明:

OneBot 是一个聊天机器人应用接口标准,旨在统一不同聊天平台上的机器人应用开发接口。AstrBot 支持接入所有适配了 OneBot v11 反向 WebSockets(AstrBot 做服务器端)的机器人协议端。

官方列出的常见协议实现端:

项目连接的平台
NapCatQQ
OneDiscDiscord
Tele-KiraLinkTelegram

"请参阅对应的协议实现端项目的部署文档。"

2.1 配置 OneBot v11

官方原文步骤:

  1. 进入 AstrBot 的 WebUI
  2. 点击左边栏 机器人
  3. 点击机器人列表上方的 创建机器人
  4. 选择 OneBot v11
  5. 在出现的表单中,填写:
字段官方说明
ID (id)随意填写,仅用于区分不同的消息平台实例
启用 (enable)勾选
反向 WebSocket 主机地址请填写你的机器的 IP 地址,一般情况下请直接填写 0.0.0.0
反向 WebSocket 端口填写一个端口,默认为 6199
反向 Websocket Token只有当 NapCat 网络配置中配置了 token 才需填写
  1. 点击 保存

2.2 配置协议实现端

官方原文:

请参阅对应的协议实现端项目的部署文档。

官方给出的一些注意点:

  • 协议实现端需要支持反向 WebSocket,即 AstrBot 端作为服务端,实现端作为客户端
  • 反向 WebSocket 的 URL 为 ws(s)://<your-host>:6199/ws

2.3 验证

官方原文:

前往 AstrBot WebUI 的 数据与日志 → 日志,如果出现 aiocqhttp(OneBot v11) 适配器已连接。蓝色的日志,说明连接成功。

如果没有,若干秒后出现 aiocqhttp 适配器已被关闭则为连接超时(失败),请检查配置是否正确。

⚠️ 注意:本文档只是忠实摘录。经源码核对,上述第二条判据在 4.28.1 上不成立——详见 04 · 踩坑复盘与官方文档勘误

2.4 附录:部署 NapCat

官方给出两条部署路径,标注"推荐采用这种方式部署"(指一键脚本)。

路径一:一键启动脚本(官方推荐)

平台官方指向的教程
WindowsNapCat.Shell - Win 手动启动教程
LinuxNapCat.Installer - Linux 一键使用脚本(支持Ubuntu 20+ / Debian 10+ / CentOS 9

关于 WebUI 在哪打开,官方说明:

  • 如果是 linux 命令行一键部署的 napcat:docker log <账号>
  • Docker 部署的 NapCat:docker logs napcat

路径二:Docker Compose 部署

官方原文步骤:

  1. 下载或复制 astrbot.yml 内容
  2. 将刚刚下载的文件重命名为 astrbot.yml
  3. 编辑 astrbot.yml,将 # - "6199:6199" 修改为 - "6199:6199",移除开头的 #
  4. astrbot.yml 文件所在目录执行:
text
NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose -f ./astrbot.yml up -d
  1. 部署完毕之后,去 NapCat 的 WebUI(默认端口 6099)中新增 OneBot 连接实例:
    • 点击 网络配置 → 新建 → WebSockets 客户端
    • 勾选 启用
    • URL 填写 ws://宿主机IP:端口/ws,如 ws://127.0.0.1:6199/ws
    • 如果采用上面的 Docker Compose 部署,可以填写 ws://astrbot:6199/ws
  2. 心跳间隔和重连间隔可以改为 1000(1 秒)
  3. 点击保存,然后前往 AstrBot WebUI 的 数据与日志 → 日志 检查是否连接成功,出现 aiocqhttp(OneBot v11) 适配器已连接 日志即代表成功

官方 astrbot.yml 的实际内容

(来源:https://github.com/NapNeko/NapCat-Docker/blob/main/compose/astrbot.yml

📌 注意:这份文件会同时新建 AstrBot 和 NapCat 两个容器,且使用自定义网络 astrbot_network。如果你的 AstrBot 是独立部署的,直接套用会与已有实例冲突。详见 03 · 我与官方方案的区别

三、使用电脑能力(Computer Use)

官方页面:https://docs.astrbot.app/use/computer.html

本节与 NapCat 部署无关,但涉及 Agent 权限,一并存档。

三档模式

模式官方说明
none不启用电脑能力,不给 Agent 挂载 Shell、Python、文件系统等工具(官方默认值
local在 AstrBot 所在机器上执行,适合需要访问本机文件、命令行工具或本地依赖的场景
sandbox在隔离沙盒中执行,适合希望降低本机风险、或让多用户使用自动化能力的场景

配置路径: WebUI → 配置文件 → AI 配置 → 能力 → 使用电脑能力

local 模式的要点

  • 能力边界接近 AstrBot 进程本身:它能访问什么,取决于 AstrBot 进程的系统权限、运行用户、工作目录和操作系统限制
  • 每个会话有独立 workspace:data/workspaces/{normalized_umo}
  • Shell 执行时,工作目录也被设置为这个 workspace
  • 本地文件工具的相对路径默认解析到 workspace 下
  • 提供的工具:Shell、Python、文件读取、文件写入、文件编辑、Grep 搜索
  • 不会挂载沙盒上传/下载工具,也没有浏览器自动化能力

权限模型

「需要 AstrBot 管理员权限」默认情况下是开启的。

开启后:

用户可用能力
管理员local 模式下的 Shell、Python、文件读取/写入/编辑、Grep 搜索
非管理员❌ 不能使用 Shell 和 Python;只能在受限目录内使用文件操作

非管理员在 local 模式下允许访问的目录:

  • data/skills
  • data/plugins/*/skills(只读,用于插件内置 Skills)
  • 当前会话的 data/workspaces/{normalized_umo}
  • AstrBot 的临时目录
  • 系统临时目录中的 .astrbot

管理员 ID 配置位置: 配置文件 → 平台配置 → 基本 → 管理员 ID(用户可用 /sid 获取自己的 ID)

⚠️ 官方明确的安全边界

本地 Shell 内置了基础危险命令拦截,例如 rm -rfsudoshutdownrebootkill -9 等。但这不是完整安全沙箱,不能把它当作安全边界。

四、官方文档中的重要提醒

以下均为官方原文,直接引用:

1. 关于公网暴露

如果您对部署、网络配置不了解,请千万不要在公网暴露 Napcat 的端口。

2. 关于 QQ 接入方式

如果您打算将 AstrBot 接入 QQ,推荐使用 QQ 官方机器人(WebSockets),由 QQ 官方推出,更稳定,支持一键扫码登录。

3. 关于沙盒

Agent 沙盒环境…(v4.12.0 版本及之后引入,替代之前的代码执行器功能)沙盒环境驱动器支持:Shipyard Neo(当前推荐)、Shipyard(旧方案)、CUA

Shipyard Neo 的三部分组成:

组件职责
Bay控制面 API,负责创建和管理 sandbox
Ship负责 Python / Shell / 文件系统能力
Gull负责浏览器自动化能力

工作区根目录: 固定为 /workspace,传入路径应相对于它(如 reports/result.txt)。

📌 一页速记

项目官方说法
AstrBot WebUI 端口6185
反向 WS 端口6199(默认)
反向 WS URL 格式ws(s)://<your-host>:6199/ws
NapCat WebUI 端口6099(默认)
推荐的 QQ 接入QQ 官方机器人(WebSockets)
NapCat 部署推荐方式一键启动脚本
成功判据日志出现 aiocqhttp(OneBot v11) 适配器已连接。
Computer Use 默认值none
管理员权限开关默认值开启

第四部分 · 我与官方方案的区别

**这份文档的定位:为什么我用的方法和官方不一样?**只回答"差异是什么、为什么、怎么选",不含操作步骤。操作步骤看 01,踩坑看 04

一、一句话总结

官方文档假设你是「从零开始、用 Docker Compose 把 AstrBot 和 NapCat 一起部署」;我的实际情况是「AstrBot 早就单独部署好了,现在只是给它补一个协议端」。

前提不同,连锁导致网络模式、部署工具、目录组织等一整串差异。

功能上完全等价——只要 NapCat 能连上 AstrBot 的 6199,用什么方式连的,AstrBot 并不关心。

前提对比

官方路径我的路径
前提两个服务一起新建一个已存在,补齐另一个
工具Docker Compose纯 Docker
网络同一个 Compose 网络--network host
互联地址ws://astrbot:6199/wsws://127.0.0.1:6199/ws

二、差异总览表

#维度官方文档我的方案差异性质
1NapCat 部署一键脚本 / 官方 astrbot.yml(Compose)docker run --network host🟢 合理变通
2容器互联同 Compose 网络,用服务名互访host 网络,走 127.0.0.1🟢 合理变通
3心跳/重连间隔建议 1000(1 秒)30000(界面默认值)🟡 可优化
4Token不强制(NapCat 配了才需填)两边都配,建议 32 位随机🟢 安全加强
5验证方式看日志判据(但该判据有问题)日志 +/proc/net/tcp连接状态🟢 更可靠
6数据目录未强制约定/data/napcat,与 AstrBot 同级🟢 施工规范
7公网暴露明确警告"不要暴露 NapCat 端口"最终全部关闭,走 SSH 隧道🟢 与官方一致
8电脑能力默认值none(不挂载任何工具)local(可执行 Shell/Python)🟡 有意为之
9QQ 接入推荐优先推荐 QQ 官方机器人两条路都走(官方机器人 + NapCat)🟢 互补

图例:🟢 = 合理变通 🟡 = 值得注意/可优化

三、逐项详解

1. NapCat 的部署方式

官方: 一键启动脚本(官方推荐)/ 官方 astrbot.yml(Docker Compose)

我的:

text
sudo docker run -d --name napcat --restart always --network host \
  -e NAPCAT_UID=1000 -e NAPCAT_GID=1000 \
  -v /data/napcat/config:/app/napcat/config \
  -v /data/napcat/qq:/app/.config/QQ \
  mlikiowa/napcat-docker:latest

为什么不一样:

原因说明
前提不同官方的 astrbot.yml把 AstrBot 和 NapCat 写在同一个 Compose 里,一步到位。我的 AstrBot 早就独立跑着,没必要为了加 NapCat 去动已有服务
工具习惯我用纯 docker,没装 Compose。docker run少一层依赖
风险控制另起一份 Compose 会新建一套网络和生命周期,容易和已有服务交叉;docker run 完全独立,删掉不影响任何人

优劣:

方案优点缺点
官方 Compose一键、可复现、便于整体迁移需要 Compose,要改官方文件(打开注释)
docker run零依赖、隔离清晰、易回滚命令长,需手动记录参数

结论: 已有 AstrBot 独立部署 → 用我的方式;全新搭建 → 用官方 Compose。

2. 容器之间怎么互联

官方: URL 格式 ws(s)://<your-host>:6199/ws;同 Compose 网络可填 ws://astrbot:6199/ws

我的: ws://127.0.0.1:6199/ws(配合 --network host

三种网络模式对比:

text
【官方 Compose 方案】
NapCat 容器 ──┐
              ├── 同一个自定义 docker network
AstrBot 容器 ─┘   用「服务名」互相找
                  → ws://astrbot:6199/ws

【我的 host 方案】
NapCat 容器(直接使用宿主机网络栈)
   └──→ 127.0.0.1:6199 → Docker 端口映射 → AstrBot 容器
                          → ws://127.0.0.1:6199/ws
  • 服务名互访:优雅,但要求两容器在同一自定义网络,需要 Compose 编排
  • host 网络:简单粗暴,直接共享宿主机端口,不用管容器名解析

⚠️ 关键澄清:端口映射 ≠ 公网放行

官方要求打开 - "6199:6199",那是把容器端口发布到宿主机,让同机的 NapCat 能通过 127.0.0.1:6199 连上。

它和"在云安全组放行 6199"是两件完全不同的事:

操作作用是否需要
Docker 端口映射 -p 6199:6199容器 → 宿主机✅ 需要
云安全组放行 6199互联网 → 云服务器完全不需要

结论: host 网络最省心,代价是牺牲容器网络隔离。单机自用完全够。

3. 心跳 / 重连间隔

官方: 建议改为 1000(1 秒)

我的: 保持界面默认 30000(30 秒)

为什么不一样: 不是有意的,这是默认值,没改

但实际影响了排障体验:

排查"连上又断"时,因为间隔是 30 秒,观察窗口内只能抓到 1~2 次尝试,导致一开始不够确定是"没启用"还是"被拒绝"。

建议:

间隔优点缺点
1000(官方建议)断线秒级恢复,排障友好心跳日志更密
30000(默认)省资源、日志干净断线恢复慢,排障不直观

结论: 想少踩坑就按官方建议改成 1000

4. Token 填不填

官方:

反向 Websocket Token:只有当 NapCat 网络配置中配置了 token 才需填写

即:官方允许两边都不填。

我的: 两边都填,建议 openssl rand -hex 32 生成 32 位随机串。

为什么不一样: 纯安全考量。不填 Token 意味着:

  • AstrBot 的 6199 不校验任何身份
  • 任何能访问到该端口的程序,都能直接接管机器人

"内网无认证"是很危险的默认假设。多一层 Token,成本几乎为零。

结论: 官方是"能用就行",我是"顺便把锁挂上"。建议保留 Token。

5. 验证方式

官方: WebUI → 数据与日志 → 日志,看 aiocqhttp(OneBot v11) 适配器已连接 表示成功

我的: 日志 + 在容器内读 /proc/net/tcp 看 6199 的连接状态

为什么不一样: 助手在容器里无法登录 WebUI,所以用了更底层的网络状态观测。

两种方式互补:

方式能回答的问题
官方日志法"适配器最终连上了吗?"
网络状态法"是压根没连,还是连上又被踢了?"

后者在本次排障中立了大功——正是看到"源端口不断变化 + 全是 TIME_WAIT",才判断出 NapCat 在反复重连但被拒绝,从而锁定 Token 不匹配 这个根因。

结论: 日常用官方日志法;卡住时用网络状态法区分"未连接"和"连接被拒"。

⚠️ 另外,官方验证章节里"出现 适配器已被关闭 即连接失败"这条判据本身有问题,详见 04 · 踩坑复盘

6. 数据目录放哪

官方: 未做强制约定。用官方 Compose 时数据自然落在 Compose 文件所在目录。

我的:

text
/data/
├── astrbot/          ← 原有
└── napcat/           ← 新增,与 AstrBot 做邻居
    ├── config/
    └── qq/           ← QQ 登录态,务必备份

为什么不一样:

原因说明
与现状一致AstrBot 已在 /data下,新服务跟着走,避免散落
备份友好tar -czf backup.tar.gz /data/astrbot /data/napcat一把梭
权限清晰数据目录属主与 NAPCAT_UID/GID对齐

结论: 纯粹施工规范差异,不影响功能。跟已有习惯保持一致就是最好的选择。

7. 公网端口暴不暴露

官方:

如果您对部署、网络配置不了解,请千万不要在公网暴露 Napcat 的端口。

我的: 完全一致,甚至更严格。

  • 6199:删掉安全组规则
  • 6099:删掉,改用 SSH 隧道
  • 隧道:ssh -L 6099:127.0.0.1:6099 root@服务器IP

为什么关掉也不影响:

text
NapCat(host 网络)──→ 127.0.0.1:6199 ──→ AstrBot 容器
                       ↑
                  走回环,不出网卡
                  不受安全组/防火墙"外网规则"约束

结论: 与官方建议完全一致,这条是硬要求。

8. 电脑能力(Computer Use)的默认值

官方:

模式含义
none不启用电脑能力,不给 Agent 挂载工具(官方默认
local在 AstrBot 所在机器上执行,能力边界接近 AstrBot 进程本身
sandbox在隔离沙盒中执行

我的实例实际值:

text
computer_use_runtime       = local     # 官方默认是 none
computer_use_require_admin = True      # 与官方默认一致 ✅

为什么不一样:

  • require_admin:与官方默认一致,不用改
  • local:偏离了官方默认的 none。这是有意开启的——否则 Agent 无法执行任何命令、读写任何文件

官方提醒要听进去:

"这不是完整安全沙箱,不能把它当作安全边界。"

真正的防线是:

  1. require_admin = True(防外部用户)
  2. 管理员名单只放自己
  3. 不要暴露给不可信的群聊(提示注入挡不住"动嘴")

结论: local 是能力与风险的取舍。要更安全就切 sandbox(需先部署 Shipyard Neo / Bay)。

9. 接 QQ 用官方机器人还是 NapCat

官方:

推荐使用 QQ 官方机器人(WebSockets),更稳定,支持一键扫码登录。

我的: 两条路都配。

平台类型说明
default_botqq_officialQQ 官方机器人
mybotaiocqhttpNapCat / OneBot v11

为什么不一样: 不是"不一样",而是互补

方式优势限制
QQ 官方机器人官方支持、稳定、不怕风控功能受平台限制
NapCat(OneBot v11)能力全、可用普通 QQ 号、生态丰富第三方协议端,有风控/封号风险

结论: 能用官方机器人解决的场景优先用官方;NapCat 用于官方覆盖不到的场景,且务必用小号

四、哪些是合理变通,哪些值得改进

🟢 合理变通(保持即可)

  1. docker run 代替官方 Compose —— AstrBot 已独立部署
  2. --network host 代替容器名互访 —— 单机场景更简单
  3. 数据目录定为 /data/napcat —— 与已有习惯一致
  4. 两边都配 Token —— 安全加强,官方不反对
  5. 用网络状态辅助验证 —— 补充手段,不影响官方流程

🟡 值得改进(建议采纳)

  1. 心跳/重连间隔30000 → 建议改 1000(官方建议值)
  2. computer_use_runtimelocal → 如果不再需要 Agent 动手,建议改回 none
  3. Token 长度:本次实际用了 9 位 → 建议换成 32 位(openssl rand -hex 32

📌 一页对比

项目官方我的
部署工具Docker Composedocker run
网络模式自定义 bridge 网络--network host
NapCat 里的 URLws://astrbot:6199/wsws://127.0.0.1:6199/ws
心跳/重连100030000
Token可选必填(32 位随机)
数据目录未约定/data/napcat
端口暴露不要暴露全部关闭 + SSH 隧道
验证手段看日志日志 + 连接状态

第五部分 · 踩坑复盘与官方文档勘误

**这份文档的定位:出问题时查这里。**记录了本次部署的完整踩坑过程、根因分析(附源码证据)、以及排错速查表。

环境:AstrBot 4.28.1(Docker)| RHEL 系 Linux日期:2026-09-21

一、结论速览

不是操作错了,是官方文档在两个地方会把人带沟里。

#问题严重度影响
1"适配器已被关闭"被解释为"连接失败",但它其实是"适配器被正常关闭/重载"的日志🔴 高会让人在协议端还没部署时就误判失败,直接放弃
2只给了"从零用 Docker Compose 一起部署"的方案,没有覆盖"已有独立 AstrBot,再单独加一个 NapCat"🔴 高无路可循,只能瞎试
3127.0.0.1在容器场景的含义没说明🟡 中地址填错,连不上
4只说"去 NapCat WebUI 配置",没说服务器环境下怎么访问这个 WebUI🟡 中进不去面板,卡死

核心那句话

官方文档写的 "若干秒后出现 aiocqhttp 适配器已被关闭 则为连接超时(失败)",在 AstrBot 4.28.1 的源码里不成立——这条日志只在适配器被主动关闭时打印,而保存平台配置这个动作本身就会触发它

二、实际发生的时间线(已确认)

以下来自部署者本人的完整口述复盘。

text
【阶段 0】AstrBot 本体部署
  参考 docs.astrbot.app/deploy/astrbot/docker.html
  → 用 Docker 成功部署 AstrBot
  → 打开日志、通过服务器连接进入 WebUI 管理面板          ✅ 成功

【阶段 1】已有平台接入
  → 创建 QQ 官方机器人(qq_official)                    ✅ 成功
  → 创建个人微信机器人(weixin_oc)                      ✅ 成功

【阶段 2】新增诉求:接入真实 QQ 号(OneBot v11)
  参考 docs.astrbot.app/platform/aiocqhttp.html
  → 第 1 步  配置 OneBot v11(WebUI 创建平台并保存)      ✅ 完成
  → 第 2 步  配置协议实现端(NapCat)                     ⚠️ 未能跑通
  → 第 3 步  验证
        └─► 日志中出现 "aiocqhttp 适配器已被关闭"
        └─► 按文档判定为"连接超时(失败)"
        └─► ❌ 中止,没有继续                              ⛳ 卡点

【阶段 3】改用另一套方案
  → 用 docker run --network host 单独部署 NapCat
  → 临时放行防火墙端口,打开 NapCat WebUI
  → 配置反向 WebSocket(URL + Token)
  → 机器人正常回话                                       ✅ 成功
  → 关闭防火墙端口                                       ✅ 安全收尾

三、官方文档的三个缺口

缺口一(最关键):所谓"连接失败"的判据不准确

官方原文

3. 验证如果出现 aiocqhttp(OneBot v11) 适配器已连接。,说明连接成功。如果没有,若干秒后出现 aiocqhttp 适配器已被关闭 则为连接超时(失败),请检查配置是否正确。

源码里实际是怎样的

astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py

text
async def shutdown_trigger_placeholder(self) -> None:
    await self.shutdown_event.wait()
    logger.info("aiocqhttp 适配器已被关闭")     # ← 这行日志

shutdown_event 只在 terminate() 里被设置:

text
async def terminate(self) -> None:
    if hasattr(self, "shutdown_event"):
        self.shutdown_event.set()               # ← 唯一触发点
    await self._close_reverse_ws_connections()

terminate() 由谁调用?astrbot/core/platform/manager.py

text
async def reload(self, platform_config: dict) -> None:
    await self.terminate_platform(platform_config["id"])   # ← 先终止旧的
    if platform_config["enable"]:
        await self.load_platform(platform_config)          # ← 再加载新的

async def terminate_platform(self, platform_id: str) -> None:
    if platform_id in self._inst_map:
        logger.info(f"Attempting to terminate platform adapter {platform_id} ...")
        ...
        await self._terminate_inst_and_tasks(inst)

结论

aiocqhttp 适配器已被关闭 会出现在这些场景:

触发场景是否代表"连接失败"
在 WebUI 里保存/修改平台配置(触发 reload)不代表,这是正常重载
在 WebUI 里禁用/删除该平台❌ 不代表
AstrBot 关闭或重启❌ 不代表
协议端连接超时失败⚠️ 源码里没有为这种情况打这条日志

唯一可靠的"成功"判据是:

text
@self.bot.on_websocket_connection
def on_websocket_connection(_) -> None:
    logger.info("aiocqhttp(OneBot v11) 适配器已连接。")

这条只在真的收到 WebSocket 连接时打印。

缺口二:缺少"已有独立 AstrBot"场景的部署方案

官方给的 NapCat 部署路径只有三种

场景官方是否覆盖
① 全新部署,Windows 跑 NapCat Shell
② 全新部署,Linux 一键脚本
③ 全新部署,官方 Compose 一起起
已有独立 AstrBot,单独加一个 Docker NapCat没有

本次正是第 ④ 种。 官方文档里找不到对应写法,只能自己摸索。

官方 Compose 为什么不能直接套用

text
  astrbot:
    image: soulter/astrbot:latest      # ← 会新起一个 AstrBot!
    container_name: astrbot
    ports:
      - "6185:6185"                    # ← 与已有实例撞端口
    volumes:
      - ./data:/AstrBot/data           # ← 全新空数据目录
冲突点后果
6185:6185端口占用新 AstrBot 起不来
./data全新目录即便起来,也是空的、与你无关
自定义网络 astrbot_network与已有 AstrBot 的默认 bridge 网络不通,服务名解析不到

缺口三:容器场景下"宿主机 IP"表述有歧义

官方原文

URL 填写 ws://宿主机IP:端口/ws。如 ws://127.0.0.1:6199/ws

为什么有歧义

127.0.0.1 的含义取决于 NapCat 跑在哪

NapCat 的部署方式127.0.0.1指的是能否连上
宿主机直接运行(一键脚本)宿主机
bridge 网络的容器NapCat 容器自己不行
--network host的容器宿主机

官方那句"如 ws://127.0.0.1:6199/ws"只在特定部署方式下成立,但没标注前提。

缺口四:没说明"服务器上怎么访问 NapCat WebUI"

官方原文:

部署完毕之后,可以去 Napcat 的 WebUI(默认端口 6099)中新增 OneBot 连接实例

但在云服务器场景下:

  • 6099 默认不对公网开放(安全组)
  • 官方没说可以用 SSH 隧道
  • 结果就是:进不去面板,配不了反向 WS,自然连不上

这正是本次部署不得不临时放行防火墙的原因。

四、根因详解:为什么会被"骗停"

关键在于第 3 步看到的日志,来源是第 1 步

text
第 1 步:在 WebUI 点【保存】
   │
   └─► platform_manager.reload()
         ├─ terminate_platform(id)   → 打印 "Attempting to terminate platform adapter ..."
         │                             → terminate() → shutdown_event.set()
         │                             → 打印 "aiocqhttp 适配器已被关闭"   ⛳ 日志诞生于此
         └─ load_platform(config)    → 启动新实例,等待协议端连接
   │
第 2 步:协议实现端(NapCat)没能跑通
   └─► 因此没有任何 WebSocket 连上来
         → 永远不会出现 "适配器已连接" 日志
   │
第 3 步:去日志页验证
   └─► 日志里**只有**第 1 步留下的 "已被关闭"
         + 官方文档说"这就是连接超时(失败)"
         → 判定失败,中止

两个误会叠加:

误会说明
① 日志归因错误那句"已被关闭"是第 1 步保存配置时旧实例正常关闭留下的,与第 2、3 步无关
② 判据不可靠官方把这条日志当作"连接失败"的证据,但它本身不携带任何连接状态信息

一条与连接无关的日志,被文档赋予了"失败"的含义,导致排查提前终止。

五、第 2 步为什么没跑通

部署者当时没有打开过 NapCat 管理面板(直到阶段 3 才第一次访问),说明 NapCat 服务当时并未处于可用状态。

✅ 已排除:套用官方 astrbot.yml 导致冲突

复核命令:

text
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
sudo find / -maxdepth 3 \( -name "ntqq" -o -name "astrbot.yml" \) 2>/dev/null

实际结果:

text
NAMES        IMAGE                          STATUS
napcat       mlikiowa/napcat-docker:latest  Up 42 minutes
astrbot      soulter/astrbot:latest         Up 20 hours
app-server   myapp:latest                   Up 2 days
blog-site    node:24-bookworm-slim          Up 4 days
nginx        nginx                          Up 3 weeks
mysql        mysql:8                        Up 3 weeks

(find 命令无任何输出)
观察结论
没有多余的 AstrBot 容器官方 Compose没有被执行过
find找不到 ntqq目录、也找不到 astrbot.ymlCompose 文件从未落到磁盘上
只有一个 napcat容器,运行 42 分钟就是阶段 3 用 docker run起的那一个

官方 Compose 那条路根本没被走。此原因排除。

⚠️ 仍然可能:NapCat 没起来 / 起来了但进不去 WebUI

B-1:NapCat 压根没部署成功

官方给的非 Compose 路径:

路径本环境适配情况
Windows NapCat.Shell❌ 环境不符
Linux 一键脚本⚠️ 官方标注支持Ubuntu 20+ / Debian 10+ / CentOS 9

本机是 RHEL 系的国产发行版不等于 CentOS 9)。一键脚本在未列入支持列表的系统上可能中途失败,且失败信息未必显眼。

B-2:NapCat 起来了,但 WebUI 访问不到 ← 几乎确定成立

证据:部署者是在阶段 3 才第一次打开 NapCat 面板("然后去增加防火墙,打开 Napcat 管理面板"),说明在此之前一直访问不到。

遗留的未知项

第 2 步具体执行了哪种方式(一键脚本 / 其他),部署者已记不清。

  • 已排除:官方 Compose
  • ⚠️ 仍不确定:是 B-1(没部署成功)还是 B-2(进不去面板)

但这不影响结论——无论第 2 步失败于哪种原因,官方的"验证"判据都是不可靠的

附带确认到的环境信息

AstrBot 镜像soulter/astrbot:latest
同机其他服务app-server/blog-site/nginx/mysql
系统RHEL 系 Linux

⚠️ 多服务共存这点值得注意:宿主机端口是共享资源6099 / 6185 / 6199 都要确认不与其他服务冲突。

六、排错速查表

现象可能原因解决办法
bash: deploy_napcat.sh: No such file or directory脚本放到了 /根目录,而执行时不在那个目录(本次实际踩到)pwdls -lfind / -name "deploy_napcat*" 2>/dev/null,然后 cd到脚本所在目录再执行
浏览器打开 6099 显示 Not Found把 6099 和 6199 搞混了NapCat WebUI 一定是6099
SSH 命令报 Permission denied命令敲在了FinalShell 的服务器窗口要在本机PowerShell / CMD 执行
日志出现 适配器已被关闭不是错误!是保存配置触发的正常重载忽略它,看有没有"已连接"
NapCat 一直"连接中 / 断开"Token 不匹配两边 Token 逐字符核对,去除空格
连上后立刻断开,反复重连同上,或 URL 路径错误确认 ws://127.0.0.1:6199/ws
TIME_WAIT反复出现、源端口不断变化NapCat 在重连但被拒绝几乎肯定是 Token 不匹配
连接正常但机器人不回复平台未启用 / 唤醒词问题检查平台状态与唤醒设置
docker pull失败镜像名变更 / 网络问题到 Docker Hub 搜可用镜像名
容器起不来端口 6099 被占用sudo ss -ltnp | grep 6099
机器人自问自答刷屏NapCat 开启了「上报自身消息」关闭该选项
进不去 NapCat WebUI6099 未放行 / 不知怎么访问用 SSH 隧道,或临时放行本机 IP

七、正确的排错顺序

官方顺序是「配置 → 部署协议端 → 验证」,但验证的判据不可靠

建议改成以"连接状态"为准,而不是以日志文本为准

text
① 配置 AstrBot 平台(端口 6199 + 一个随机 Token)
       ↓
② 部署协议端 NapCat,扫码登录
       ↓
③ 在 NapCat 里配置反向 WS 客户端,URL + Token 填对,保存并启用
       ↓
④ 验证(按可靠性排序)
   a. 看日志:出现 "aiocqhttp(OneBot v11) 适配器已连接。"  ← 唯一可靠的"成功"判据
   b. 容器内看 6199 是否有 ESTABLISHED 连接            ← 能区分"没连"和"连上又断"
   c. 直接发消息测试

"已被关闭"到底该怎么理解

你看到的日志组合真实含义
Attempting to terminate platform adapter ...+适配器已被关闭适配器被重载/关闭(多半因为刚保存了配置),不代表连接失败
只有 适配器已被关闭,反复出现平台在反复重载,检查是否有插件或外部程序在改配置
适配器已连接。真的成功了
什么都没有,一直没动静协议端从未连上来,去查网络地址和协议端状态

八、给官方文档的修订建议

如愿意,可整理成 issue 提给 AstrBot 官方。

建议 1:修正"验证"章节的判据

原文如果没有,若干秒后出现 aiocqhttp 适配器已被关闭 则为连接超时(失败),请检查配置是否正确。

建议改为出现 aiocqhttp(OneBot v11) 适配器已连接。 表示成功。注意:日志中的 aiocqhttp 适配器已被关闭适配器被重载或关闭时的正常日志(保存平台配置、禁用平台、重启 AstrBot 时都会打印),不能作为连接失败的判据。若始终未见"已连接"日志,请检查协议端的反向 WS 地址与 Token 是否正确。

建议 2:补充"已有独立 AstrBot"的部署章节

新增一节 "已有 AstrBot 时,如何单独部署 NapCat"

text
docker run -d --name napcat --restart always --network host \
  -e NAPCAT_UID=1000 -e NAPCAT_GID=1000 \
  -v /data/napcat/config:/app/napcat/config \
  -v /data/napcat/qq:/app/.config/QQ \
  mlikiowa/napcat-docker:latest

并在 NapCat WebUI 里填 ws://127.0.0.1:6199/ws

建议 3:明确"网络地址"的三种情况

NapCat 运行方式应该填的地址
宿主机直接运行ws://127.0.0.1:6199/ws
--network host容器ws://127.0.0.1:6199/ws
bridge 容器(与 AstrBot 同网络)ws://<服务名或容器名>:6199/ws
bridge 容器(不同网络)ws://<宿主机内网IP>:6199/ws

建议 4:补充"服务器上如何访问 NapCat WebUI"

说明两种方式:

  1. SSH 隧道(推荐):ssh -L 6099:127.0.0.1:6099 user@host
  2. 临时放行安全组 6099仅限自己的 IP),配置完立即删除

建议 5:澄清"端口映射 ≠ 公网放行"

官方 Compose 里打开 - "6199:6199" 是把容器端口发布到宿主机,不等于需要在云安全组放行 6199。建议与"千万不要在公网暴露 Napcat 端口"这句合并说明。

附录:源码证据

文件astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py

text
# 成功日志:收到 WebSocket 连接时
@self.bot.on_websocket_connection
def on_websocket_connection(_) -> None:
    logger.info("aiocqhttp(OneBot v11) 适配器已连接。")

# 关闭日志:shutdown_event 被设置时
async def shutdown_trigger_placeholder(self) -> None:
    await self.shutdown_event.wait()
    logger.info("aiocqhttp 适配器已被关闭")

# shutdown_event 的唯一设置点
async def terminate(self) -> None:
    if hasattr(self, "shutdown_event"):
        self.shutdown_event.set()
    await self._close_reverse_ws_connections()

文件astrbot/core/platform/manager.py

text
async def reload(self, platform_config: dict) -> None:
    await self.terminate_platform(platform_config["id"])   # ← 保存配置走这里
    if platform_config["enable"]:
        await self.load_platform(platform_config)
    ...

async def terminate_platform(self, platform_id: str) -> None:
    if platform_id in self._inst_map:
        logger.info(f"Attempting to terminate platform adapter {platform_id} ...")

推论链:保存平台配置 → reload()terminate_platform()inst.terminate() → 设置 shutdown_event → 打印 aiocqhttp 适配器已被关闭

因此该日志 ≠ 连接失败。

附录:复核命令记录

本次用于排障与验证的命令,可复现:

text
# 1. 查看所有容器(确认有没有多余的 AstrBot)
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"

# 2. 查找官方 Compose 的残留文件
sudo find / -maxdepth 3 \( -name "ntqq" -o -name "astrbot.yml" \) 2>/dev/null

# 3. 查看 6199 的连接状态
python3 - <<'PY'
import socket, struct
st={'01':'ESTABLISHED','06':'TIME_WAIT','0A':'LISTEN'}
ip=lambda h: socket.inet_ntoa(struct.pack('<L', int(h,16)))
for line in open('/proc/net/tcp').readlines()[1:]:
    p=line.split()
    lp=int(p[1].split(':')[1],16); rp=int(p[2].split(':')[1],16)
    if lp==6199 or rp==6199:
        print(f"{ip(p[1].split(':')[0])}:{lp} <-> {ip(p[2].split(':')[0])}:{rp}  {st.get(p[3],p[3])}")
PY

# 4. 端口占用检查
sudo ss -ltnp | grep -E "6099|6199|6185"

# 5. NapCat 日志 / WebUI Token
sudo docker logs --tail 50 napcat
sudo docker logs napcat 2>&1 | grep -i -A2 "token\|webui"

一句话总结

官方文档的"验证"判据把"适配器被正常关闭"误当成了"连接失败",而保存平台配置这个动作本身就会产生这条日志——两者叠加,导致排查被误判中止。

  • 「源码层面的调用链」——确定(见源码证据)
  • 「实际走过的时间线」——已确认
  • 「第 2 步失败的具体原因」——已排除官方 Compose,其余见第五节

正确且唯一可靠的"成功"判据是:日志中出现 aiocqhttp(OneBot v11) 适配器已连接。

评论区

评论加载中...