GPUStack 启用 HTTPS 全攻略:自签证书与 Nginx 反代实战

发布时间:2026/9/15 20:49:29
GPUStack 启用 HTTPS 全攻略:自签证书与 Nginx 反代实战 GPUStack 这种开源 GPU 调度平台装完之后第一件事是什么大多数人是打开浏览器访问http://server:80看到 Web UI 正常显示就以为完事了。我之前也是这么干的直到有一次在公网环境做演示Chrome 直接警告“密码和 API Token 将明文传输”旁边同事半开玩笑说“你这管理端谁都能嗅探”。这才意识到GPUStack 的 Web 管理端和 API 默认跑在 HTTP 上虽然方便但真要投入多人使用、跨网络管理必须把 HTTPS 安排上。这篇文章就聊一聊我给 GPUStack 加 HTTPS 的完整过程包括官方 TLS 参数直配和 Nginx 反向代理两条路线以及我实际踩过的坑。1. 先摸清 GPUStack 的 HTTP 暴露面再决定证书方案很多教程上来就让你申请证书、改配置但我建议先花十分钟搞清楚 GPUStack 的默认监听方式、认证流程和数据链路。因为 HTTPS 不是简单加个证书它会影响 GPU 节点注册、浏览器 WebSocket 连接、API 调用方式搞不清楚这些后面大概率会踩坑。1.1 默认监听、认证机制与数据流GPUStack 默认监听0.0.0.0:80直接在 HTTP 端口上提供 Web UI 和 REST API。如果你是通过 pip 安装后直接执行gpustack start没有任何反向代理或防火墙的话相当于整个管理面裸奔在网络上。它的认证机制大致是用户在 Web UI 上登录后获取一个 token后续浏览器通过 Authorization Header 携带这个 token 调用 API。在 HTTP 明文环境下token 可以被同一网络中的任意抓包工具直接读取。就算内网环境一旦有主机被入侵攻击者拿到 token 就等于拿到了整个 GPU 集群的调度权限。此外GPU 工作节点agent注册到管理端时也会使用 API 地址和 token。如果你打算把集群调度地址对外暴露或者跨地域组网就必须让注册地址走 HTTPS否则同样存在凭证泄露风险。1.2 不加 HTTPS 的三个真实风险第一个风险就是登录凭证和 token 明文传输。这个最直接Wireshark 一抓一个准不需要多高深的黑客技术。第二个风险是 Web UI 被中间人篡改。你可能觉得管理页面被改一下没什么但如果攻击者把页面上显示的 GPU 型号、显存状态、任务结果替换掉会直接影响你的调度决策。更危险的是攻击者可以往页面里注入恶意脚本浏览器下次访问时就会执行。第三个风险是浏览器安全策略越来越严格。Chrome、Firefox 都在逐步将 HTTP 页面标记为“不安全”某些高级 Web API比如剪贴板、摄像头、service worker在非 HTTPS 环境下不可用。GPUStack 的 Web 终端、日志流等功能依赖 WebSocket如果这些功能在 HTTP 下表现不稳定很多时候不是 GPUStack 的 bug而是浏览器把请求拦了。1.3 规划域名、端口与证书放置位置在动手之前先想清楚三个问题第一用 IP 还是域名如果只是内网临时用自签证书 IP 访问问题不大如果长期使用强烈建议准备一个内网域名比如gpustack.lab.local这样证书的 SAN 可以包含所有可能访问的地址。第二443 端口是否已被占用如果这台机器上还跑了其他 Web 服务就不要让 GPUStack 直接监听 443而是保持 GPUStack 监听某个内部端口如 8443再用 Nginx 按域名分发。如果没有其他 Web 服务可以让 GPUStack 直接绑定 443。第三证书文件放在哪里我习惯统一放在/etc/gpustack/certs/目录下权限设为 600属主设为运行 GPUStack 的用户。不要放在/tmp或者家目录避免意外泄露。2. 方式一用 GPUStack 自带的 TLS 参数直接加密GPUStack 本身支持 TLS不用额外装东西。这种方式适合单机部署、内网环境或者你不想引入 Nginx 这种额外组件。官方代码里提供了证书和私钥的相关启动参数不同版本名字略有差异以gpustack start --help输出为准。我用的版本支持--server-crt和--server-key两个参数。2.1 自签证书生成也能用于内网如果公司有内部 CA那最好直接到内部 CA 去申请一张证书SAN 里写上 GPUStack 服务器的 IP 和域名。如果用的是自签证书可以用 OpenSSL 一次性生成带多个 SAN 的证书避免“证书只对 localhost 有效”的尴尬。下面是一个实测可用的命令生成一个同时包含localhost、内网 IP、自定义域名的自签证书sudo mkdir -p /etc/gpustack/certs cd /etc/gpustack/certs sudo openssl req -x509 -nodes -days 825 -newkey rsa:2048 \ -keyout gpustack.key \ -out gpustack.crt \ -subj /CCN/STBeijing/LBeijing/OExample/CNgpustack.lab.local \ -addext subjectAltNameDNS:localhost,DNS:gpustack.lab.local,IP:192.168.1.10,IP:127.0.0.1 sudo chmod 600 gpustack.key sudo chmod 644 gpustack.crt这里-addext是 OpenSSL 1.1.1 以上才支持的写法。825 天的有效期是为了兼容 Chrome 对自签证书最长有效期的限制825 天以内。如果你用内部 CA有效期可以自己定但最好还是遵循这个窗口。2.2 启动时指定证书和私钥生成证书之后直接启动 GPUStacksudo -u gpustack gpustack start \ --server-crt /etc/gpustack/certs/gpustack.crt \ --server-key /etc/gpustack/certs/gpustack.key \ --bind-addr 0.0.0.0:443如果--bind-addr不指定默认还是 80但是只要传了证书GPUStack 会自动改走 HTTPS 端口常见实现是 443如果 443 被占用会启动失败。启动日志里会打印类似Listening on https://0.0.0.0:443的信息这就说明 TLS 已经生效。如果你想保留 80 端口的 HTTP 服务做临时访问也可以只指定证书而不改端口让 GPUStack 直接在 80 端口上跑 HTTPS。不过这样访问习惯会比较怪不推荐。2.3 通过 systemd 环境变量固化配置用命令行参数启动最大的问题是容易忘。如果服务器重启后你忘了加参数GPUStack 就又退回 HTTP 了。所以建议把配置固化到 systemd 服务里。假设你有一个gpustack.service编辑文件加上环境变量[Service] Usergpustack Groupgpustack EnvironmentGPUSTACK_SERVER_CRT/etc/gpustack/certs/gpustack.crt EnvironmentGPUSTACK_SERVER_KEY/etc/gpustack/certs/gpustack.key EnvironmentGPUSTACK_BIND_ADDR0.0.0.0:443 ExecStart/usr/local/bin/gpustack start Restartalways注意GPUStack 不同版本的环境变量命名可能不同有的叫SERVER_CERT_PATH有的叫SSL_CERTFILE。你要做的就是运行gpustack start --help看输出里证书参数对应的环境变量名字是什么别照抄网上的贴子。改完配置后执行sudo systemctl daemon-reload sudo systemctl restart gpustack2.4 验证 HTTPS 已经生效启动完成后建议不要只访问浏览器而是用 curl 验证证书链是否完整curl -v --cacert /etc/gpustack/certs/gpustack.crt \ https://127.0.0.1:443/ \ -H Host: gpustack.lab.local \ -o /dev/null -sS 21 | grep -E subject|issuer|SSL connection如果输出里有subject: CN gpustack.lab.local说明证书匹配。如果你是直接用 IP 访问要确保 curl 后面用的是 IP并且证书 SAN 里包含这个 IP否则会报证书域名不匹配。3. 方式二Nginx 反代 Lets Encrypt 证书适合生产环境官方参数直接加 HTTPS 虽然简单但在多服务共存、需要随时拔掉 HTTPS、或者将来要搭配其他 Web 组件的场景下Nginx 反向代理更灵活。我给正式项目配置 GPUStack 时都是套一层 NginxGPUStack 自身保持监听内网 HTTP 端口Nginx 负责对外提供 HTTPS。3.1 为什么在 GPUStack 外面再套一层 Nginx首先是证书管理方便。Lets Encrypt 的 certbot 可以自动续期Nginx 配置改动之后nginx -s reload就能生效而不用重启 GPUStack 服务。其次是可以在这一层做统一的安全策略比如 IP 白名单、请求体大小限制、WebSocket 超时调整、访问日志记录。这些都是生产环境必须考虑的但 GPUStack 自己管不了那么细。第三是可以做端口复用。如果你一台机器上还要跑监控面板、日志系统用 Nginx 按域名或路径区分流量就不用每个组件都独占一个 443 端口。3.2 用 certbot 申请并自动续期免费证书如果你的 GPUStack 服务器有公网域名并且 80/443 端口能互通可以申请 Lets Encrypt 证书。先安装 certbot 和 Nginx 插件以 Ubuntu 22.04 为例sudo apt update sudo apt install -y nginx certbot python3-certbot-nginx sudo certbot certonly --nginx -d gpustack.example.comcertonly模式只负责申请证书不自动修改 Nginx 配置避免把你的现有配置弄乱。申请到的证书路径一般是/etc/letsencrypt/live/gpustack.example.com/fullchain.pem/etc/letsencrypt/live/gpustack.example.com/privkey.pem续期由 certbot 自带的 systemd timer 处理你只需要在 Nginx 配置里引用上面两个路径即可。证书更新后Nginx 配置不需要改因为路径是固定的。如果没有公网域名也可以自己搭建内部 CA或者继续用自签证书走 Nginx。这里更推荐内部 CA因为自签证书每台客户端机器都要导入信任维护成本太高。3.3 Nginx server 配置的核心片段与参数解释下面是我在用的 GPUStack Nginx 配置重点参数已经加注释。这个配置关键点在于把 HTTP 80 重定向到 HTTPS用proxy_pass把/转发到 GPUStack 的内网 HTTP 端口。# /etc/nginx/conf.d/gpustack.conf server { listen 80; server_name gpustack.example.com; # 全站强制跳转 HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name gpustack.example.com; ssl_certificate /etc/letsencrypt/live/gpustack.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gpustack.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 上传/下载大小限制GPUStack 传模型和数据集时体量可能很大 client_max_body_size 20G; # 访问日志单独记录方便排查 API 请求 access_log /var/log/nginx/gpustack.access.log; # 核心反代配置 location / { proxy_pass http://127.0.0.1:80; 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; # WebSocket 升级支持GPUStack 的日志流和终端依赖这个 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 长时间无响应的任务不要被网关断开 proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_connect_timeout 90s; } }这里最容易被忽略的是proxy_set_header Host $host和Upgrade / Connection两行。没有 Host 头GPUStack 会认为请求来路不正确没有 WebSocket 升级页面里打开 GPU 状态面板时日志流会一直转圈或者直接报错。改完配置后sudo nginx -t sudo systemctl reload nginx3.4 防火墙和 SELinux 的放行细节Nginx 监听 443 后系统防火墙要放行 443 和 80如果要跳转的话。以 ufw 为例sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw reload如果你用的是 CentOS/RHEL还有 SELinux 这个隐形坑。默认情况下SELinux 禁止 Nginx 访问网络后端。你可能会发现 curl 本机 443 没问题但从外部访问却连不上Nginx 日志里报connect to 127.0.0.1:80 failed (13: Permission denied)。解决方法是sudo setsebool -P httpd_can_network_connect 1这条命令允许 Nginx 转发请求到后端端口。如果是其他后端服务可能是别的布尔值但 GPUStack 这个场景下httpd_can_network_connect足够。4. 迁移 HTTPS 之后必须处理的四个兼容性坑HTTPS 配好只是第一步真正折腾人的是迁移后各种连接不上、页面报错。以下四个问题是我实际遇到过的按出现频率从高到低排一下。4.1 证书域名不符导致节点注册失败GPUStack 是多节点架构工作节点启动时用管理端地址去注册。如果你用https://192.168.1.10:443注册但证书 SAN 里没写这个 IP节点就会报证书错误注册失败。解决办法是生成证书时把内网所有可能访问管理端的 IP 和域名都写进 SAN。如果你已经用 Nginx 反代让所有节点统一走同一个域名证书只写这个域名即可。域名解析可以写到各节点的/etc/hosts不用改 DNS。比如echo 192.168.1.10 gpustack.example.com /etc/hosts4.2 WebSocket 和长连接被反代截断GPUStack 的 Web UI 实时显示 GPU 状态、任务日志靠的是 WebSocket。如果你只配了普通proxy_pass没有加Upgrade和Connection头页面会表现为大部分功能正常但一查看日志流就会卡住过一会儿提示“连接已断开”。这个问题在 Nginx 配置里已经给了解决方案就是上面那段配置中的proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade;还有一个注意点如果 GPUStack 和 Nginx 之间还有一层防火墙或者负载均衡要注意这些中间设备是否支持 WebSocket 的 TCP 长连接有的云负载均衡默认超时时间很短会导致 WebSocket 频繁断开。4.3 自签证书刚配完刷新没生效用自签证书IP 访问时浏览器会提示“您的连接不是私密连接”。有些教程会教你点“高级”-“继续前往”但你点了之后发现页面还是进不去甚至反复重定向。这通常是因为你在 Nginx 里加了 HTTP 跳转但浏览器缓存的 HTTP 重定向响应没有失效。解决办法是在 Nginx 返回 301 时加上always和合适的缓存控制头或者在浏览器无痕模式里测一次。如果确认是旧缓存可以关闭标签页后重新打开或者用curl -kI https://your-server看响应头是否正常。4.4 代理模式下文件上传大小限制GPUStack 里上传模型文件动辄几个 GBNginx 默认client_max_body_size是 1 MB超过就返回 413 错误。我在配置里写了 20G但如果你模型更大可以继续调大或者改成0表示不限。不建议直接改成0因为 Nginx 会先把文件读入临时目录太大容易把磁盘写满还是设一个合理的上限比较好。另外如果你用的是官方 TLS 直连方式而非 Nginx就不会有这个限制因为 GPUStack 自己处理上传时不受 Nginx 的 body size 约束。5. 安全加固不能止于 HTTPS收尾的几个动作HTTPS 上线后建议顺手做下面三件事把 GPUStack 的安全水位再往上提一档。5.1 用重定向代替直接关闭 80 端口有些人配好 HTTPS 后直接拔掉 80 端口结果在外网访问时遇到各种打不开的诡异问题。因为很多公司防火墙策略、CDN 回源检查还会访问 80。正确做法是保留 80 端口但让它 301 跳转到 HTTPS。这样既保证了安全性又不影响用户输入习惯也不影响 certbot 后续的 HTTP 认证续期。server { listen 80; server_name gpustack.example.com; return 301 https://$host$request_uri; }5.2 清理默认管理员密码与弱 API KeyHTTPS 解决的是传输加密应用本身的弱口令问题它管不了。GPUStack 安装后默认的管理员账号密码是强密码还是默认密码取决于你初始化时怎么设置。如果之前不小心设了一个弱密码现在一定要改掉。改完密码后之前签发的 API Key 可能还有效建议在管理后台把旧的、不用的 API Key 全部清除重新生成。另外检查一下 GPUStack 的 API 是否开放了注册接口。如果开放任何人都可以通过 Web API 创建账号那就很危险。建议关闭自助注册只允许管理员创建用户。5.3 定期检查证书过期日和回滚方案自签证书虽然写了 825 天但企业内部不规范的情况下经常有“证书又过期了”的突发情况。就算用 Lets Encrypt也要定期确认续期任务正常运行。可以用 certbot 的--dry-run测试续期sudo certbot renew --dry-run同时建议把“切换回 HTTP 临时访问”作为应急预案。具体做法是在 Nginx 配置里临时改proxy_pass指向 GPUStack 的另一个 HTTP 端口或者直接用 GPUStack 命令行的--server-crt去掉。这个预案看似简单但真出事时可以省去大把排查时间。我经历过一次证书私钥文件被备份脚本误改权限导致 GPUStack 起不来当时就是靠切回临时 HTTP 端口把集群业务保住的。另一个贴心建议把证书文件的关键信息加到监控里。可以写个简单的 shell 脚本每天检查证书剩余天数如果少于 14 天就在日志里输出告警配合你的短信/钉钉通知服务避免“过期当天才反应过来”的尴尬。我用这套方案已经稳定运行了半年多期间经历过证书自动续期、GPU 节点跨网段注册、上传大模型文件等多个场景HTTPS 没有掉过链子。如果你也在用 GPUStack建议别偷懒第一步配 HTTPS 就扔掉 HTTP。尤其是多人共用的环境越早加密后患越少。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询