1. 企业云平台里把 Openclaw 跑成 HTTPS 服务,到底难在哪
Openclaw 是一个可以自托管的个人 AI 助手网关,能对接多种大模型、消息渠道和 Agent 工具,适合企业内部研发云平台给每位用户开一个独立实例。它默认只监听 loopback,也就是 127.0.0.1,这在单机本地用没问题,但一旦放到云平台上,用户要通过浏览器或客户端从外部访问,就必须解决三件事:容器怎么编排、流量怎么安全转发、证书怎么配。
我所在的环境是一个内部研发云平台,用户可以自助启动 Docker 容器,平台通过端口映射把服务暴露出去。直接暴露 Openclaw 的 18789 端口风险很大,因为它的控制台和 API 一旦被扫描到,攻击面相当可观。所以我的方案是在同一个容器里加一层 Nginx,用 HTTPS 对外,Openclaw 本体继续只绑 loopback,外部只能通过 Nginx 的 TLS 入口进来。
这篇文章会交付一套可复制的落地路径:docker-compose 片段、Nginx server 块、OpenSSL 自签证书生成命令,以及 https 访问、证书链校验、容器健康检查的验证动作。适合正在做企业内部 AI 平台、需要把 Openclaw 容器化并加上 HTTPS 的工程师跟做。下面所有命令和配置我都实际跑过,版本基于 Openclaw 2026.3.8。
2. 前置准备:TaoToken 接入与 Openclaw 模型配置
Openclaw 本身只是网关,真正干活的是背后的大模型。企业场景下模型来源通常有两种:自建推理服务,或者接一个统一的模型 API 网关。我这边用 TaoToken 作为模型接入层,它的好处是一个 Key 能覆盖多种模型,Openclaw 的 provider 配置里只要填 Base URL、Key 和 Model ID 三件套就行,不用为每个模型单独维护一套凭证。
TaoToken 的 API 地址是 https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为 OpenAI 兼容的 base_url 使用。你需要在控制台创建一个 API Key,然后把它写进 Openclaw 的 provider 配置。如果你还没建 Key,可以先去 API Keys 页面生成:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=openclaw_docker_nginx_openssl
Openclaw 的模型配置写在 openclaw.json 里,provider 段落大致长这样,把 baseUrl 指向 TaoToken,apiKey 换成你自己的,model 填你要用的模型 ID:
{ "providers": { "taotoken": { "type": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥", "models": { "default": { "id": "claude-sonnet-4-5", "name": "Claude Sonnet 4.5" } } } } }这里有个容易踩的点:baseUrl 结尾不要加 /v1,Openclaw 的 openai-compatible 适配器会自己拼路径,加了反而会变成 /v1/v1/chat/completions 导致 404。Model ID 要和你实际要调用的模型对齐,写错了会在请求时返回 model not found。如果你不确定该填哪个 ID,可以在模型对话页面先手动试一次,确认能通再写进配置:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=openclaw_docker_nginx_openssl
对于长期跑 Agent 或需要频繁编码调用的场景,Coding Plan 会比按量计费更划算,适合企业内部多人共用的网关型部署:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=openclaw_docker_nginx_openssl
前置准备做完后,你手上应该有三样东西:一个可用的 TaoToken Key、确认过的 Model ID、以及云平台的容器 IP(我这边是 172.18.193.247,你换成自己的)。接下来进入证书和 Nginx 配置。
3. 可复制配置:OpenSSL 自签证书 + Nginx server 块 + Dockerfile
这一节是全文的核心,所有片段都可以直接复制改 IP 使用。顺序是先生成证书,再写 Nginx 配置,再写 Openclaw 的 gateway 配置,最后用 Dockerfile 把 Nginx 和证书打进镜像。
3.1 生成云平台 IP 的自签证书
因为服务是通过云平台 IP 加端口访问的,证书的 SAN 里必须包含这个 IP,否则浏览器会报证书不匹配。先创建 openssl.cnf:
[req] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_req prompt = no [req_distinguished_name] countryName = CN stateOrProvinceName = Beijing localityName = Beijing organizationName = Example Inc. organizationalUnitName = IT commonName = 172.18.193.247 [req_ext] subjectAltName = @alt_names [v3_req] subjectAltName = @alt_names [alt_names] IP.1 = 172.18.193.247 DNS.1 = internal.example.com把 IP.1 换成你云平台实际的容器 IP,如果有多个入口 IP 就继续加 IP.2、IP.3。DNS.1 是可选的,如果你有内部域名解析也可以加上。
然后生成私钥和自签证书,有效期 365 天:
openssl genrsa -out myip.key 2048 openssl req -x509 -new -nodes \ -key myip.key \ -sha256 -days 365 \ -out myip.crt \ -config openssl.cnf \ -extensions v3_req生成完一定要验证 SAN 里确实带了 IP,这一步很多人跳过,结果浏览器一直报错:
openssl x509 -in myip.crt -text -noout | grep -A 1 "Subject Alternative Name"正常输出里应该能看到IP Address:172.18.193.247。如果没有,说明 openssl.cnf 的 alt_names 没生效,检查 -extensions v3_req 参数是否漏了。
3.2 Nginx server 块配置
Nginx 负责 TLS 终止和反向代理,把外部 HTTPS 请求转到 Openclaw 本体的 loopback 端口。创建 default.conf:
server { listen 18999 ssl http2; server_name 172.18.193.247; ssl_certificate /etc/nginx/certs/myip.crt; ssl_certificate_key /etc/nginx/certs/myip.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://localhost:18789; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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_read_timeout 3600s; proxy_send_timeout 3600s; } } server { listen 3001 ssl http2; server_name 172.18.193.247; ssl_certificate /etc/nginx/certs/myip.crt; ssl_certificate_key /etc/nginx/certs/myip.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://localhost:3000; 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_read_timeout 3600s; proxy_send_timeout 3600s; } }18999 端口转发到 Openclaw 的 18789,3001 端口转发到 OpenClaw-bot-review 的 3000。后者是一个轻量级 Web 仪表盘,能一览所有机器人、Agent、模型、会话的运行状态,内置像素风动画办公室,Agent 会化身像素角色在里面走动就座,运维的时候看着挺有意思。注意 18999 这个 server 块里带了 Upgrade 和 Connection 头,因为 Openclaw 控制台有 WebSocket 长连接,少了这两个头页面会一直转圈连不上。
3.3 Openclaw gateway 配置
openclaw.json 里的 gateway 段落决定了 Openclaw 监听在哪、允许哪些来源访问。关键是把 bind 设成 loopback,只让本机 Nginx 能连,外部一律走 Nginx:
{ "gateway": { "port": 18789, "mode": "local", "bind": "loopback", "controlUi": { "allowedOrigins": [ "http://localhost:18789", "http://127.0.0.1:18789", "https://172.18.193.247:18999" ] }, "auth": { "mode": "token", "token": "替换成你自己的长随机串" } } }allowedOrigins 里必须把https://云IP:18999加进去,否则从外部打开控制台会被 CORS 拦掉。token 用一段足够长的随机字符串,这是控制台和 API 的访问凭证,泄露等于把实例交出去。
3.4 Dockerfile 构建私有镜像
在本地建一个目录,把 default.conf、openclaw.json、certs 子目录(放 myip.crt 和 myip.key)都放进去。再创建一个 debian.sources 指定国内源,加速 apt 安装:
Types: deb deb-src URIs: https://mirrors.tuna.tsinghua.edu.cn/debian Suites: trixie trixie-updates trixie-backports Components: main contrib non-free non-free-firmware Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg Types: deb deb-src URIs: https://mirrors.tuna.tsinghua.edu.cn/debian-security Suites: trixie-security Components: main contrib non-free non-free-firmware Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg拉取 bot-review 代码,然后写 Dockerfile:
git clone https://github.com/xmanrui/OpenClaw-bot-review.gitFROM m.daocloud.io/ghcr.io/openclaw/openclaw:2026.3.8 USER root COPY debian.sources /etc/apt/sources.list.d/ RUN apt-get update && apt-get install nginx nano -y COPY default.conf /etc/nginx/conf.d/default.conf COPY certs/ /etc/nginx/certs/ COPY OpenClaw-bot-review/ /app/OpenClaw-bot-review/ RUN chown -R node:node /app/OpenClaw-bot-review USER node RUN npm config set registry https://registry.npmmirror.com WORKDIR /app/OpenClaw-bot-review RUN npm install WORKDIR /app构建镜像:
docker build -t openclaw:local .这里有个细节:npm install 必须在 USER node 之后执行,否则装出来的 node_modules 属主是 root,运行时 bot-review 会因为没有写权限报错。另外基础镜像用的是 2026.3.8 版本,Openclaw 迭代很快,升级时记得同步改这个 tag。
4. 验证请求:https 访问、证书链校验与容器健康检查
配置写完不算完,必须实际验证。这一节给出从启动到访问成功的完整动作。
先准备 docker-compose 片段,把镜像、端口映射、证书挂载都写清楚:
services: openclaw-gateway: image: ${OPENCLAW_IMAGE:-openclaw:local} ports: - "18999:18999" - "3001:3001" volumes: - ./data:/app/data restart: unless-stopped healthcheck: test: ["CMD", "curl", "-fk", "https://localhost:18999/"] interval: 30s timeout: 5s retries: 3启动:
git clone https://github.com/openclaw.git git checkout v2026.3.8 cd openclaw export OPENCLAW_IMAGE=openclaw:local docker compose up -d容器起来后,Nginx 不会自动跑,需要手动进容器启动一次:
docker exec -it -u root openclaw-openclaw-gateway-1 nginx然后做三项验证。
第一项,证书链校验。用 openssl s_client 连本地端口,看证书是否正确返回:
openssl s_client -connect 172.18.193.247:18999 -servername 172.18.193.247 </dev/null 2>/dev/null | openssl x509 -noout -subject -dates输出里应该能看到 subject 里的 CN 和证书有效期。如果报verify error:num=18:self-signed certificate,这是自签证书的正常提示,说明证书链本身是通的,只是没有受信任 CA 签发。
第二项,https 访问。浏览器打开:
https://172.18.193.247:18999/?token=你的token自签证书会弹安全警告,点继续访问即可。这时页面会提示device pairing required,这是 Openclaw 的设备配对机制,新设备首次访问需要批准。进容器操作:
docker exec -it openclaw-openclaw-gateway-1 bash openclaw devices list openclaw devices approve <requestid>把 list 里看到的 requestid 填进 approve,再刷新页面就能进控制台了。
第三项,容器健康检查。看 healthcheck 状态:
docker inspect --format='{{.State.Health.Status}}' openclaw-openclaw-gateway-1返回 healthy 说明容器内 curl 能通过 HTTPS 访问到 Nginx。如果一直是 starting 或 unhealthy,多半是 Nginx 没启动,或者证书路径不对导致 Nginx 起不来,用docker logs看具体报错。
三项都通过后,再验证一下模型调用是否正常。在控制台里发一条消息,如果能收到 TaoToken 返回的模型回复,说明从 Nginx 到 Openclaw 再到模型 API 的整条链路都通了。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
部署过程中我遇到过几类典型报错,这里逐个对照给出排查方向。
401 Unauthorized。这个最常见,来源有三个。一是 TaoToken 的 Key 填错或过期,检查 openclaw.json 里 apiKey 是否和 TaoToken 控制台一致,注意别把前后空格带进去。二是 Openclaw 控制台的 token 不对,URL 里的?token=必须和 gateway.auth.token 完全一致。三是 Nginx 转发时把 Authorization 头丢了,检查 proxy_set_header 里有没有漏掉透传,默认情况下 Nginx 会保留 Authorization,但如果你加了自定义 header 操作要确认没覆盖。
local proxy failed。这个报错通常出现在 Openclaw 尝试访问模型 API 时。原因是容器内 DNS 解析不了外部域名,或者出口网络被限制。先在容器里测一下:
docker exec -it openclaw-openclaw-gateway-1 curl -I https://taotoken.net/api如果 curl 不通,说明容器网络有问题,检查云平台的出口策略。如果 curl 通但 Openclaw 报 local proxy failed,检查 openclaw.json 里有没有配 http_proxy 之类的环境变量,容器内不需要代理,配了反而会走错。
reading choices 报错。这个一般出现在模型返回格式不符合预期时,Openclaw 解析响应体里的 choices 字段失败。排查方向:确认 baseUrl 没多加 /v1,确认 Model ID 是 TaoToken 支持的模型,确认请求确实打到了 chat/completions 端点。可以在容器里手动发一次请求对比:
curl https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer sk-你的密钥" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}'如果这个 curl 返回正常但 Openclaw 还报错,那就是 Openclaw 的 provider 配置字段名写错了,对照官方文档检查 type 和 baseUrl 的拼写。
OAuth 相关报错。如果你在 Openclaw 里配了需要 OAuth 的渠道或工具,报错通常和回调地址有关。因为服务跑在 HTTPS 的 18999 端口后面,OAuth 回调地址必须写成https://172.18.193.247:18999/callback这种形式,不能写 localhost。另外自签证书会导致部分 OAuth 提供方拒绝回调,这种情况要么换正式证书,要么在提供方那边把自签证书的指纹加白。
排查时有个通用技巧:先看 Nginx 的 access.log 和 error.log,确认请求有没有到 Nginx;再看 Openclaw 容器日志,确认请求有没有到应用层。两层日志一对比,问题出在转发还是应用就一目了然。
6. 长期跑 Agent 与多人共用,接入方式怎么选
企业云平台上给用户开 Openclaw 实例,通常不是一次性用完就关,而是长期挂着跑 Agent、定时任务、消息渠道。这种场景下模型接入方式的选择会影响成本和稳定性。
如果只是偶尔测试,按量调用模型对话就够了,用多少算多少。但如果是多人共用、Agent 频繁调用,建议走 Coding Plan,额度更可控,也不用担心某个用户把配额跑爆影响其他人。接入文档里有完整的 provider 配置说明和字段解释,配之前过一遍能少踩很多坑:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=openclaw_docker_nginx_openssl
最后说一个实际运维中的小技巧:自签证书有效期 365 天,到期前浏览器会直接拒绝访问,建议在云平台上加一个定时任务,提前 30 天检查证书剩余有效期,快到期时自动重新生成并重启 Nginx。命令很简单:
openssl x509 -in myip.crt -noout -checkend 2592000返回Certificate will expire就说明 30 天内要换了。把这个检查挂到监控里,比等到用户报障再处理省心得多。