通过Docker和Nginx实现OpenClaw在Ubuntu服务器上的完整部署流程
这次把 OpenClaw 部署在一台 Ubuntu 服务器上,使用 Docker 运行,再通过宝塔面板中的 Nginx 站点做反向代理,最后绑定域名,通过 HTTPS 访问控制界面。
最终访问链路如下:
浏览器 ↓ https://你的https域名 ↓ Nginx(宝塔站点) ↓ 127.0.0.1:18789 ↓ OpenClaw Gateway
这篇主要记录整个部署过程,以及顺手完成的几项加固:Docker 端口只绑定本地、Nginx 白名单限制、UFW 拒绝端口直连。目标很明确,不只是把服务跑起来,而是让它以一个更适合长期使用的方式对外提供访问。

环境准备与安装初始化
服务器环境是 Ubuntu 24,已经安装宝塔面板,并启用了 Nginx。OpenClaw 通过 Docker Compose 运行,域名通过宝塔站点绑定并配置 SSL。

本次部署使用到的环境信息如下:
| 项目 | 值 |
|---|---|
| 系统 | Ubuntu 24 |
| 面板 | 宝塔面板 |
| Web 服务 | Nginx |
| OpenClaw 项目目录 | /www/docker/openclaw/openclaw-main |
| OpenClaw 配置目录 | /root/.openclaw |
| Gateway 端口 | 18789 |
| Bridge 端口 | 18790 |
| 域名 | 你的https域名 |
| 允许访问的公网 IP | 自行调整 |
源码获取方式
由于服务器访问 GitHub 不太稳定,这次没有直接拉仓库,而是先在本地下载压缩包,再上传到服务器。
压缩包路径如下:
/www/docker/openclaw/openclaw-main.zip
解压后目录如下:
/www/docker/openclaw/openclaw-main
进入项目目录后的常规操作:
cd /www/docker/openclaw/openclaw-main ls chmod +x docker-setup.sh ./docker-setup.sh
安装脚本是交互式的,这次采用的是尽量轻量的初始化方式,关键选择如下:
| 步骤 | 选择 |
|---|---|
| 初始化确认 | Yes |
| 安装模式 | QuickStart |
| 模型提供商 | OpenRouter |
| API Key 提供方式 | Paste API key now |
| 聊天渠道 | Skip for now |
| Skills | 按需选择,尽量最小化部署 |
| Hooks | Skip for now |
安装过程本身并不复杂,真正需要处理的重点在于,如何把 OpenClaw 接到一个合理、安全的公网入口上。
OpenClaw 配置与 Docker 端口收口
OpenClaw 配置文件位置
有一个地方比较容易找错:OpenClaw 的实际配置文件并不在项目目录里,而是在下面这个位置:
/root/.openclaw/openclaw.json
项目目录下的内容主要是运行环境和 Compose 配置,真正控制 Gateway、认证方式和 UI 来源校验的,是这个 openclaw.json。
本次用到的关键配置如下:
{
"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback",
"auth": {
"mode": "token"
},
"controlUi": {
"allowedOrigins": [
"https://你的https域名",
"http://你的https域名"
],
"dangerouslyAllowHostHeaderOriginFallback": true
}
}
}这里最重要的是两个配置项:
controlUi.allowedOriginsdangerouslyAllowHostHeaderOriginFallback
因为 OpenClaw 在非本地访问场景下会做来源校验。如果你是通过域名访问控制 UI,但没有把域名加入允许来源列表,网关可能直接拒绝启动,或者前端能打开但后端无法连接。
所以只要不是在本机 localhost 上使用,而是通过域名反代访问,这段配置基本都需要处理。
修改 Docker Compose 端口绑定
OpenClaw 默认的 Compose 配置,会把 18789 和 18790 直接映射到公网。
默认写法如下:
ports:
- "${OPENCLAW_GATEWAY_PORT:-18789}:18789"
- "${OPENCLAW_BRIDGE_PORT:-18790}:18790"
这种方式在测试阶段没有问题,但如果直接用于公网服务器,就意味着外部可以通过 服务器IP:18789 直接访问 Gateway。
更合理的做法,是只让 Docker 端口绑定到本地回环地址,让外部流量统一从 Nginx 入口进入。
修改后如下:
ports:
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}:18789"
- "127.0.0.1:${OPENCLAW_BRIDGE_PORT:-18790}:18790"
这样改完以后,18789 和 18790 只允许本机访问,公网无法直接连接。
实际修改命令如下:
cd /www/docker/openclaw/openclaw-main
cp docker-compose.yml docker-compose.yml.bak
sed -i 's#- "${OPENCLAW_GATEWAY_PORT:-18789}:18789"#- "127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}:18789"#' docker-compose.yml
sed -i 's#- "${OPENCLAW_BRIDGE_PORT:-18790}:18790"#- "127.0.0.1:${OPENCLAW_BRIDGE_PORT:-18790}:18790"#' docker-compose.yml
修改完成后重启容器:
docker compose down docker compose up -d
这一步非常关键。因为如果不先把 Docker 端口收口,后面即使配置了域名和 Nginx 反向代理,Gateway 实际上仍然是对公网暴露的。那时 Nginx 只是“增加了一层入口”,不是“唯一入口”。
宝塔反向代理与访问入口配置
这次使用的是宝塔面板,所以站点直接在宝塔里创建。

