Docker部署OpenClaw并用Nginx反向代理:TaoToken统一Key接入配置实战
1. 为什么要把 OpenClaw 塞进 Docker 再用 Nginx 兜一层OpenClaw 是一个可以本地部署的 AI 网关/助手服务能对接多种模型和消息通道适合想把 AI 能力收拢到自己服务器上的人。但直接跑起来会碰到两个很烦的问题一是它默认监听 18789 端口裸奔在公网上不安全二是你手头可能有好几个 AI 工具每个都要单独配 Key、单独记接口地址时间一长自己都记不清哪个 Key 对应哪个服务。我这次的做法是用 Docker Compose 把 OpenClaw 和 Nginx 分别编排成容器Nginx 做反向代理并加上 Basic 认证和自签 SSL对外只暴露一个 HTTPS 入口。同时把模型调用的 Key 统一走 TaoToken 的 API 地址这样 OpenClaw 里只需要维护一份 Key其他工具也能复用同一套配置。这篇会给出可直接复制的docker-compose.yml、nginx.conf、OpenClaw 网关配置骨架以及容器起来之后验证反向代理连通性和 Key 是否生效的具体命令。目标是一次性跑通 OpenClaw 的对外服务入口不用来回改配置。适合谁看手里有一台能跑 Docker 的 Linux 服务器、想让 OpenClaw 通过域名安全访问、并且希望把多个 AI 工具的 Key 统一管理的人。下面按实际部署顺序来。2. 前置准备TaoToken 统一 Key 与目录规划在动 Docker 之前先把 Key 的事情理清楚。TaoToken 的定位是统一模型调用入口你可以在它的控制台生成 API Key然后把 OpenClaw 里的模型请求地址指向 TaoToken 的 API 端点。这样做的直接好处是以后换模型或者加工具不用每个地方都改一遍 Key。具体操作是进控制台创建 Key拿到一串以sk-开头的字符串。这个 Key 后面会写进 OpenClaw 的环境变量或配置文件里。如果你还没建过 Key可以走这个入口https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteAPI 的基础地址是https://taotoken.net/api注意这个地址不带任何查询参数配置时直接填这个就行。OpenClaw 里凡是需要填模型服务地址的地方都指向它。目录规划我按下面这样分OpenClaw 和 Nginx 各自独立互不干扰mkdir -p /data/openclaw/openclaw_data/workspace mkdir -p /data/nginx/nginx_data/{html,conf,logs,ssl}授权这块有个坑OpenClaw 容器内以 UID 1000 运行如果宿主机目录属主不对启动会报权限错误。先按 UID/GID 授权实在不行再放宽chown 1000:1000 /data/openclaw/openclaw_data -R chmod 777 /data/openclaw/openclaw_data -R注意chmod 777只是排障时的兜底手段生产环境建议把属主和权限调对之后就收回宽松权限。3. 可复制配置OpenClaw 与 Nginx 的 docker-compose 编排3.1 OpenClaw 的 docker-compose.ymlOpenClaw 这里用network_mode: host原因是它的网关配置对访问来源比较敏感用 host 网络能省掉一堆端口映射和跨域说明。镜像用ghcr.io/openclaw/openclaw:2026.3.28。services: openclaw-gateway: image: ghcr.io/openclaw/openclaw:2026.3.28 restart: unless-stopped network_mode: host privileged: true ipc: host init: true environment: - HOME/home/node - NODE_ENVproduction - TERMxterm-256color volumes: - /data/openclaw/openclaw_data:/home/node/.openclaw - /data/openclaw/openclaw_data/workspace:/home/node/.openclaw/workspace command: openclaw gateway --allow-unconfigured healthcheck: test: [ CMD, node, -e, fetch(http://127.0.0.1:18789/healthz).then((r)process.exit(r.ok?0:1)).catch(()process.exit(1)) ]启动cd /data/openclaw docker compose up -d起来之后进容器做初始化docker compose exec openclaw-gateway /bin/bash openclaw onboard openclaw status openclaw dashboardopenclaw dashboard会输出一个带 token 的登录地址先记下来后面验证要用。3.2 Nginx 的 nginx.conf 与反向代理配置Nginx 用nginx:1.28-alpine主配置保持精简站点配置单独放conf.d。user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; charset utf-8; include /etc/nginx/conf.d/*.conf; }生成自签证书和 Basic 认证文件openssl req -x509 -newkey rsa:2048 -nodes -sha256 \ -keyout /data/nginx/nginx_data/ssl/openclaw.key \ -out /data/nginx/nginx_data/ssl/openclaw.crt \ -days 36500 \ -subj /CCN/STLN/LSY/OOpenClaw/CNopenclaw.example.top sh -c echo admin:$(openssl passwd -apr1 Aa123456) /data/nginx/nginx_data/ssl/.htpasswd反向代理站点配置重点是 WebSocket 支持和清空 Authorization 头server { listen 18443 ssl; server_name openclaw.example.top; ssl_certificate /etc/nginx/ssl/openclaw.crt; ssl_certificate_key /etc/nginx/ssl/openclaw.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; auth_basic OpenClaw Login; auth_basic_user_file /etc/nginx/ssl/.htpasswd; add_header Strict-Transport-Security max-age31536000; includeSubDomains always; add_header X-Frame-Options SAMEORIGIN always; add_header X-Content-Type-Options nosniff always; access_log /var/log/nginx/openclaw-access.log; error_log /var/log/nginx/openclaw-error.log; location / { proxy_pass http://172.16.0.2:18789; proxy_set_header Authorization ; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header X-Forwarded-User $remote_user; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 300s; proxy_buffering off; } }Nginx 的 compose 文件services: nginx: image: nginx:1.28-alpine container_name: nginx-proxy restart: always ports: - 14311:14311 - 18443:18443 volumes: - ./nginx_data/nginx.conf:/etc/nginx/nginx.conf - ./nginx_data/html:/usr/share/nginx/html - ./nginx_data/conf:/etc/nginx/conf.d - ./nginx_data/ssl:/etc/nginx/ssl - ./nginx_data/logs:/var/log/nginx deploy: resources: limits: memory: 2G启动cd /data/nginx docker compose up -d3.3 OpenClaw 网关配置骨架OpenClaw 的网关配置里auth.mode设为trusted-proxy让它信任 Nginx 传来的x-forwarded-user头。allowedOrigins要把 HTTPS 入口加进去。{ gateway: { port: 18789, mode: local, bind: custom, customBindHost: 172.16.0.2, controlUi: { allowedOrigins: [ http://localhost:18789, http://172.16.0.2:18789, https://openclaw.example.top:18443 ], allowInsecureAuth: false, dangerouslyDisableDeviceAuth: false }, auth: { mode: trusted-proxy, trustedProxy: { userHeader: x-forwarded-user, requiredHeaders: [x-forwarded-proto, x-forwarded-host], allowUsers: [admin] } }, trustedProxies: [localhost, 127.0.0.1, 172.16.0.2, 172.18.0.2], tailscale: { mode: off, resetOnExit: false } } }模型调用这块把服务地址指向 TaoToken 的 API 端点Key 填你在控制台生成的那串。这样 OpenClaw 内部所有模型请求都走统一入口不用在多个地方重复配 Key。4. 验证请求反向代理连通性与 Key 生效容器都起来之后先确认 OpenClaw 自身健康curl -s http://127.0.0.1:18789/healthz返回 ok 说明网关活着。然后验证 Nginx 反向代理这一层注意带上 Basic 认证curl -k -u admin:Aa123456 https://openclaw.example.top:18443/healthz如果返回和上面一致说明 Nginx 到 OpenClaw 的链路通了。-k是因为自签证书浏览器里第一次访问也会提示不安全手动信任即可。再验证 WebSocket 升级是否正常可以用curl看响应头里有没有101 Switching Protocolscurl -k -i -u admin:Aa123456 \ -H Connection: Upgrade \ -H Upgrade: websocket \ https://openclaw.example.top:18443/Key 生效的验证最直接的方式是在 OpenClaw 里发一条测试消息看它能不能正常返回模型结果。如果返回鉴权失败先检查 Key 有没有写对、API 地址是不是https://taotoken.net/api。想单独验证 Key 本身可以走模型对话入口发一条测试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite5. 本篇常见错排查502 Bad GatewayNginx 连不上 OpenClaw。先确认proxy_pass里的 IP 和端口对再确认 OpenClaw 容器确实在监听 18789。用docker compose logs openclaw-gateway看有没有启动报错。401 Unauthorized 反复弹窗Basic 认证文件路径不对或者.htpasswd里用户名密码格式有问题。确认auth_basic_user_file指向的路径在容器内存在且 Nginx 有读权限。WebSocket 连不上、页面一直转圈检查proxy_set_header Upgrade和Connection upgrade这两行有没有漏proxy_http_version必须是 1.1。OpenClaw 报设备未授权trusted-proxy模式下确认 Nginx 传了x-forwarded-user且这个用户名在allowUsers列表里。如果还是不行用openclaw devices list看有没有待批准的设备再openclaw devices approve requestId。容器启动权限报错宿主机目录属主不是 UID 1000。按前面说的先chown 1000:1000还不行再临时放宽权限。跨域报错allowedOrigins里没加你实际访问的域名和端口。改完配置要重启 OpenClaw 容器才生效。6. 长期跑编码和 Agent 的话Key 怎么管更省心如果你只是偶尔用 OpenClaw 发发消息上面这套配置够用了。但如果你打算把它当成长期的编码助手或者 Agent 入口Key 的管理方式值得再想一步。我自己的做法是把 TaoToken 的 Key 集中放在一处OpenClaw、其他编辑器插件、脚本都引用同一个来源换 Key 的时候只改一个地方。对于需要长时间跑编码任务或者 Agent 流程的场景可以看一下 Coding Plan 的说明它更适合这种持续调用的用法https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite接入过程中如果碰到配置对不上的地方接入文档里有各字段的说明对着查比反复试快https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite最后提醒一句Nginx 那层 Basic 认证只是第一道门自签证书浏览器会报警告正式对外用建议换成受信任的证书。OpenClaw 的trustedProxies列表也别写太宽只放你实际用到的代理地址就行。