距离上一篇 OpenClaw 基础部署文章发出已经半个多月了期间我没有闲着把部署完成后遇到的各种问题挨个撸了一遍。先说结论OpenClaw 这个项目确实能做到永久免费运行前提是你愿意花点时间折腾而且它的文档远没有覆盖所有真实场景很多坑必须自己踩过才知道。这篇就当是续篇专门补上部署手册里不会写的那部分实战经验。这篇内容主要面对两类人一类是已经照着前一篇把服务跑起来但接下来遇到各种幺蛾子的人另一类是还在观望、准备从零部署的人。我会把从初始化服务器到日常维护整个链路中容易被忽略的环节全部拆开讲每一条都是真实遇到过、处理过、复测过的问题不是停留在理论层面的建议。1. 部署前的架构思路先看清楚整个系统的依赖关系OpenClaw 不是单体二进制它由核心服务、消息中间件、前端静态资源、向量存储等几个部分协同工作。如果只盯着某一个容器看出了问题你会陷入“重启一下试试”的死循环。所以我在内存规划、目录设计、网络划分这几件事上花了很大功夫它们决定了后续你排查问题时的难易程度。1.1 核心服务到底由哪些组件构成标准部署里最重要的两个部分一个是 OpenClaw 主程序一个是它的状态存储。主程序负责处理指令、调用模型接口、管理插件生命周期状态存储负责缓存会话上下文、任务队列和持久化的业务数据。如果你只部署了主程序而没有配好存储短期内可能看不出问题但运行几个小时后就会出现会话丢失、任务堆积不消费等怪现象。很多人会把数据库暴露到公网端口上这是我在踩坑记录里最想提醒的一点。除非你有非常强的安全隔离需求否则存储组件只需要在容器内网互相访问即可不需要映射宿主机端口。我在某台测试服务器上犯过这个错误结果日志里出现了大量陌生 IP 的探测连接最后只能关掉端口重刷防火墙规则。1.2 数据目录规划不然后面备份恢复会哭OpenClaw 的数据目录建议拆成三个独立目录业务数据目录、配置目录、临时文件目录。为什么拆开因为它们的备份策略完全不一样。业务数据需要频繁备份配置目录只需要在版本升级前备份一次临时文件目录则可以随意清理。混在一个大目录里做备份时要么打包了一堆无用的临时文件要么遗漏了关键配置很尴尬。我的目录方案是/home/user/openclaw/ ├── data/ # 业务数据含数据库文件、任务队列持久化 ├── config/ # 所有 yaml 配置、环境变量文件 ├── logs/ # 运行日志、审计日志 └── tmp/ # 可清理的临时文件给目录授权的时候注意一点不要在 root 权限下运行所有容器。我用的是宿主机上独立创建的普通用户执行 docker compose 命令数据目录的属主也改为这个用户。否则后期你在维护时会遇到文件无法修改、容器内进程创建的文件宿主机删不掉的问题。1.3 端口规划冲突问题的根源往往在这里OpenClaw 主服务默认监听 80 端口nginx 反向代理监听 443这并没有问题。但服务器上如果还跑了其他 Web 服务端口冲突就是必然的。我在某次部署中把 OpenClaw 映射到了宿主机的 8080结果容器内部仍然监听 80走了 nginx 的 location 转发后发现页面资源路径全部变成了根路径css 和 js 全部加载失败。这个问题的解决方案是在 compose 文件里保持宿主机端口和容器内部端口的映射一致或者干脆用 80 端口加配置里的子路径但很多前端应用不支持子路径部署你需要确认项目文档里是否声明支持。最稳妥的做法还是独占一个域名或者一个独立端口。2. 环境准备与初始化不是装个 Docker 就够了很多部署翻车不是因为 OpenClaw 本身的问题而是底层的容器运行环境不达标。新装的服务器往往缺少大量依赖比如 iptables 规则未初始化、overlay2 存储驱动没有启用、cgroup 版本不对这些都会让容器启动时爆出一堆莫名其妙的错误。2.1 服务器基础环境检查清单建议在部署前用下面这个命令集做一轮快速检查# 检查系统版本 cat /etc/os-release # 检查内核版本建议大于 5.x uname -r # 检查 CPU 架构arm 和 x86 的镜像包不一样 uname -m # 检查磁盘剩余空间建议至少 20G df -h # 检查内存大小单机部署建议不低于 2G free -h内存这一项我要重点说一下。OpenClaw 主程序加上存储组件在安静状态下的内存占用约为 600M 到 900M一旦开始处理长时间上下文的任务内存峰值会快速攀升到 1.5G 以上。如果你用的是 1G 内存的小机器需要额外配置 swap否则容器可能直接被 oom killer 干掉日志里只留下Killed两个字很多人看到这个直接懵了。2.2 Docker 与 Compose 插件安装我推荐使用 Docker 官方脚本安装省事、干净。安装完成后把当前用户加入 docker 组避免每次执行命令都要加 sudo。# 如果国内下载官方脚本慢可以多试几次或者错峰操作 curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # 添加当前用户到 docker 组 sudo usermod -aG docker $USER # 安装 compose 插件 sudo apt-get install -y docker-compose-plugin # 重新登录或执行 newgrp 让组生效 newgrp docker检查 Docker 是否正常docker version docker compose version这里有个小技巧——通过命令行安装后记得重启一下服务器或者至少sudo systemctl restart docker。我第一次部署时跳过了这一步结果 iptables NAT 规则没有自动生成容器虽然起来了容器之间却无法通信。2.3 换源问题镜像拉取失败的应对策略OpenClaw 的镜像体积不小主程序镜像大概在 1G 左右拉取时间受出口带宽影响明显。如果你在服务器上反复拉取失败或者下载到了一半就报错这时候不要干等优先检查 Docker 的镜像源配置。但这里也要强调一句不要从网上随便复制来源不明的镜像源脚本到生产服务器尽量使用自己熟悉、长期维护的公共仓库地址并且配置后立即验证镜像的完整性。修改/etc/docker/daemon.json{ registry-mirrors: [https://你的镜像源地址] }改完重启 Dockersudo systemctl daemon-reload sudo systemctl restart docker重启后先用一个小镜像比如hello-world验证拉取是否正常再拉 OpenClaw 的镜像。如果依然超时可以试一下分时间段拉取——我这边是凌晨时段拉大镜像的成功率明显更高。3. 核心踩坑记录从启动失败到数据丢失我把能踩的坑都踩了这一节是全文的重头戏。OpenClaw 的基础部署流程走完并不难难的是部署完成后让它在长时间运行中保持稳定。我把遇到的典型问题按影响程度排序每条都附了现象、原因和最终验证过的解决办法。3.1 配置文件的 YAML 缩进错误容器“假启动”的元凶YAML 的缩进问题在部署时极其隐蔽。配置文件里一个键值对缩进错一个空格OpenClaw 主进程可能不会立即报错而是直接跳过该配置项用默认值启动。表面上看容器状态是 running健康检查也通过但实际功能就是不正常。我遇到过的一个例子是model部分的配置写错了缩进导致整个模型配置没有被加载。启动日志里没有任何报错我还原了当时的错误写法model: provider: openai base_url: https://api.example.com/v1 api_key_env: OPENCLAW_API_KEY # 这里缩进少了一个空格 model_name: gpt-4o-mini就是少缩进了两个空格主进程就把api_key_env和model_name当成了base_url的子键后续读取模型名称时拿到一个 null所有对话请求都返回失败。排查这种问题最好的工具是在把配置文件挂载进容器之前先在宿主机上用yamllint做一次静态检查。我在宿主机上装了一个检查脚本每次修改配置后先跑一遍python3 -m yamllint config/config.yaml另外还要提一点OpenClaw 主程序对配置文件的更新并不都是热加载的。某些参数修改以后即使你看到了“配置已生效”的日志也不代表所有组件都拿到了新配置。最保险的做法是修改核心参数后重启关联容器。这条经验是我在改了某参数后服务看似正常、实测依然使用旧配置时得出的教训。3.2 模型 API 密钥校验失败的隐藏原因模型 API 接入时最常见的报错是 401 或 invalid api key但这并不全是密钥本身的问题。OpenClaw 通过环境变量注入密钥环境变量文件很容易在编辑过程中混入不可见字符或多余引号。我踩过的具体坑是配置环境变量时手滑把密钥写成了带引号的形式比如在.env文件里写了OPENCLAW_API_KEYsk-xxx。OpenClaw 调用模型接口时把完整的sk-xxx包括双引号都放进了 Authorization 头导致服务端校验失败。正确的写法应该是OPENCLAW_API_KEYsk-xxxxx不带引号、不带分号、前后没有空格。如果你使用的是带特殊符号的密钥比如#或$记得在.env文件里用单引号包起来但没有特殊符号时尽量不要加任何引号。还有一个隐蔽的坑是密钥在编辑工具中换行了。如果你用网页端的记事本编辑.envWindows 换行符会被带入文件容器内读取时会在密钥末尾多出一个\r照样会校验失败。处理办法是在宿主机上执行dos2unix .env或者用 vim 输入:set ffunix后保存退出。3.3 容器内时区与日志乱码问题默认情况下容器内的时区是 UTC中文环境下的服务器则是东八区这会导致两个问题一是日志里的时间戳和中国标准时间差 8 小时二是部分组件在输出中文日志时因为区域设置不对出现乱码。解决方式是在 compose 文件里给容器设置环境变量environment: - TZAsia/Shanghai - LANGC.UTF-8 - LC_ALLC.UTF-8设置完成后重启容器然后进入容器确认docker exec -it openclaw date执行date命令显示的时区应该是 CST。如果你挂载了宿主机的/etc/localtime到容器内同样注意需要配合TZ环境变量使用只挂载文件不设置环境变量部分使用 Golang 编写的服务依然读的是 UTC。3.4 数据卷权限异常重启容器后数据“消失”了另一个让我差点崩溃的问题是容器重启后之前创建的会话和配置像是全被清空了。排查到最后发现不是数据丢了而是容器内进程的用户 ID 和宿主机数据目录的属主不一致容器在写入数据时因为权限不足静默失败了。默认情况下容器内进程以 root 身份运行但如果你出于安全考虑在 compose 里指定了user: 1000:1000而宿主机数据目录是 root 所有就会发生无法写入的情况。相反的如果宿主机的目录是某个普通用户所有而容器内进程要求写入的是 root 身份也会产生很多权限相关的报错。最稳妥的做法是让宿主机数据目录的属主和容器内运行进程的用户 ID 保持一致。比如容器内运行用户是 UID 1000那么执行chown -R 1000:1000 /home/user/openclaw/data chown -R 1000:1000 /home/user/openclaw/config之后重启容器再写一条测试数据验证是否真的可以持久化。注意chown之后不要再通过宿主机的普通用户直接修改数据目录里的文件否则可能会出现新的属主不一致。3.5 磁盘空间被日志占满OpenClaw 容器默认把日志输出到 stdout如果你没有做日志轮转运行一段时间后/var/lib/docker/containers目录会飞速膨胀。日志文件动辄几 GB最终占满磁盘。表现出来就是所有操作都失败数据库写入报 disk full。我在宿主机上配置了 Docker 的日志清理策略写在/etc/docker/daemon.json里{ log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 } }配置完成后要重启 Docker 才会生效。注意只对之后新建的容器生效已经存在的容器需要重建才能应用新的日志策略。如果磁盘已经满了可以先手动清理大文件日志再执行配置更新。3.6 反向代理超时访问面板转圈或直接 504OpenClaw 的某些页面接口响应很慢比如加载会话列表的时候需要同时从存储组件拉取数据加上模型服务的依赖首次响应时间可能超过默认的 60 秒。Nginx 默认配置下超过 60 秒没有响应就直接返回 504。第一次遇到我还以为是 OpenClaw 卡死了反复看日志才发现它其实只是处理得慢被网关超时打断了。在 Nginx 的配置文件里调整超时参数location / { proxy_pass http://127.0.0.1:8080; proxy_connect_timeout 30s; proxy_send_timeout 120s; proxy_read_timeout 120s; }修改完成后重载 Nginx 配置sudo nginx -s reload再次验证慢接口是否正常返回。这个参数调整很重要尤其是未来你会给 OpenClaw 挂载更多外部扩展能力时接口响应时间会进一步拉长。4. 完整实操指南从零开始把 OpenClaw 部署到一台干净服务器这一节我会以一台全新的云服务器为例把完整流程走一遍。每一步都会说明目的和验证方式你可以直接照着执行也可以根据自己的环境做微调。4.1 初始化云服务器我用的是 Ubuntu 22.04 镜像拿到服务器后第一步是更新系统包sudo apt-get update sudo apt-get upgrade -y装几个后续需要用到的工具sudo apt-get install -y curl git vim unzip ufw配置防火墙只放行必要的端口sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable这里需要注意如果你的云服务商自带安全组规则UFW 只是在系统层面做了一次过滤两者需要保持一致否则你会发现某个端口在系统层面放行了但还是连不上。4.2 安装 Docker 环境按照 2.2 节的方式安装 Docker再用docker run --rm hello-world验证。验证输出里如果出现了Hello from Docker!说明 Docker 拉取镜像和运行容器的基本链路是通的。如果不通按 2.3 节的方式检查镜像源配置。4.3 创建项目目录并编写部署文件项目目录我统一放在/home/user/openclaw下。进入目录后创建 compose 文件cd /home/user/openclaw vim docker-compose.yml写一个最小可用的 compose 配置内容如下services: openclaw: image: openclaw/standalone:latest container_name: openclaw restart: unless-stopped ports: - 8080:80 environment: - TZAsia/Shanghai - LANGC.UTF-8 - OPENCLAW_API_KEY${OPENCLAW_API_KEY} volumes: - ./data:/data - ./config:/app/config depends_on: - redis healthcheck: test: [CMD, curl, -f, http://127.0.0.1:80/healthz] interval: 30s timeout: 5s retries: 3 redis: image: redis:7-alpine container_name: openclaw-redis restart: unless-stopped command: [redis-server, --appendonly, yes, --requirepass, change_me_redis_password] volumes: - ./data/redis:/data healthcheck: test: [CMD, redis-cli, -a, change_me_redis_password, ping] interval: 30s timeout: 5s retries: 3 networks: default: driver: bridge我特意加了健康检查配置。很多人忽略健康检查实际上它是判断容器是否“真正可用”的最直接手段。OpenClaw 的镜像里一般自带 curl如果你的镜像没有可以把test改成其他检测命令比如用 Python 的urllib。4.4 编写配置文件和环境变量创建.env文件填入你的实际配置OPENCLAW_API_KEYsk-你的密钥配置文件写在config/config.yaml里这里给出一个基础示例server: host: 0.0.0.0 port: 80 log_level: info model: provider: openai base_url: https://api.example.com/v1 api_key_env: OPENCLAW_API_KEY model_name: gpt-4o-mini storage: redis_host: redis redis_port: 6379 redis_password: change_me_redis_password redis_db: 0注意base_url里我用的是示例地址实际使用时要改成你所使用的模型服务的真实接口地址如果模型服务商的接口是 HTTPS 且证书正常保持默认即可。4.5 启动服务并验证启动前先做配置文件的 YAML 校验docker compose config这个命令会解析你写的 compose 文件如果语法有问题会直接报错提示。没有问题后再正式启动docker compose up -d等待容器拉取镜像并启动然后查看容器状态docker ps看到两个容器都处于Up状态后看日志确认没有明显错误docker logs -f openclaw最后发起一次测试请求。如果是面板服务直接浏览器访问http://服务器IP:8080能看到登录页说明服务已经正常。如果请求模型接口可以用命令验证curl -X POST http://127.0.0.1:8080/v1/chat/completions \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:你好}]}这种情况是 OpenClaw 本身提供兼容的接口端点时的测试方式具体以项目文档段为准但思路是通用的。4.6 配置 Nginx 反向代理与 HTTPS面板直接暴露 IP 加端口也能用但如果有条件我建议配一层 Nginx主要目的是统一入口、便于后面加证书。安装 Nginxsudo apt-get install -y nginx在/etc/nginx/sites-available/openclaw写配置server { listen 80; server_name your.domain.com; location / { proxy_pass http://127.0.0.1:8080; 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; proxy_connect_timeout 30s; proxy_send_timeout 120s; proxy_read_timeout 120s; } }启用站点并重载 Nginxsudo ln -s /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/ sudo nginx -t sudo nginx -s reloadHTTPS 部分我不展开讲思路是使用你信任的证书签发方式拿到证书后在 Nginx 配置里监听 443、配置证书路径并加一个 80 端口到 443 的跳转即可。5. 日常运维备份、升级、监控的闭环部署只是开始真正决定项目能否长期稳定运行的是运维。OpenClaw 这类自托管服务日常维护的重点就三件事备份、升级、监控。5.1 备份策略数据多副本才安全我用的是简单的定时任务脚本每天凌晨把数据目录打包并保留最近 7 天的副本。写一个备份脚本/home/user/openclaw/backup.sh#!/bin/bash BACKUP_DIR/home/user/backups DATE$(date %Y%m%d_%H%M%S) cd /home/user/openclaw docker compose exec -T redis redis-cli -a change_me_redis_password SAVE tar -czf $BACKUP_DIR/openclaw_$DATE.tar.gz data config find $BACKUP_DIR -name openclaw_*.tar.gz -type f -mtime 7 -delete加入 crontabcrontab -e # 每天凌晨 2 点执行备份 0 2 * * * bash /home/user/openclaw/backup.sh特别提醒千万不要在数据目录读写繁忙的时刻硬打包。先借助存储组件自身的持久化机制比如 Redis 的 SAVE/BGSAVE让数据落盘再打文件包否则容易备份出不一致的数据。5.2 平滑升级不要直接拉 latest 覆盖OpenClaw 的版本更新比较频繁latest标签会一直指向最新版。直接docker compose pull docker compose up -d虽然方便但风险很高——新版可能改动数据表结构、配置项名称或在启动时做数据迁移一旦失败意味着服务长时间不可用。我建议的升级流程是先触发一次手动备份。查看项目仓库的 Release 说明确认没有破坏性变更。再执行拉取和重启。如果容器启动失败立即执行docker compose down并恢复旧版本镜像。给镜像打固定标签是更安全的选择。比如当前用的是openclaw/standalone:1.4.2升级时先拉openclaw/standalone:1.5.0验证没问题后再把 compose 文件里的镜像版本改过来并重新 up。5.3 日志与健康状态监控没有监控面板也可以基于健康检查做最简单的状态判断。如果容器没有配置healthcheck可以用现成命令定期探测curl -s http://127.0.0.1:8080/healthz如果返回ok说明服务正常。再把这个探活命令接入你的告警工具例如通知机器人。我用的逻辑很简单连续三次探活失败就发一条通知消息到手机上运维睡得也踏实一点。日志这块重启之前先看一眼最近的错误日志很重要。很多问题在重启后就被新日志刷掉了你会失去唯一的排查线索。我用的是先复制再清理的策略比较笨但有效。6. 常见问题速查表把最常见的几个问题和解决办法整理成一张表方便现场排查参考。问题现象可能原因排查方法解决方式容器启动后立刻退出配置文件语法错误或环境变量缺失docker logs 容器名查看退出日志用 yamllint 检查配置核对环境变量镜像拉取超时网络波动或镜像源不稳定docker pull单独测试配置可用的镜像源错峰拉取外部访问面板打不开端口未放行或 Nginx 配置错误curl 127.0.0.1:8080本地先测检查云安全组和 UFW检查 Nginx 日志模型接口报 401密钥注入格式错误查看.env文件是否有引号或换行清掉引号执行dos2unix重启后数据没了数据目录属主不一致ls -n查看目录属主对比容器进程 UID执行chown -R对齐属主页面请求长时间卡住然后失败Nginx 代理超时观察 504 日志调整proxy_read_timeout参数磁盘空间被占满容器日志无限增长du -sh /var/lib/docker/containers配置日志轮转并手动清理大日志文件容器间无法通信没有共享自定义网络docker network ls检查在 compose 里声明共享网络排查问题的时候我一般习惯从上往下看日志先找服务启动阶段的错误后看请求处理阶段的错误。一条报错信息往往藏着一个根因不要看到报错就重启多收集几层日志再做判断。7. 关于工具和脚本的一些元经验在自托管部署这件事上工具选对能少走很多弯路。Docker Compose 是我最喜欢的单机编排工具它的学习成本不高一个docker-compose.yml文件就能把服务、网络、卷、健康检查全部定义清楚。新出的版本还支持docker compose config做静态校验强烈建议每次修改配置后都执行一遍。有一个细节值得单独拿出来说OpenClaw 的配置接口有时会把模板直接渲染到网页上你可以直接在面板里改配置。但面板里保存的配置和文件系统中挂载的config.yaml可能会产生冲突两者以哪个为准取决于项目的加载顺序。为了避免混乱我建议只在文件系统里维护一份配置通过 volumes 挂载进容器面板里的配置功能要么不开、要么作为只读展示。还有一点是关于扩展能力的安装方式。OpenClaw 支持插件、脚本和外部服务集成安装插件时尽量通过项目官方提供的渠道第三方来源的脚本在安装前要自己读一遍源码不要因为偷懒直接执行在线脚本。安全这件事需要始终绷紧弦。时间久了你会发现自托管这件事真正的价值不在于省钱而在于完全掌控自己的数据和运行逻辑。OpenClaw 的部署难度属于中等偏上有一定 Docker 基础的人大概一个下午就能跑起来但要做到长期稳定运行需要的是运维习惯和排错思路。最后分享一个我自己的小技巧每次操作前先在终端里敲一遍当前目录的路径并把所有 compose 操作统一到同一个项目目录下执行养成一个“所有操作都在项目目录里做”的习惯可以避免大量因路径不对导致的问题。