1. 项目概述:为什么ChatGLM-6B需要Nginx与SSL?
如果你已经成功在本地或服务器上跑起了ChatGLM-6B的WebUI,看着它在浏览器里(通常是http://localhost:7860或http://your-server-ip:7860)欢快地运行,可能会觉得大功告成了。但作为一名有经验的部署者,我通常会立刻意识到两个核心问题:安全与可用性。直接暴露HTTP服务,尤其是在公网环境下,无异于“裸奔”——所有的对话数据、模型交互都是明文传输,极易被窃听或篡改。同时,一个IP加端口的访问方式既不专业,也难以记忆和分享。
这就是Nginx反向代理和SSL证书登场的时刻。简单来说,这个组合能帮你实现三件事:
- 加密通信:通过HTTPS协议,为你的ChatGLM-6B WebUI套上一层坚固的“铠甲”,确保用户与AI助手之间的所有对话内容都是加密的。
- 统一入口:你可以使用一个漂亮的域名(如
chat.yourdomain.com)来访问服务,隐藏后端复杂的端口和路径,提升专业度和易用性。 - 增强能力:Nginx作为专业的Web服务器,能提供负载均衡、静态文件缓存、访问控制、限流等高级功能,为你的AI服务保驾护航。
本教程将手把手带你完成从零开始,为ChatGLM-6B WebUI配置Nginx反向代理并启用HTTPS的全过程。无论你是个人开发者想安全地对外提供服务,还是团队内部需要搭建一个可靠的AI对话平台,这套方案都经过了实战检验。
2. 环境准备与前置检查
在动手配置之前,我们需要确保基础环境是就绪的。这里假设你已经在一台Ubuntu 20.04或22.04 LTS的服务器上部署好了ChatGLM-6B的WebUI服务,并且它正运行在某个端口(例如7860)上。如果你还没部署,需要先完成那一步。
2.1 系统与网络环境确认
首先,通过SSH登录到你的服务器。我们需要确认几件关键事情:
检查ChatGLM-6B WebUI服务状态:
# 查看是否有Python进程在运行WebUI,通常与gradio或streamlit相关 ps aux | grep -E “(gradio|streamlit|python.*chat)” # 或者直接检查7860端口是否被监听 sudo netstat -tulpn | grep :7860如果看到类似0.0.0.0:7860或127.0.0.1:7860的监听信息,说明服务正常。一个最佳实践是让WebUI仅监听本地回环地址(127.0.0.1),这样外部无法直接访问,只能通过Nginx代理,安全性更高。你可以在启动WebUI的命令中指定--server-name 127.0.0.1(对于Gradio)来实现。
检查服务器公网IP与防火墙:确保你的服务器拥有一个公网IP地址,并且云服务商的安全组(或防火墙规则)已经放行了**80(HTTP)和443(HTTPS)**端口。这是后续申请SSL证书和提供Web服务的基础。你可以使用curl ifconfig.me查看公网IP,并用sudo ufw status(如果使用UFW)检查防火墙规则。
准备一个域名:你需要一个已经注册并可以管理的域名。这可以是向域名注册商购买的一级域名(如yourdomain.com),也可以是免费的二级域名。在域名的DNS管理后台,添加一条A记录,将你想要的子域名(例如chat或ai)指向你的服务器公网IP地址。DNS解析全球生效可能需要几分钟到几小时,你可以用ping your-subdomain.yourdomain.com或nslookup your-subdomain.yourdomain.com来验证是否生效。
2.2 Nginx的安装与基础配置
如果你的系统还没有Nginx,安装它非常简单。我推荐使用官方仓库安装,以获得较新的稳定版本。
# 更新软件包列表 sudo apt update # 安装Nginx sudo apt install nginx -y安装完成后,启动Nginx并设置开机自启:
sudo systemctl start nginx sudo systemctl enable nginx现在,在浏览器中访问你的服务器公网IP(http://<你的服务器IP>),你应该能看到Nginx的默认欢迎页面。这说明Nginx已经成功安装并运行。
注意:如果此时你无法访问欢迎页面,大概率是服务器的防火墙或云平台安全组没有放行80端口。请务必先去云服务商控制台检查“安全组”或“防火墙”设置,添加入站规则,允许TCP协议的80和443端口。
接下来,我们先清理一下默认配置,为我们的专属配置让路。Nginx的站点配置文件通常存放在/etc/nginx/sites-available/目录,而通过创建符号链接到/etc/nginx/sites-enabled/来启用。
# 移除默认站点的启用链接 sudo rm /etc/nginx/sites-enabled/default # 可选:你也可以备份或删除sites-available里的默认文件 # sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.backup现在,环境准备就绪,我们可以进入核心的SSL证书申请环节了。
3. 申请与配置SSL证书(以Let‘s Encrypt为例)
要让我们的服务从HTTP升级到HTTPS,SSL证书是必需品。购买商业证书是一种选择,但对于个人项目和大多数场景,Let‘s Encrypt提供的免费、自动化证书是绝佳选择。它的证书有效期为90天,但可以通过工具自动续期,实现永久免费。
3.1 安装Certbot客户端
Certbot是Let‘s Encrypt官方推荐的自动化证书管理工具。在Ubuntu上,我们可以通过Snap包管理器安装,这是目前最推荐的方式,能确保获得最新版本和最佳兼容性。
# 确保snapd已安装并运行 sudo apt install snapd -y sudo snap install core sudo snap refresh core # 安装Certbot sudo snap install --classic certbot # 创建命令行软链接,方便直接使用certbot命令 sudo ln -s /snap/bin/certbot /usr/bin/certbot3.2 使用Certbot申请证书
申请证书有多种验证方式,我们选择最通用的--webroot模式。这种方式下,Certbot会在你的Web根目录下创建一个临时文件,Let‘s Encrypt的服务器通过访问这个文件来验证你对域名的控制权。因此,需要确保你的Nginx正在运行,并且能够通过域名访问到。
首先,为你的域名创建一个Web根目录,并确保Nginx有读取权限:
sudo mkdir -p /var/www/chatglm-html sudo chown -R www-data:www-data /var/www/chatglm-html sudo chmod -R 755 /var/www/chatglm-html然后,运行Certbot命令申请证书。请务必将chat.yourdomain.com替换为你实际解析到服务器的域名。
sudo certbot certonly --webroot \ -w /var/www/chatglm-html \ -d chat.yourdomain.com \ --email your-email@example.com \ --agree-tos \ --non-interactive \ --force-renewal参数解释:
--webroot: 指定使用webroot验证模式。-w /var/www/chatglm-html: 指定Web根目录路径,Certbot会在此创建.well-known/acme-challenge/目录存放验证文件。-d chat.yourdomain.com: 指定你要申请证书的域名。--email: 用于接收证书过期提醒等重要通知的邮箱。--agree-tos: 自动同意Let‘s Encrypt的服务条款。--non-interactive: 非交互式运行,适合脚本自动化。--force-renewal: 如果已有旧证书,强制更新。
如果一切顺利,你会看到类似 “Congratulations! Your certificate and chain have been saved at:” 的成功信息。证书和私钥通常存放在/etc/letsencrypt/live/chat.yourdomain.com/目录下。关键文件有:
fullchain.pem: 完整的证书链(你的证书+中间CA证书),Nginx的ssl_certificate指令需要它。privkey.pem: 你的私钥,Nginx的ssl_certificate_key指令需要它。
实操心得:申请证书时最常见的错误是域名解析未生效或80端口被阻挡。务必先用
curl -I http://chat.yourdomain.com测试一下,确保能收到Nginx的响应(哪怕是404),再进行申请。如果服务器在境内,且域名未备案,80端口可能被运营商拦截,这时可以尝试使用DNS验证模式(--preferred-challenges dns),手动添加TXT记录来验证域名所有权,具体命令可查阅Certbot文档。
3.3 配置证书自动续期
Let‘s Encrypt证书只有90天有效期,手动续期太麻烦。幸运的是,Certbot提供了自动续期功能。实际上,安装Certbot时,它已经创建了一个systemd定时器(timer)或cron job来处理续期。我们可以手动测试一下续期流程是否畅通:
sudo certbot renew --dry-run这个--dry-run参数会模拟续期过程而不真正操作,用于检查配置是否正确。如果看到 “The dry run was successful” 的提示,说明自动续期配置没问题。
Certbot的自动续期脚本会定期检查证书,并在到期前30天内自动续签。你无需额外操作。但为了保险起见,可以查看一下系统定时任务:
systemctl list-timers | grep certbot # 或查看cron job sudo cat /etc/cron.d/certbot4. 配置Nginx反向代理与HTTPS
有了SSL证书,现在可以配置Nginx作为反向代理,将外部HTTPS请求安全地转发到内部运行的ChatGLM-6B WebUI服务。
4.1 创建Nginx服务器块(Server Block)配置
在/etc/nginx/sites-available/目录下,为我们ChatGLM-6B服务创建一个新的配置文件,例如chatglm:
sudo nano /etc/nginx/sites-available/chatglm将以下配置内容粘贴进去。请务必替换所有chat.yourdomain.com为你的真实域名,并确认证书路径正确。
# HTTP服务器块,强制将所有HTTP请求重定向到HTTPS server { listen 80; listen [::]:80; # 支持IPv6 server_name chat.yourdomain.com; # 你的域名 # 告诉Let‘s Encrypt验证程序,验证文件在这里 location /.well-known/acme-challenge/ { root /var/www/chatglm-html; } # 将所有其他HTTP流量永久重定向(301)到HTTPS版本 location / { return 301 https://$server_name$request_uri; } } # HTTPS服务器块 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name chat.yourdomain.com; # 你的域名 # SSL证书路径(由Certbot申请) ssl_certificate /etc/letsencrypt/live/chat.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/chat.yourdomain.com/privkey.pem; # SSL协议和加密套件配置,禁用不安全的旧版本 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # 启用SSL会话缓存,提升性能 ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off; # 启用OCSP Stapling,提高SSL握手速度和隐私性 ssl_stapling on; ssl_stapling_verify on; # 安全相关的HTTP响应头 add_header Strict-Transport-Security “max-age=63072000; includeSubDomains; preload” always; add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection “1; mode=block” always; # 可选:内容安全策略,如果WebUI有复杂资源加载需求可能需要调整 # add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’; style-src ‘self’ ‘unsafe-inline’; img-src ‘self’ data: https:;” always; # 核心:反向代理配置,将请求转发到本地的ChatGLM-6B WebUI location / { # 假设你的ChatGLM-6B WebUI运行在本地7860端口 proxy_pass http://127.0.0.1:7860; # 传递原始客户端信息 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; # 告诉后端这是HTTPS请求 # WebSocket支持(Gradio等框架的WebUI常需要) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection “upgrade”; # 超时设置,AI模型推理可能耗时较长 proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; send_timeout 300s; # 禁用缓冲,对于流式响应(如ChatGLM的逐字输出)很重要 proxy_buffering off; proxy_request_buffering off; proxy_cache off; } # 可选:静态文件缓存,如果WebUI有大量静态资源可以提升性能 # location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { # proxy_pass http://127.0.0.1:7860; # proxy_cache_valid 200 302 6h; # proxy_cache_valid 404 1m; # add_header X-Cache-Status $upstream_cache_status; # } # 独立的访问日志和错误日志,便于排查问题 access_log /var/log/nginx/chatglm_access.log; error_log /var/log/nginx/chatglm_error.log; }4.2 启用配置并测试Nginx
保存并退出编辑器(在nano中是Ctrl+X,然后按Y,再按Enter)。接下来,启用这个站点配置:
# 创建从sites-available到sites-enabled的符号链接 sudo ln -s /etc/nginx/sites-available/chatglm /etc/nginx/sites-enabled/在重启Nginx之前,至关重要的一步是测试配置文件语法是否正确:
sudo nginx -t如果输出nginx: configuration file /etc/nginx/nginx.conf test is successful,恭喜你,配置语法没问题。如果有错误,它会明确指出错误行和原因,请根据提示回头检查配置文件。
测试通过后,重新加载Nginx配置使其生效:
sudo systemctl reload nginx # 或者使用 restart,但reload更优雅,不会中断现有连接 # sudo systemctl restart nginx4.3 验证HTTPS访问
现在,打开你的浏览器,访问https://chat.yourdomain.com。你应该能看到:
- 浏览器地址栏显示绿色的锁标志,表示连接是安全的。
- 成功加载ChatGLM-6B的WebUI界面。
你可以使用命令行工具快速验证:
curl -I https://chat.yourdomain.com应该返回HTTP/2 200或者HTTP/1.1 200 OK的状态码。
注意事项:如果遇到502 Bad Gateway错误,首要原因是Nginx无法连接到后端的ChatGLM-6B服务。请检查:
- ChatGLM-6B WebUI进程是否在运行?
ps aux | grep :7860- WebUI是否监听在
127.0.0.1:7860而不是0.0.0.0:7860?如果是后者,Nginx的proxy_pass也需要相应改为http://服务器内网IP:7860,但监听本地回环地址更安全。- 服务器本地防火墙(如UFW)是否允许Nginx进程访问7860端口?
sudo ufw status verbose
5. 高级配置、优化与安全加固
基础配置完成后,我们的服务已经可以安全访问了。但对于生产环境,还需要一些优化和加固,以提升性能、稳定性和安全性。
5.1 性能优化配置
AI对话可能涉及较长的上下文和生成时间,我们需要调整Nginx的一些默认参数来适应。
在刚才的server块中,可以添加或调整以下指令:
# 在 server { ... } 块内添加 # 调整客户端请求体大小限制,如果上传大文件或长文本可能需要 client_max_body_size 50M; # 增加各类超时时间,防止长对话或复杂推理超时 client_body_timeout 300s; client_header_timeout 300s; keepalive_timeout 300s; # 启用Gzip压缩,减少网络传输量 gzip on; gzip_vary on; gzip_min_length 1024; gzip_proxied any; # 对代理的响应也进行压缩 gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;5.2 安全加固配置
除了SSL和基础的安全头,我们还可以增加一些限制:
# 在 server { ... } 块内添加 # 限制HTTP请求方法,只允许GET, POST, HEAD等必要方法 if ($request_method !~ ^(GET|POST|HEAD|OPTIONS)$) { return 405; } # 限制特定目录的访问(如果WebUI有管理后台等路径) # location /admin { # deny all; # return 404; # } # 防止非法Host头攻击 if ($host !~ ^(chat\.yourdomain\.com|yourdomain\.com)$ ) { return 444; # Nginx特有的444状态码,直接关闭连接 } # 设置更严格的CSP(内容安全策略),根据WebUI实际加载的资源调整 # 初始配置可以较宽松,稳定后再收紧 # add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’ https://cdn.jsdelivr.net; style-src ‘self’ ‘unsafe-inline’; img-src ‘self’ data: https:; font-src ‘self’ data:; connect-src ‘self’ wss:;” always;5.3 负载均衡配置(可选)
如果你的ChatGLM-6B服务负载很高,或者为了高可用,可以在多台服务器上部署WebUI实例,然后用Nginx做负载均衡。
首先,在Nginx主配置文件(/etc/nginx/nginx.conf)的http { ... }块内,定义一个上游服务器组(upstream):
http { ... # 定义上游服务器组,名为chatglm_backend upstream chatglm_backend { # 假设你有三台运行WebUI的服务器 server 192.168.1.101:7860 weight=3 max_fails=3 fail_timeout=30s; # 权重高,性能好 server 192.168.1.102:7860 weight=2 max_fails=3 fail_timeout=30s; server 192.168.1.103:7860 weight=1 max_fails=3 fail_timeout=30s backup; # 备份服务器 # 负载均衡算法,可选 least_conn(最少连接), ip_hash(会话保持)等 # least_conn; } ... }然后,修改我们之前server块中的location /部分,将proxy_pass指向这个上游组:
location / { proxy_pass http://chatglm_backend; # 其余proxy_set_header等配置保持不变... }这样,Nginx就会将请求分发到上游服务器组中的各个实例。weight参数控制权重,backup标记备份服务器(只有当主服务器都不可用时才启用)。max_fails和fail_timeout定义了健康检查机制。
6. 故障排查、监控与日常维护
部署完成后,稳定的运行离不开持续的监控和及时的故障排查。
6.1 常见问题与解决方案速查表
| 问题现象 | 可能原因 | 排查命令与解决方案 |
|---|---|---|
| 502 Bad Gateway | 后端ChatGLM-6B服务未启动或崩溃;端口不对;防火墙阻止。 | 1.ps aux | grep -E “(gradio|python)”2. sudo netstat -tulpn | grep :78603. 检查WebUI日志。 4. curl -v http://127.0.0.1:7860(在Nginx服务器上测试后端)。 |
| SSL证书错误 (浏览器提示不安全) | 证书路径错误;证书过期;证书域名不匹配。 | 1.sudo nginx -t检查配置。2. sudo certbot certificates查看证书状态。3. 检查Nginx配置中 ssl_certificate和ssl_certificate_key路径。4. 使用 openssl x509 -in /path/to/fullchain.pem -text -noout查看证书详情。 |
| 连接超时 (长时间无响应后断开) | Nginx或后端服务超时设置太短;服务器负载过高。 | 1. 在Nginx配置中增加proxy_connect_timeout,proxy_read_timeout等值(如300s)。2. 检查服务器资源(CPU、内存、GPU)使用率: htop,nvidia-smi。3. 查看Nginx错误日志 tail -f /var/log/nginx/chatglm_error.log。 |
| 413 Request Entity Too Large | 客户端上传的数据(如长文本)超过了client_max_body_size限制。 | 在Nginx配置的server或http块中增加client_max_body_size 100M;(根据需求调整)。 |
| WebSocket连接失败 (WebUI功能异常) | Nginx未正确配置WebSocket代理。 | 确保配置中包含proxy_http_version 1.1;和proxy_set_header Upgrade/Connection指令。 |
| 域名访问跳转到默认页 | Nginx配置中server_name未正确设置;默认站点未禁用。 | 1. 检查配置文件中server_name是否正确。2. 确认 /etc/nginx/sites-enabled/下没有其他默认配置文件冲突。3. sudo nginx -T | grep server_name查看所有生效的server_name。 |
6.2 日志监控与分析
日志是排查问题的第一手资料。我们之前配置了独立的访问和错误日志。
- 实时查看错误日志:
sudo tail -f /var/log/nginx/chatglm_error.log。当出现问题时,这里会有详细的错误信息。 - 分析访问日志:
sudo tail -f /var/log/nginx/chatglm_access.log。可以查看访问来源、请求路径、状态码、响应时间等。 - 使用日志分析工具:对于长期运营,可以使用
goaccess、awstats等工具生成可视化的访问报告。
然后就可以通过浏览器查看详细的统计报告了。sudo apt install goaccess goaccess /var/log/nginx/chatglm_access.log --log-format=COMBINED -o /var/www/html/report.html
6.3 自动化维护脚本
我们可以编写一个简单的Shell脚本,将日常维护任务自动化,比如检查证书有效期、清理旧日志、重载配置等。
创建脚本文件/usr/local/bin/nginx_chatglm_maintain.sh:
#!/bin/bash echo “=== ChatGLM-6B Nginx 维护脚本开始运行 $(date) ===” # 1. 检查SSL证书状态 echo “1. 检查SSL证书状态...” sudo certbot certificates # 2. 尝试续期即将过期的证书(Certbot会自动判断,这里只是手动触发检查) echo -e “\n2. 尝试续期证书(模拟)...” sudo certbot renew --dry-run if [ $? -eq 0 ]; then echo “证书续期检查通过。” else echo “警告:证书续期检查未通过,请手动检查。” fi # 3. 清理30天前的旧日志 echo -e “\n3. 清理旧日志文件...” find /var/log/nginx -name “chatglm_*.log.*” -type f -mtime +30 -delete echo “已清理30天前的日志压缩文件。” # 4. 重新加载Nginx配置(如果配置测试成功) echo -e “\n4. 测试并重载Nginx配置...” if sudo nginx -t; then sudo systemctl reload nginx echo “Nginx配置已重载。” else echo “错误:Nginx配置测试失败,请检查配置文件。” exit 1 fi echo -e “\n=== 维护脚本执行完毕 $(date) ===”给脚本添加执行权限,并添加到crontab中,例如每周一凌晨3点执行:
sudo chmod +x /usr/local/bin/nginx_chatglm_maintain.sh sudo crontab -e # 在crontab文件中添加一行 0 3 * * 1 /bin/bash /usr/local/bin/nginx_chatglm_maintain.sh >> /var/log/nginx_maintenance.log 2>&1经过以上步骤,你的ChatGLM-6B WebUI就已经从一个简单的本地服务,升级为一个拥有自定义域名、HTTPS加密、经过性能优化和安全加固的准生产级应用了。这套Nginx反向代理+SSL的方案,其核心思想和配置同样适用于其他基于Web的AI模型服务,如Stable Diffusion WebUI、Ollama WebUI等,你只需要修改proxy_pass的后端地址和端口即可。