十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenClaw+Cloudflare Tunnel+Zero-Trust:搭建可远程访问的私有AI智能体

OpenClaw+Cloudflare Tunnel+Zero-Trust:搭建可远程访问的私有AI智能体 如果你也和我一样手里跑着一个本地部署的AI智能体却总是因为“人不在电脑前”而用不上它那这篇文章应该能帮你省下至少两天的折腾时间。核心主角是开源的ClawdBot社区里现在更多直接叫 OpenClaw——一个可以接微信、飞书、钉钉通过大模型“干活”的 Agent 框架另外两个配角是 Cloudflare Tunnel 和 Zero-Trust一个负责把本地服务安全暴露到公网一个负责给公网访问加门禁。这套组合搭完之后我在手机上就能唤起自己部署的 OpenClaw出门在外也能随时打开它的控制台IM 里丢一条消息给它就能让它跑任务体验上已经接近那些“云上托管”的商业 Agent 产品但数据和模型资源全在自己手里。这篇保姆教程不假设你有任何公网 IP、服务器或网络工程基础只要求你有一台能跑 Node.js 的电脑、一个域名、以及愿意跟着操作指南一步一步来。我把自己从零搭到跑通的完整过程、踩过的坑、每个坑背后的原因都写了出来。1. 为什么是这组搭配三个组件各自解决什么问题1.1 ClawdBotOpenClaw能接 IM、能写 Skill 的开源 Agent 框架OpenClaw 是一个开源智能体运行框架核心思路是把大模型的能力装进一个可以“动手执行任务”的框架里。它不是某个固定的聊天机器人而是一个壳模型可以换能力可以通过 Skill 无限扩展。社区里有人拿它写小说有人让它修复 ComfyUI 的环境问题有人给它写 Skill 接各种第三方 API还有人靠 Active Memory 给它做长期工作记忆。我当时看上它就三点私有部署。模型 API Key、对话记录、Skill 逻辑全部存在自己的机器上不经过第三方平台。渠道灵活。官方支持接入飞书、钉钉社区也有大量微信相关的实践。模型中立。DeepSeek、千问、通义、本地模型、NVIDIA NIM甚至 OpenAI 兼容接口都可以接入不像某些产品锁死在自家模型上。实际上手之后我发现OpenClaw 的日常使用可以很轻配好模型写好一个 Skill然后在 IM 里发一句“帮我查一下某个 API 的文档并整理成摘要”它就能自己拆解任务、调用工具、返回结果。这个体验要远好于单纯在网页对话框里聊大模型。1.2 Cloudflare Tunnel把本地服务安全搬到公网的“管道”本地部署最大的麻烦是“别人访问不了你”。没有公网 IP 的情况下传统套路是路由器端口映射或者用第三方内网穿透工具。前者要求运营商给你公网 IP后者通常限速、限流量免费版还强制绑定域名不稳定。Cloudflare Tunnel 的思路完全不同在本地跑一个cloudflared进程由它主动向 Cloudflare 边缘节点建立一条出方向的加密隧道。外部用户访问你的自定义域名时请求会先到 Cloudflare 边缘再由边缘通过隧道转发到本地服务。这样做有几个实打实的好处不需要公网 IP也不需要路由器上做任何端口映射。出口方向由你的程序发起家里网络、公司网络、虚拟机里都能跑。自带 HTTPS不用自己申请证书。免费额度对这个场景完全够用。你可以把它理解成你的电脑和 Cloudflare 之间常年保持着一条加密管道别人访问你的域名时Cloudflare 负责把请求“塞进管道”递到你家电脑的服务上。别人看到的是 Cloudflare 的 IP看不到你本机的真实 IP。1.3 Zero-Trust给服务加一道身份门禁隧道把服务暴露到公网之后随之而来的是新的问题任何人都可能通过域名访问你的 WebUI。OpenClaw 的控制台如果裸奔在公网上不仅数据会被看光还有可能被当成肉鸡别人通过它调用你的模型 API那是真金白银的消耗。Cloudflare Zero-Trust也叫 Cloudflare Access做的事情是在流量到达你的服务之前先做一次身份验证。用户访问域名时先看到 Cloudflare 的登录页输入邮箱收到一次性验证码验证通过之后Cloudflare 才把请求转发到隧道本地。也就是说即使你的服务本身完全没有账号体系也能获得一层和 Cloudflare 安全体系同级的外层防护。三个组件加在一起的完整链路是用户访问域名 → Cloudflare 边缘检查 Zero-Trust 策略 → 通过后进入隧道 → 到达本地 OpenClaw。任何一环都挡在服务之前风险面被压缩到最低。2. 零基础环境准备版本、运行方式以及最容易卡住的地方2.1 先确认 Node.js 版本这个项目对运行时要求非常严格OpenClaw 对 Node.js 版本的要求很细22.22.3 23、24.15.0 25或者25.9.0。这和我平时见到的那种“随便装个 LTS 就行”的开源项目完全不同。我一开始用的 Node 20启动时直接报错提示版本不匹配。后来切到 Node 22.22.3 之后才正常。检查版本用node -v如果版本不对强烈建议用 nvm 管理多版本。macOS/Linux 用 nvmWindows 用 nvm-windows。安装好后切换到指定版本nvm install 24.15.0 nvm use 24.15.0这里有个细节Windows 用户在安装新版本 Node 之前最好把旧版本先卸载干净否则可能出现“装了新版但node -v还是旧版”的诡异问题。我遇到过好多次基本都是 PATH 环境变量顺序或者 npm 全局 bin 目录残留导致的。2.2 本地源码运行还是 Docker两条路线怎么选OpenClaw 有两条主流部署路线源码运行和 Docker 运行。源码运行适合需要二次开发、调试 Skill、快速改代码的场景。大致流程是git clone openclaw仓库地址 cd openclaw npm install npm startDocker 运行适合不想污染宿主机环境、或者希望快速迁移的场景。社区里有大量关于“Mac mini Docker 本地部署”和“VM 虚拟机安装”的讨论。用 Docker 的好处是版本一致性可以在不同机器上得到完全相同的运行环境。我个人的建议是如果你只是拿它当工具用直接 Docker如果你想给 OpenClaw 写自定义 Skill、做二次开发源码运行更方便因为改完代码能立刻在终端看到输出调试体验好很多。如果是在 VM 里用 Docker 部署注意嵌套虚拟化的性能损耗内存至少给到 4GB 以上否则模型加载和构建过程会非常卡。2.3 Windows 上两个高频报错及处理Windows 用户最容易遇到的两个问题热词里都出现了。第一个是oneclaw node runtime not found。这个报错看起来像是“找不到 Node”实际上 OpenClaw 启动时会对运行时版本做校验校验失败就会报这个。常见处理是彻底卸载旧 Node安装符合版本矩阵的版本然后重启终端。另外检查一下 npm 全局路径npm config get prefix如果前缀指向的是一个不存在的目录后面的npm install -g都有问题。第二个是failed to remove ~\.openclaw: error: ebusy: resource busy or locked, unlink。这个错误几乎只出现在 Windows 上。原因是有进程占用了~/.openclaw目录下的文件。最常见的占用者是还在运行的 OpenClaw 进程、Node.js 进程、代码编辑器VSCode 看着不占实际上会有文件监听、以及安全软件的全盘扫描。解决步骤任务管理器里结束所有node.exe进程。关闭正在编辑 .openclaw 目录下文件的编辑器。如果还不行临时退一下安全软件或者把~/.openclaw目录加入实时扫描排除清单。确认没有进程占用后再手动删除或重新初始化。这个坑的根源在于 Windows 对文件锁的处理方式和 Linux/macOS 不一样。很多在 Linux 上能正常删除的文件在 Windows 上就是删不掉。遇到 EUSY不要硬删先找“谁锁了文件”。2.4 数据目录与配置目录OpenClaw 默认会在用户目录下创建~/.openclaw目录用来存放配置、日志、Skill、Active Memory 等数据。如果你之前装过旧版本新版本启动时可能会因为配置结构变化而报错。此时建议先备份旧目录再让其初始化一份全新配置mv ~/.openclaw ~/.openclaw_backup备份之后重新启动 OpenClaw它会自动生成一份默认配置。确认没问题后再把自己需要的模型配置手动迁移回去。这个操作能规避掉非常多“灵异问题”因为大部分升级场景下的报错都和旧配置里的字段不兼容有关。3. 让 OpenClaw 正常“开口说话”模型配置与多模型切换3.1 模型供应商与 API Key 配置环境准备好之后第一步就是配置模型。OpenClaw 支持多种模型供应商包括 DeepSeek、千问通义、OpenAI 兼容接口、本地模型、NVIDIA NIM 等。配置文件的格式因版本而异但核心字段基本一致model: provider: deepseek apiKey: sk-xxxx model: deepseek-chat社区里很多人用千问的免费 token 跑通基础对话也有人在本地跑模型做完全离线场景还有人通过 NVIDIA NIM 接入专业领域的推理能力。如果你刚开始我建议先挑一个你已经有的 API Key 的供应商配好之后不要急着切换先把对话跑通。这里需要特别提醒模型供应商的 API 地址是否可达是你自己网络环境和供应商决定的和 OpenClaw 框架本身无关。如果发现配了 API Key 之后请求超时先用其他工具或命令行单独测试该模型的 API 连通性确认没问题后再排查 OpenClaw 侧的配置不然很容易在错误的方向上浪费时间。3.2 “unknown model”与“agent failed before reply”的根因热词里有一条很典型的报错unknown model: deepsee。这个基本就是模型名写错了。DeepSeek 官方 API 里的模型名通常是deepseek-chat或deepseek-reasoner不会是deepseek或deepsee这样简写。多一个字母、少一个字母模型服务端都会直接拒绝。还有一条高频报错agent failed before producing a reply。遇到这个先不要怀疑框架坏了先确认API Key 是否正确、是否有余额。模型名称是否在该供应商的模型列表里。网络是否能正常访问模型 API 服务。如果是新加的供应商确认该供应商的接口格式和 OpenClaw 要求的是否一致。我的排查经验是先绕开 OpenClaw直接用 curl 或脚本调用一次模型 API确认可以返回内容之后再说。如果单独调用都不通问题出在模型侧如果单独调用通、进了 OpenClaw 不行再去看配置文件的 model 字段和 provider 名称是否匹配。还有一个容易被忽略的点“zero token”或新初始化的环境里如果还没生成会话上下文第一次对话可能因为初始化的原因失败。多试一次或者清掉~/.openclaw下的缓存目录再试往往就好了。3.3 多模型切换与默认模型OpenClaw 支持多模型配置也就是说你可以在一个实例里同时配好 DeepSeek、千问、本地模型然后按需切换。切换可以在 WebUI 里操作也可以通过在对话中发送特定指令或者在配置文件里指定默认模型。我的建议是把最常用、最稳定的模型设为默认其他模型作为备用。比如我默认用 DeepSeek 做日常任务因为便宜、速度快写长文或需要更强推理时切到更强模型本地模型只在调试 Skill 或者网络不可用时用。配置多个模型时要保证每个模型的provider、apiKey、model三件套都齐全。少一个切换时会直接报模型初始化失败。这种问题不好排查因为报错信息不一定指向具体是哪个模型配置没写完。3.4 Control UIWebUI无法启动的排查OpenClaw 的 Control UI 是管理界面能在浏览器里查看会话、切换模型、管理 Skill、查看 Active Memory。热词里出现openclaw control ui did not start启动成功后却没有打开浏览器页面或者页面完全打不开。我遇到的常见原因有三个终端窗口没有打印出 UI 地址。此时看启动日志里有没有http://localhost:端口之类的输出如果有手动复制到浏览器。端口被占用。OpenClaw 的 UI 端口如果已被其他服务占用UI 进程会启动失败。换个端口或者把占用端口的进程关掉。首次启动时需要下载前端依赖资源如果网络不好前端文件加载不完整浏览器里只显示空白页。遇到这种情况清掉浏览器缓存硬刷新一次还不行就重启 OpenClaw。注意区分 API 端口和 UI 端口。API 端口是给 IM 渠道和外部调用用的UI 端口是管理界面用的两者不能搞混。Cloudflare Tunnel 转发时也必须转发到正确的端口转发错了会看到 521 或 523 错误。4. 让公网能访问到本地Cloudflare Tunnel 完整配置4.1 前置条件域名、DNS、cloudflared配置 Cloudflare Tunnel 之前你需要三样东西一个 Cloudflare 账号。一个域名且域名的 DNS 托管在 Cloudflare。本地安装cloudflared命令行工具。安装cloudflared很直接。macOS 用 Homebrewbrew install cloudflaredLinux 可以下载官方二进制curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared chmod x cloudflared sudo mv cloudflared /usr/local/bin/Windows 就下载cloudflared-windows-amd64.exe改名成cloudflared.exe放到一个固定目录里并把该目录加入 PATH。安装完成后验证cloudflared --version4.2 创建隧道并把域名指向本地服务第一步登录 Cloudflare 并授权域名cloudflared tunnel login这条命令会弹出浏览器选择你的域名授权之后会在~/.cloudflared/下生成一张证书文件。第二步创建隧道cloudflared tunnel create openclaw创建完成后会在~/.cloudflared/下生成一个 JSON 凭据文件。这个文件相当于隧道的身份证别删。第三步把域名路由到隧道cloudflared tunnel route dns openclaw claw.example.com这条命令会在你的 DNS 里自动创建一个claw.example.com的 CNAME 记录指向openclaw.cfargotunnel.com也就是告诉 Cloudflare这个域名的流量要进 openclaw 这条隧道。4.3 用 config.yml 管理入口隧道默认不知道要把流量转发到本机的哪个端口所以需要创建一个配置文件~/.cloudflared/config.ymltunnel: openclaw credentials-file: /Users/yourname/.cloudflared/隧道ID.json ingress: - hostname: claw.example.com service: http://localhost:3000 - service: http_status:404注意两个细节tunnel字段填隧道名称不是域名。credentials-file的路径要绝对路径Windows 上注意路径分隔符。ingress列表最后一定要有一条兜底规则返回http_status:404。如果没有兜底配置校验会报错。如果你的 OpenClaw UI 端口不是 3000把它改成实际端口。想同时暴露 API 端口可以再加一条 hostname 指向另一个域名或子路径ingress: - hostname: api.claw.example.com service: http://localhost:3001 - hostname: claw.example.com service: http://localhost:3000 - service: http_status:404配置文件改好之后检查一下cloudflared tunnel ingress validate4.4 隧道跑起来之后怎么验证和排障启动隧道cloudflared tunnel run openclaw如果一切正常你会看到类似Registered tunnel connection的日志。这时在浏览器里访问https://claw.example.com应该能打开本地 OpenClaw 的界面。如果打不开先看本地访问是否正常curl http://localhost:3000如果本地正常但公网不行大概率是隧道配置问题。浏览器报 521 表示 Cloudflare 无法连接到你本地服务常见原因是 config.yml 里的 service 端口写错或者 OpenClaw 的启动地址绑定了127.0.0.1外部无法通过隧道的虚拟网络访问。后者需要在启动参数里把监听地址改成0.0.0.0。我在这上面栽过一次OpenClaw 启动时默认绑定 localhostTunnel 这边一切正常但公网始终访问不了。后来发现 cloudflared 发出的请求到不了服务一看日志服务只监听了回环地址。改成0.0.0.0后立刻好了。如果你希望隧道一直在后台跑可以把它安装成系统服务cloudflared service install安装后会注册为开机自启的服务管理起来省心很多。5. 给服务加锁Zero-Trust 访问策略配置5.1 创建 Access 应用与访问策略隧道通了之后如果你直接去访问claw.example.com会发现没有任何登录过程服务裸奔在公网。这时候就需要 Zero-Trust 上场。登录 Cloudflare 控制台进入 Zero Trust 板块。首次使用会要求创建一个团队名字免费版即可。然后按下面步骤操作在左侧菜单找到Access Applications。点击Add an application选择Self-hosted。Application 名字随便填比如 “OpenClaw Console”。Session duration 默认 24 小时可以按需缩短。下一步设置 PolicyPolicy name: Only Me Action: Allow Include: Emails - 你的邮箱保存之后再访问claw.example.com会出现 Cloudflare 的登录页。输入邮箱会收到一次性验证码验证通过后才会放行到本地 OpenClaw。这一步做完你的 WebUI 就有了身份门禁即使服务本身没有账号体系也不是谁都能访问的了。5.2 IM 回调地址被拦截怎么办Service Token这里有个大坑OpenClaw 接入飞书、钉钉后消息平台服务器会主动调用你的回调地址比如https://claw.example.com/webhook/feishu。这些服务器是“机器”没有邮箱无法完成交互式验证码登录请求会被 Zero-Trust 直接挡住。结果就是你往 IM 里发消息OpenClaw 完全没反应因为回调根本进不来。解决方案是使用 Zero-Trust 的 Service Token。在 Access 应用里给回调路径单独配置一条 Policy不要求邮箱登录而是要求请求头里带上 Service Token在 Zero Trust 控制台找到Access Service Auth。创建一个 Service Token系统会生成 Client ID 和 Client Secret。在 OpenClaw 的 IM 渠道配置里把回调请求头设置为CF-Access-Client-Id: 你的Client ID CF-Access-Client-Secret: 你的Client Secret在 Access 应用里新增一条 PolicyInclude 选择Service Token勾选刚创建的那个 TokenAction 设为 Allow。这样配置之后携带了正确 Service Token 的请求就能绕过邮箱验证直接进入隧道普通浏览器用户仍然需要邮箱验证。两者互不干扰。还有一种更省事但不太推荐的做法对回调路径设置 Policy 时 Action 选Bypass。Bypass 意味着该路径下的所有请求都不需要验证任何人都能调用你的回调接口。如果不做其他防御别人可以伪造请求给你的 IM Bot 下发垃圾消息。所以我建议至少用 Service Token不要直接 Bypass。5.3 更安全的细节域名、地区、IP 限制把 Cloudflare Tunnel 和 Zero-Trust 都搭好之后还有几个可以做的小加固邮箱域限制如果你的需求是团队协作Policy 里的 Include 可以直接填Emails domain: yourcompany.com这样只有该邮箱域下的人能访问。IP 限制如果你有固定的办公 IP可以在 Policy 里加一条 IP 范围限制再加一个“先匹配 IP、后匹配邮箱”的嵌套结构。国家地区限制Cloudflare 支持按国家维度控制访问但实际效果取决于你的用户分布。如果只有你自己用可以直接限制为当前所在国家。审计日志Zero Trust 的 Access 日志里会记录每次登录和拦截操作。哪天你发现访问量异常先来这里看。这些配置都不是必须的但能显著减少风险面。我的原则是WebUI 这类管理入口宁严勿松IM 回调这类机器访问入口宁用 Service Token不裸奔。6. 接入微信、飞书、钉钉的通用思路与合规提醒6.1 渠道接入的本质回调 URL 和消息路由OpenClaw 接 IM 渠道本质上是做三件事在 IM 开放平台创建应用获得凭证。把 IM 平台的事件回调地址指向你的公网域名比如https://claw.example.com/webhook/feishu。OpenClaw 收到回调后解析消息内容交给模型处理再通过 IM 开放平台的 API 把结果发回会话。所以在做 IM 接入之前Tunnel 加 Zero-Trust 这套公网链路必须先跑通。没有公网回调地址IM 平台根本找不到你的服务。这也是我把 IM 接入放在教程后面的原因——前置条件必须先就位。6.2 飞书、钉钉的配置步骤飞书和钉钉的逻辑比较接近以飞书为例在飞书开放平台创建企业自建应用开启机器人能力。在事件订阅里配置请求地址也就是你的公网回调 URL。配置校验方式。飞书第一次请求你的地址时会发一个 challenge 验证请求OpenClaw 正常情况下能自动响应前提是你的 Zero-Trust 策略没有把这次验证请求挡掉。所以第一次配置时最好先把对应路径临时放行调试通过后再收紧策略。在 OpenClaw 的渠道配置里填上飞书应用的 App ID、App Secret保存后重启。钉钉的流程类似只是回调校验方式和事件订阅格式有差异按官方文档操作即可。如果你在配置后向机器人发了消息却完全没有响应先去 Zero Trust 的 Access 日志里看回调请求是不是被拦截了。我之前排查过一次日志里密密麻麻全是 Blocked就是 Service Token 没配上。这里也再次印证了 5.2 节说的回调路径必须单独处理身份验证。6.3 关于个人微信自动化我的建议“OpenClaw 接入微信”是社区里非常热门的搜索词但我要先泼一盆冷水直接用个人微信账号做自动化的方案在安全性上有很大隐患轻则账号被限制功能重则封号。这不只是 OpenClaw 的问题是所有个人微信自动化工具的通病。正常做法是使用官方支持的接口比如公众号、企业微信或者用飞书、钉钉这类本身就对机器人开放程度较高的平台。如果你只是自己用我建议优先接飞书或钉钉开发体验顺畅得多。配合公网回调和数据隐私保护策略整个链路完全可控。7. 部署过程踩坑记录与完整排查链路7.1 本地服务正常但公网打不开先看状态码如果本地curl localhost:3000正常但公网域名打不开先看浏览器报错的状态码。Cloudflare 的错误页面一般会区分 521、522、523状态码含义常见原因521Cloudflare 无法连接源站本机服务没启动或监听地址不是 0.0.0.0522连接源站超时防火墙拦截或 cloudflared 无法访问本地端口523源站不可达本机 IP 变化隧道凭据对不上524源站响应超时本地服务处理请求超过 100 秒其中 521 最常见。我遇到过“OpenClaw 看起来在跑但绑定的是 127.0.0.1隧道访问不到”的情况改监听地址为 0.0.0.0 后解决。522 多见于 Windows 防火墙弹窗时点了“取消”导致 cloudflared 没有权限访问本机端口。523 则更多出现在笔记本睡眠唤醒之后本机 IP 变化了重启一下 cloudflared 就好。排查顺序可以固定为先看本地再看隧道最后看策略。7.2 IM 回调没反应先看 Access 日志IM 回调没有响应时不要急着改 OpenClaw 代码。我的排查链路是IM 开放平台的调试工具里手动触发一次回调看平台侧是否报错。看 OpenClaw 的终端日志有没有收到请求。看 Zero Trust 的 Access 日志有没有被 Block 的请求。用模拟请求手动调一次回调地址curl -X POST https://claw.example.com/webhook/feishu \ -H Content-Type: application/json \ -H CF-Access-Client-Id: Client ID \ -H CF-Access-Client-Secret: Client Secret \ -d {test:ok}如果模拟请求返回正常而 IM 平台的消息依然进不来问题基本出在 IM 平台侧的加密配置或事件订阅字段。如果模拟请求被拦就在 Access 策略里检查 Service Token 的匹配情况。7.3 VM / Docker 环境下的资源问题在 VM 里用 Docker 跑 OpenClaw有一个常见的隐蔽坑磁盘空间不足。VM 的虚拟磁盘默认不会自动扩容docker build拉镜像、构建层叠文件系统时空间很容易被占满然后出现莫名其妙的安装失败。先看一下磁盘占用docker system df df -h清理构建缓存可以用docker builder pruneMac mini 用 Docker 部署一般注意 Apple Silicon 的 arm64 架构镜像即可如果某些依赖没有 arm64 版本可能需要加--platformlinux/amd64但性能会有损耗。优先看镜像仓库有没有提供 arm64 版本。7.4 文档读取失败与上下文限制“OpenClaw 读取不了文档”是另一个高频问题。大部分时候不是“读不了”而是模型上下文不够长或者文档格式特殊扫描版 PDF、图片型文件模型本身不支持解析。这种情况下模型收到的内容是空的表现就是“读取不了”。排查思路先确认这个文档格式是否被当前模型支持。文本类直接复制内容到对话里测试PDF/Word 先转成文本再说。如果文档本身很大先切片或摘要再喂给模型。Skill 里接 API 时也要注意返回值大小超出上下文就会被截断。除了解析问题也要确认文档是在本地哪个路径。OpenClaw 运行在容器里时宿主机路径需要挂载进容器才能访问否则它压根看不到你的文件。这也是“本地能读、容器里读不了”的常见原因。最后说点实际的体会。这套组合真正跑通之后我再也没觉得“本地部署的智能体只能在电脑前玩”。出门在外手机微信/飞书里叫它干活和管理界面随时打开看日志数据始终在自己手里。回过头看搭建过程中最耗时间的不是任何一步的“操作”而是每一步的“默认值”——Node 版本、绑定地址、回调验证方式、Service Token每一个都在用默认方式把我带进沟里。希望这篇教程能帮你把这些默认值一次性全部避开。
返回列表