
上周四晚上我盯着终端里刷屏的日志终于看到 ClawdBot 打出了那一行“bot online”。那一刻的成就感不亚于第一次把个人博客挂到公网。随后两天它在我的钉钉群里帮我盯指标、早上九点自动汇总天气和待办夜里同事问它问题也能秒回——一台 1 核 2G 的小服务器安安静静就把活儿干了。这篇东西就是那晚整个过程的完整复盘。ClawdBot 是一个可以自托管部署的常驻式 AI 助手服务说人话就是你把它装在自己的服务器上配好大模型接口它就能 7×24 小时在线通过钉钉、飞书这类聊天工具的机器人接口和你对话还能跑定时任务、做信息检索。我踩过的坑、试出来的最稳路线、还有现在每天在用的配置都写在下面了。无论你手里是一台云服务器还是一台吃灰的旧电脑只要能把 Docker 跑起来按这个流程走大概率能一次过。1. 项目定位与部署思路1.1 ClawdBot 到底是个什么东西最早我在 GitHub 上翻到 ClawdBot 的时候第一反应是这名字蹭了 Claude 的热度。实际用下来它更像是一个“聊天机器人外壳 任务调度器”的结合体。你给它一个模型接口它负责把自然语言请求转发给模型同时把多轮对话上下文、用户身份隔离、定时任务这些脏活累活揽下来。换句话说ClawdBot 本身不生产智能它是把智能“接入”到你日常聊天工作流里的那一层胶水。它可以做几件非常实在的事把你对接的对话接口变成 7×24 小时在线的聊天机器人挂在钉钉群或飞书群里多用户会话隔离A 用户和 B 用户各自保持独立上下文不会互相串台通过内置的 cron 定时模块每天固定时间主动推送消息比如早报、数据巡检、待办提醒支持 API 兼容的多模型配置可以随时切换到不同的模型服务,也可以同时配置多套模型做路由。这么说吧如果你的需求只是本地跑一个网页版的临时问答那用不着 ClawdBot随便一个 streamlit 脚本都能做到。但你要的是一个长期在线、稳定不崩、能接入 IM、能定时触发任务的“私人助理”这种场景正是 ClawdBot 这类常驻服务存在的意义。1.2 为什么我推荐 Docker Compose 部署ClawdBot 的官方文档实际上给了两种安装方式一种是直接把 Python 环境拉起来裸跑另一种是用 Docker Compose 跑容器。我第一次图省事选了裸跑结果 Python 版本冲突、依赖装不上、系统 Python 被我折腾得差点崩掉最后老老实实切到 Docker 路线。用 Docker Compose 部署对我这种“尽量少折腾服务器环境”的人来说收益是压倒性的依赖全部封装在镜像里宿主机上只需要一个 Docker 引擎以后重装系统、迁移服务器一条docker compose up -d就能恢复服务版本升级简单改一下镜像标签重新拉取即可出问题还能秒回滚到旧版本重启策略交给 Docker 管理进程崩了自动拉起来实现 7×24 不依赖 systemd 脚本。这个思路其实和我们平时做项目差不多能隔离的就隔离能把可变部分抽出来的就抽出来。ClawdBot 的可变部分主要是配置和数据Docker 把它们分别映射到宿主机的.env文件和./data目录升级镜像不影响数据思路非常清晰。2. 安装前的准备工作2.1 服务器与系统选型先说硬件底线。ClawdBot 本体其实消耗不了多少资源真正的“大户”是对接的模型服务——如果模型服务跑在本地那需要独立显卡和大显存如果模型服务走远程接口那么 1 核 2G 内存的机器跑 ClawdBot 绰绰有余。我用的就是一台 1 核 2G、20G 硬盘的轻量服务器装了 Debian 12实测跑了两天内存占用稳定在 400M 左右非常轻松。系统方面优先选 Debian 12 或 Ubuntu 22.04/24.04。这两个系统对 Docker 的兼容性最好遇到问题的搜索资料也多。如果你手上只有 CentOS 7 这类老系统建议先花十分钟换个系统重装别在源上浪费时间——我见过有人在 CentOS 7 上折腾 Docker 老版本折腾了俩小时最终换 Debian 五分钟搞定。还有一点容易被忽略时区。服务器默认往往是 UTC 时区而 ClawdBot 的定时任务和日志时间显示都依赖系统时区。我直接在环境变量里写了TZAsia/Shanghai后面所有日志和定时触发时间就都正常了。这个后面配置环节会再强调。2.2 安装 Docker 与 Compose 插件这里给出 Debian/Ubuntu 系最省事的安装方式。我最推荐用系统自带的docker.io包虽然版本不一定是最新但稳定性和依赖处理都比手动加源省心apt update apt install -y docker.io docker-compose-v2 systemctl enable --now docker docker compose version最后一条命令如果输出了类似Docker Compose version v2.x.x的信息说明 Compose 插件已经就位。注意我刻意没用curl -fsSL https://get.docker.com | sh这种官方脚本因为国内网络访问那个脚本源经常超时反而apt源里的包更可靠。如果你是新建的 Debian 12 系统apt 源里默认就有 docker.io不用额外配置任何东西。如果你的系统里已经装了旧版 Docker建议先把旧容器都停掉然后直接安装 docker.io 覆盖。装好之后顺手验证一下 Docker 引擎是否在跑systemctl status docker --no-pager看到active (running)就行。2.3 项目目录与端口规划我习惯把这类自托管服务统一放在/opt下方便备份和管理。创建 ClawdBot 的项目目录mkdir -p /opt/clawdbot/data /opt/clawdbot/logs目录结构大概是这样的/opt/clawdbot/docker-compose.ymlCompose 编排文件/opt/clawdbot/.env所有敏感配置和可变配置/opt/clawdbot/data/容器内产生的数据持久化目录/opt/clawdbot/logs/日志持久化目录。端口规划上我建议容器内部端口保持默认的 8080宿主机映射到一个不常用的高位端口比如 18080。为什么不用默认的 80 端口一是 80 端口太容易被其他服务占用二是如果把 ClawdBot 直接暴露在 80 上公网扫描器会第一时间盯上它。高位端口加白名单访问能省掉很多不必要的麻烦。3. 一步步安装 ClawdBot3.1 获取项目文件与镜像ClawdBot 项目的发布包可以从它的 GitHub Releases 页面下载也可以直接用 git 克隆源码仓库。考虑到多数人只需要部署不需要看源码我更推荐下载 release 包cd /opt/clawdbot # 假设 release 包已经下载到当前目录 tar -zxvf clawdbot-*.tar.gz解压后里面一般包含docker-compose.yml、.env.example、docker/等文件。先把示例配置文件复制一份cp .env.example .env这里有个业界惯例值得多说一句为什么用.env而不是直接改docker-compose.yml因为.env里放的是密钥、令牌这类敏感信息它天然不会被提交到 git 仓库.gitignore里一般已经忽略了而且以后想切换不同环境测试、生产只需要替换这一个文件。这种做法在专业团队里也是标准操作不是 ClawdBot 独有。3.2 修改 .env 配置打开.env文件这是整个安装过程的核心。我当时的配置长这样# 模型接口配置 API_BASE_URLhttps://api.example.com/v1 API_KEYsk-xxxxxxxxxxxxxxxx MODELclawdbot-pro # 服务配置 BOT_PORT8080 ADMIN_TOKENplease_change_me_to_a_long_random_string # 功能开关 CRON_ENABLEDtrue SEARCH_ENABLEDfalse逐个说明API_BASE_URL填你使用的模型服务商提供的接口地址注意路径一般要带/v1。我一开始漏掉了这个后缀结果调用模型时直接 404。这个地址不用写成某个固定厂商的只要是 OpenAI 兼容格式的接口理论上都能用。API_KEY是调用模型的密钥。这里必须提醒一句任何情况下不要把密钥写进博客、贴进聊天群或者提交到公开仓库。密钥泄漏的代价不仅仅是被人刷额度更可能被人拿去调用模型服务制造违规内容最后账单算在你头上。MODEL填你购买的模型名称。不同服务商的模型命名差异很大一定要去服务商文档里确认填错了会出现模型不存在或者响应格式异常。我一开始填了个自以为是的名字日志里报Model Not Found查了五分钟文档才改正。ADMIN_TOKEN是访问 ClawdBot 管理接口的令牌相当于这个助手的“管理员密码”。务必改成一个足够长的随机字符串可以用openssl rand -hex 32生成然后粘进去。这个令牌不要和 API_KEY 共用同一个值职责分离。时区相关的变量我没有单独列出来但强烈建议你在.env末尾追加一行TZAsia/Shanghai否则定时任务按 UTC 时间触发每天早上九点的早报会变成下午五点很影响体验。3.3 编写 docker-compose.yml 并启动服务仓库自带的docker-compose.yml基本不用大改但为了让你彻底搞懂它干了什么我把改完的版本贴出来version: 3.8 services: clawdbot: image: clawdbot/clawdbot:latest container_name: clawdbot restart: unless-stopped ports: - 18080:8080 environment: - TZAsia/Shanghai - LANGC.UTF-8 env_file: - .env volumes: - ./data:/app/data - ./logs:/app/logs这个文件里最关键的三个点一是restart: unless-stopped。这行配置让 Docker 在容器崩溃、服务器重启后自动把服务拉起来。没有这行服务器重启后 ClawdBot 就静悄悄死了你还得手动docker compose start那就谈不上 24/7 了。二是env_file指向.env。容器启动时会把里面的变量自动注入环境ClawdBot 进程读取环境变量完成初始化。这样我们不用改任何代码生产环境的配置就落到了宿主机上。三是volumes的映射。./data:/app/data和./logs:/app/logs是持久化目录。ClawdBot 的数据库文件、会话状态、日志都写到容器内部如果不映射出来一旦容器被删除所有数据灰飞烟灭。映射到宿主机后迁移和备份都方便。配置文件就位后执行启动命令docker compose up -d第一次启动会拉取镜像时间取决于网络状况。拉完后看到Container clawdbot Started表示容器已经起来了。接着看启动日志docker compose logs -f clawdbot日志里如果出现bot online或者类似的关键字恭喜你基础部署已经成功。3.4 验证服务是否真的可用服务起来了不代表它真的能干活至少要做两个验证。第一个是健康检查接口用 curl 打一下curl -s http://127.0.0.1:18080/api/v1/healthz正常会返回一个 JSON里面通常包含status: ok和版本号。第二个是模型连通性验证在 ClawdBot 管理接口里发一条测试消息看日志里是否出现模型返回的内容。这里我要强调一个容易忽略的点如果curl返回Connection refused不要急着怀疑 ClawdBot先确认 Docker 容器状态是Up再看端口映射是否正确。我遇到过最坑的情况是容器端口映射写成了8080:8080但宿主机 8080 被另一个服务占了导致映射失败日志却显示容器正常——排查了半天才发现是端口冲突。4. 接入聊天平台让助手真正“开口”4.1 梳理接入逻辑ClawdBot 本身不包含聊天界面它对外提供的是 HTTP API 和平台回调接口。换句话说你平时在聊天窗口里看到的 ClawdBot实际上是通过钉钉、飞书这类平台的“自定义机器人”能力实现的平台收到用户消息后把消息内容 POST 到 ClawdBot 的回调地址ClawdBot 处理完再把回复 POST 回去。所以整个接入链路是三部曲创建平台机器人、拿到回调凭证、把凭证填到 ClawdBot 配置里。需要注意的是ClawdBot 支持钉钉、飞书、企业微信等平台不同平台的创建步骤大同小异我以钉钉为例分享完整流程其他平台按类似逻辑操作即可。4.2 创建钉钉机器人并配置回调在钉钉开放平台创建一个企业内部应用然后添加机器人能力。创建完成后你会得到三个关键信息AppKey、AppSecret 和机器人编码。然后到 ClawdBot 的配置里新增一个通道把这三个信息填进去。填的时候注意回调地址要填成你的服务器公网地址加端口比如http://你的域名或IP:18080/api/v1/platforms/dingtalk/callback。这一步有个很容易翻车的点公网回调地址必须能被钉钉服务器访问到。如果你的服务器在防火墙或安全组里没有放行 18080 端口钉钉发的消息会直接超时机器人看起来像是“哑了”。我一开始忘了放行安全组调试了半天最后打开安全组端口后立刻通了。为了安全建议在钉钉后台里把机器人的回调加签密钥也配置好然后在 ClawdBot 对应配置项里填入同一个密钥。这样过来的请求会带签名校验能有效防止别人伪造消息调用你的机器人。4.3 配置角色人设与多模型路由接入平台之后ClawdBot 已经能和你对话了但默认人设非常枯燥像是和一个 API 文档聊天。ClawdBot 提供了角色人设配置项在.env或管理界面里设置BOT_PERSONA你是一个严谨又接地气的私人助理回答问题简洁、有条理必要时给出操作建议。这一行对体验的提升是肉眼可见的。默认人设下同样的提问回复风格像机器翻译设置人设之后回复明显更有针对性。多模型路由也是我一直开着用的功能ClawdBot 支持配置主模型和备用模型当主模型接口超时或报错时自动切换到备用模型。配置方式是在.env里追加MODEL_BACKUPmodel-name-2 API_BACKUP_KEYsk-xxxx API_BACKUP_URLhttps://api.example.com/v1这两个模型可以是同一家的不同规格也可以是不同服务商。我实测下来切换会造成两秒左右的延迟但总比直接报错让用户干等着强。5. 7×24 小时稳定运行的守护配置5.1 开机自启与崩溃重启ClawdBot 能长时间跑起来靠的是 Docker 的restart: unless-stopped。这个策略的含义是只有当进程被手动docker compose stop停止过Docker 才不重启它如果是容器内部崩溃、被 OOM killer 杀掉、服务器重启它都会自动拉起。但这只是第一道防线。如果 ClawdBot 依赖的模型接口连续失败容器可能陷入“启动→失败→重启→再失败”的循环。这时候光看容器状态是Up不够要配合健康检查才能防患于未然。我给 compose 服务加了一段健康检查配置healthcheck: test: [CMD, curl, -f, http://localhost:8080/api/v1/healthz] interval: 60s timeout: 5s retries: 3 start_period: 20s通过docker compose ps可以看到容器健康状态从健康检查能及时发现服务“半死不活”的情况而不是等用户来抱怨才反应过来。5.2 日志管理与轮转策略常驻服务的另一个坑是日志膨胀。ClawdBot 默认会把所有对话记录和系统日志写到/app/logs映射到宿主机就是/opt/clawdbot/logs。如果不做限制日志文件一个月就能涨到几个 G把小硬盘塞满。我采用了两层策略。第一层是让 Docker 限制容器日志大小在 compose 里加logging: driver: json-file options: max-size: 20m max-file: 5这样容器内部打给 Docker 的日志最多保留 100M。第二层是宿主机上对logs目录设置 logrotate。简单写一个/etc/logrotate.d/clawdbot配置/opt/clawdbot/logs/*.log { daily rotate 7 compress missingok copytruncate }copytruncate这个参数很重要ClawdBot 进程可能一直持有日志文件的写入句柄直接mv或者rm会导致日志不再写入copytruncate会先复制再截断原文件不影响进程写日志。这是我在实际运维里踩过的坑第一次没加这个参数第二天发现日志全没了。5.3 升级与回滚ClawdBot 的迭代节奏比较快差不多一两周就会发一个新版本。升级步骤非常简单docker compose pull docker compose up -d它会拉取新镜像并用新镜像重建容器数据目录里的内容不会丢。但请记住一句话升级之前一定先备份数据目录。ClawdBot 的会话数据、定时任务配置都存在./data下万一新版出了兼容问题你还能快速回滚。回滚的方案有两个如果你知道上一个能用的镜像版本号直接修改 compose 里的image标签为旧版本然后重新up -d如果你之前的操作已经把容器删除也可以从备份恢复./data目录。5.4 数据备份的极简方案我现在的备份方案朴素但可靠每天凌晨打包./data和./logs目录保留七天。写一个 cron 任务0 3 * * * tar -czf /backup/clawdbot-$(date \%F).tar.gz -C /opt clawdbot/data clawdbot/logs find /backup -name clawdbot-*.tar.gz -mtime 7 -delete不要小看这个简单粗暴的打包方案。我已经记不清有多少次因为一时偷懒没备份然后在升级、调试、误操作之后追悔莫及。这种几行代码就能完成的备份任务是 24/7 服务的最后底牌。6. 常见问题与排查实录6.1 容器反复重启或健康检查失败现象docker compose ps显示容器状态在Restarting和Up之间反复横跳。处理步骤先用docker compose logs --tail 50 clawdbot看最新的报错。我遇到过的原因按概率排序第一是 API_KEY 配错了模型接口返回 401进程初始化失败主动退出第二是模型名MODEL填错接口返回 404 或Model Not Found第三是端口被占用容器端口映射失败。定位到具体原因后修改.env或 compose 文件然后docker compose up -d --force-recreate注意一定要加--force-recreate否则 Docker 可能沿用旧配置改了半天没效果。6.2 模型请求超时或返回空现象机器人能收到消息但回复很慢或者直接什么都不回复。排查思路分两步先看日志里请求模型那一段的耗时和状态码再测试模型接口的连接性。如果超时集中在每天某个时间段通常是模型服务端负载过高如果是一直超时大概率是API_BASE_URL网络通路问题。可以临时切换到备用模型确认是本服务问题还是模型服务问题。另外ClawdBot 有一个请求超时配置项默认值可能偏短。如果你接的模型思考链比较长建议适当调大REQUEST_TIMEOUT120我一开始没调这个参数遇到需要长思考的问题时机器人经常“沉默”后来改成 120 秒就好了。6.3 端口冲突与服务不可达现象curl http://127.0.0.1:18080/api/v1/healthz直接拒绝连接但容器状态正常。先执行docker compose ps看端口映射那一列确认是0.0.0.0:18080-8080/tcp。如果冒号左侧不是 18080说明你的 compose 文件里映射端口被改过。如果映射正确再检查宿主机防火墙和云安全组。命令ss -tlnp | grep 18080能看到监听就说明端口是通的不通就查防火墙。还有一种极端情况服务器本身开启了 SELinux容器网络被限制执行setenforce 0临时测试如果通了再考虑写允许规则。6.4 内存或硬盘空间告急现象运行几天后 ClawdBot 突然挂掉查看系统日志发现Out of memory或磁盘带满。内存不足的话先看是 ClawdBot 吃内存还是 Docker 其他容器吃内存。ClawdBot 长期运行后内存缓慢增长通常和对话历史缓存有关。解决办法是给容器设置内存上限deploy: resources: limits: memory: 512M设置了上限后即使出现内存泄漏也只是容器被杀后重启不会拖垮整台服务器。硬盘满的话按 5.2 节的日志轮转处理然后清理 Docker 的无用镜像和容器缓存docker system prune -f6.5 定时任务不触发现象CRON_ENABLEDtrue配好了但每天早上该推送时没有响应。优先检查时区。定时任务的表达式用的是本机时区如果你把TZAsia/Shanghai写在.env里但 compose 文件里没有把它传给容器环境那容器内依然是 UTC。我建议时区在 compose 的environment和.env两处都配一遍双保险。其次检查定时任务的推送目标是否配置正确。ClawdBot 的定时消息不是直接丢到某个人聊天窗口里而是推送给你设定好的群或会话配置里有一个目标会话 ID填错了就会“静默失败”。写在最后的几句体己话整个流程走完我最深的感受是ClawdBot 这东西本身不难装难的是把它真正“用起来”。安装只是半小时的事但你要花时间想清楚它怎么融入你的工作流——是替你盯群里的关键词、是每天早上给你一封摘要、还是让你在手机上和服务器对话。我目前最满意的搭配是钉钉群机器人加两个模型互为备份再配一个每天九点的早报任务。如果你也打算照着我这条路走建议从最小的功能开始验证别一上来就堆配置跑通了再加功能。另外给ADMIN_TOKEN和API_KEY留一份纸质或者加密笔记备份这个小习惯关键时刻能救命别问我是怎么知道的。