需要注意的是,站点目录本身并不是重点。它不会直接渲染 OpenClaw 页面,更像是一个 Nginx 入口,用于完成三件事:
- 绑定域名
- 配置 HTTPS 证书
- 反向代理到本机 OpenClaw Gateway
站点目录给一个普通路径即可,例如:
/www/wwwroot/你的https域名
最终使用的核心 Nginx 配置如下:
location / {
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_connect_timeout 60s;
proxy_buffering off;
proxy_request_buffering off;
}这段配置主要完成了三件事。
首先是 IP 白名单控制,只允许服务器本机和指定公网 IP 访问,其它请求直接返回 403。
其次是补齐 WebSocket 所需代理头,因为 OpenClaw 控制界面依赖 WebSocket 与后端通信。
最后才是将流量转发到 127.0.0.1:18789。
修改完成后,先检查配置:
nginx -t
确认没有问题后再重载:
nginx -s reload
安全加固与访问控制
虽然前面已经把 Docker 端口绑定到了 127.0.0.1,理论上公网已经无法直接访问 18789 和 18790,但这里我还是补了一层 UFW。
执行规则如下:
ufw deny 18789 ufw deny 18790 ufw enable
这样做的目的就是多一层保险。即使后续某次改动误把 Docker 端口重新暴露出来,防火墙层面仍然可以拦住这两个端口,避免被直接访问。
对外开放端口建议只保留:
| 端口 | 用途 |
|---|---|
| 22 | SSH 登录 |
| 80 | HTTP |
| 443 | HTTPS |
如果服务器在腾讯云、阿里云等云平台上,安全组也建议同步关闭 18789 和 18790,只保留 22、80、443。
OpenClaw 的认证机制
OpenClaw 默认并不是传统的账号密码登录系统,而是采用 Gateway Token 模式。
也就是说,用户可以看到前端页面,但如果没有正确的 Token,就无法真正连接后端。这时前端通常会提示:
unauthorized: gateway token missing
Token 存放在:
/root/.openclaw/openclaw.json
结构大概如下:
"auth": {
"mode": "token",
"token": "xxxxxxxxxxxxxxxx"
}这意味着它的访问控制实际上分成两层:
第一层是外层访问控制,也就是能不能先打开这个页面。这部分由 Nginx 白名单、域名入口和 HTTPS 决定。
第二层是内部操作控制,也就是能不能真正控制 Agent。这部分由 Gateway Token 决定。
所以这次的思路很简单,外层用 Nginx 白名单限制访问范围, 内层保留 OpenClaw 自己的 Gateway Token 作为实际控制权限。
如果后续还想进一步强化,也可以在 Nginx 层再加 BasicAuth,让浏览器先弹账号密码框。
当前这套结构的最终效果
到这里,这次部署的整体安全边界就比较清楚了。
当前已经完成的控制如下:
| 层级 | 作用 |
|---|---|
Docker 只绑定 127.0.0.1 | 阻止公网直接访问 18789/18790 |
| UFW 拒绝 18789/18790 | 防止端口直连 |
| Nginx 白名单 | 只允许指定来源访问 |
| HTTPS 域名访问 | 满足安全上下文要求 |
| Gateway Token | 控制真正的 Agent 连接权限 |
最终访问表现应该如下:
| 访问方式 | 结果 |
|---|---|
https://你的https域名,且来源 IP 为允许 IP | 正常访问 |
https://你的https域名,但来源为其他 IP | 403 Forbidden |
http://服务器IP:18789 | 无法访问 |
| 页面打开但没填 Gateway Token | 页面可见但无法操作 |
| 正确填写 Gateway Token | 可正常控制 OpenClaw |
到这一步,至少入口是统一的,权限是分层的,公网也没有留下多余暴露面。
问题排查、运维命令与后续优化
先看 DNS,再查服务
这次排查过程中,还有一个很典型的问题。
一开始域名访问不上,最先怀疑的是 Docker、Nginx 或者 OpenClaw 配置本身,结果最后发现问题根本不在服务层,而是在 DNS。
你的https域名 这个子域名,必须先在 DNS 控制台中添加 A 记录,例如:
| 类型 | 主机记录 | 记录值 |
|---|---|---|
| A | openclaw | xxx.xxx.xxx.xxx |
只有解析生效之后,请求才会真正打到当前服务器。
可以通过以下命令验证:
ping -c 2 你的https域名 curl -I http://你的https域名 curl -Ik https://你的https域名
如果 DNS 尚未生效,通常看到的报错会是:
Could not resolve host Name or service not known
所以如果遇到域名无法访问的问题,建议先确认 DNS 解析是否正确,再去检查 Docker、Nginx 或 OpenClaw 本身。
常用运维命令整理
下面把部署和排查时比较常用的命令一起记下来,后面复用会比较方便。
查看容器状态:
cd /www/docker/openclaw/openclaw-main docker ps docker compose ps
查看网关日志:
docker logs --tail 100 openclaw-main-openclaw-gateway-1
重启 OpenClaw:
cd /www/docker/openclaw/openclaw-main docker compose down docker compose up -d
检查 Nginx 配置:
nginx -t nginx -s reload
检查 80 和 443 是否监听:
ss -lntp | grep -E ':80|:443'
检查 OpenClaw 本机端口:
curl -I http://127.0.0.1:18789 curl -I http://127.0.0.1:18789/__openclaw__/canvas/
检查 Nginx 到 OpenClaw 的反代链路:
curl -I http://127.0.0.1 -H "Host: 你的https域名" curl -Ik https://127.0.0.1 -H "Host: 你的https域名"
这些命令都比较基础,但在排查时很高频。尤其是本机端口和反代链路测试,通常能很快判断问题到底出在 OpenClaw、Docker、Nginx,还是域名解析层。
后续还能继续增强的方向
目前这套结构已经可以稳定使用,但如果后续想继续往更完整的生产环境演进,还可以继续补几项:
| 方向 | 说明 |
|---|---|
| 增加 Nginx BasicAuth | 再加一层浏览器级账号密码认证 |
| 接入 Cloudflare Access / OAuth | 做更标准的统一身份认证 |
| 隐藏默认控制路径 | 降低被扫描器直接探测到的概率 |
| 固定允许来源域名 | 进一步减少 Host Header 风险 |
| 细化模型调用策略 | 按 OpenRouter / DeepSeek 做权限隔离 |
| 记录访问日志和异常日志 | 方便后续审计和问题回溯 |
这些都不是这次部署的必需项,但如果后面要从“自己用”逐步走向“长期用”或者“多人用”,基本都会慢慢补上。
总结
这次部署完成后,OpenClaw 已经可以通过 HTTPS 域名正常访问,Gateway 端口也不再直接暴露到公网。
目前这套结构的核心有三点:
- 域名作为统一入口
- Docker 端口只绑定本地
- Nginx 白名单和 Gateway Token 形成双层限制
对个人长期使用来说,这样的结构已经比较稳,也方便后续继续叠加认证或访问控制。
以上就是OpenClaw在Ubuntu服务器上的完整部署流程的详细内容,更多关于OpenClaw在Ubuntu上的部署的资料请关注脚本之家其它相关文章!
相关文章
Ubuntu20.04安装cuda10.1的步骤(图文教程)
这篇文章主要介绍了Ubuntu20.04安装cuda10.1的步骤(图文教程),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07


最新评论