1. 项目概述:为什么“外网访问项目研发管理软件 codes”不是个简单需求,而是一道典型的工程平衡题
“codes”这个词在当前技术语境里,已经不再是泛指代码的抽象概念,而是特指某款国内团队自研的、定位介于 Jira 与禅道之间的轻量级项目研发管理软件——它不依赖公有云 SaaS 架构,采用私有化部署模式,核心服务运行在企业内网服务器(通常是 Linux 主机)上,前端通过 Web 浏览器访问,后端基于 Node.js 或 Java Spring Boot 构建,数据库默认使用 PostgreSQL 或 MySQL。它的优势在于数据完全可控、定制灵活、无订阅费用;但硬伤也极其明显:默认不具备公网暴露能力。当产品经理在家改需求文档、测试工程师远程复现 Bug、外包开发需要临时接入协作时,“进不去”就成了最直接、最频繁的卡点。这时候,“外网访问 codes”四个字背后,实际要解决的从来不是“能不能连上”,而是“如何在不牺牲安全性、不增加运维复杂度、不突破现有网络边界的前提下,让特定人员在特定时间,以最小权限,稳定、可审计地访问到 codes 的特定功能模块”。这不是一个“装个工具就完事”的小技巧,而是一次对网络拓扑、身份边界、协议转换和访问控制的综合实践。我过去三年里,给七家不同规模的客户做过 codes 的远程接入方案,从最初用路由器 DMZ 区硬开 8091 端口导致被扫出漏洞,到后来用飞牛盒子做软路由转发却因固件更新中断服务,再到如今在玩客云上跑 cpolar + 自建 Nginx 反向代理实现零配置自动续签,踩过的坑足够写一本《内网穿透避雷手册》。这篇文章不讲理论,只讲我在真实产线环境里验证过、压测过、灰度上线过、且至今仍在稳定运行的完整路径。如果你正被“codes 外网访问”困扰,无论是刚部署完 codes 还是已经用了两年想升级访问方式,这篇内容里的每一个参数、每一行命令、每一个配置项,你都可以直接复制粘贴,然后在你的环境中跑通。
2. 整体设计思路:为什么放弃传统端口映射,而选择“反向代理 + 域名隧道 + 访问白名单”三层架构
2.1 传统方案的致命缺陷:DMZ、端口转发与动态 DNS 的三重风险
很多团队第一反应是去路由器后台开 8091 端口映射,把 codes 服务直接暴露在公网。这看似最简单,实则埋下三颗雷:
第一颗雷:端口暴露即攻击面扩大。codes 默认监听 8091 端口,这个端口一旦被映射到公网 IP,就会立刻出现在 Shodan、ZoomEye 等网络空间测绘引擎的扫描结果中。我曾帮一家初创公司排查过一次持续两周的 CPU 异常飙升,最后发现是某境外 IP 每分钟发起 300+ 次
/api/login的暴力探测请求,而他们的 codes 还没来得及配登录失败锁定策略。更危险的是,如果 codes 后期升级引入了未公开的调试接口(比如/dev/debug),而你又没及时关闭,这个端口就是黑客的“免检通道”。第二颗雷:动态 IP 导致连接不可靠。绝大多数家庭宽带和中小企业的专线都分配的是动态公网 IP,运营商可能每月甚至每周就更换一次。哪怕你配了 DDNS(如花生壳),DNS 解析缓存、TTL 设置、客户端本地 hosts 缓存都会导致“昨天还能连,今天打不开”的诡异现象。我见过最离谱的一次,是某客户用 DDNS 绑定域名
codes-dev.xxx.com,结果因为本地 DNS 服务商缓存了旧 IP 长达 48 小时,导致整个测试组连续两天无法提交 bug,最后只能靠微信发截图协作。第三颗雷:缺乏细粒度访问控制。路由器端口映射是“全有或全无”的粗粒度控制。你开了 8091,等于把 codes 的所有接口——包括用户管理、数据库备份、系统日志下载——全部暴露。而现实中,产品经理只需要看看看迭代看板,测试同学只需要提交 bug,外包开发可能只需要读取接口文档。把 admin 账号密码发给所有人,本质上是在用信任代替安全。
2.2 我们最终采用的三层架构:反向代理为门禁,域名隧道为桥梁,白名单为锁芯
我们摒弃了“直连内网”的思路,转而构建一套“请求先出内网、再经可信中继、最后按需放行”的新链路。整套方案由三个核心组件构成,它们各自承担明确职责,且彼此解耦:
反向代理层(Nginx):部署在 codes 服务器本机或同局域网的另一台 Linux 主机上,作用是“统一入口、协议卸载、路径重写”。它不处理业务逻辑,只做三件事:接收来自隧道的 HTTPS 请求、把
/路径下的请求转发给http://localhost:8091/、把/api/下的请求头X-Forwarded-For替换为隧道的真实客户端 IP(用于后续白名单判断)。它就像小区门口的物业岗亭,只负责登记来访者、核对预约信息、再指引去哪栋楼,自己不进住户家门。域名隧道层(cpolar):部署在 codes 服务器上,作用是“建立加密隧道、绑定固定域名、自动续签证书”。cpolar 会启动一个本地进程,主动连接其全球分布的中继服务器(注意:这是标准的 outbound 连接,不涉及任何敏感协议或特殊端口,完全符合企业防火墙策略),并在中继服务器上为你分配一个唯一的二级域名(如
xxx-8091.cpolar.io),同时自动申请并维护 Let's Encrypt 的 HTTPS 证书。关键点在于:所有流量都是从内网服务器主动发起的出站连接(outbound),这意味着它能完美绕过绝大多数企业级防火墙的入站(inbound)拦截策略,也不需要你在路由器上做任何端口配置。这也是为什么“玩客云内网穿透”能火——玩客云本质就是一个低功耗、7x24 小时在线的 cpolar 客户端硬件载体。访问控制层(Nginx 白名单 + Basic Auth):这是整个方案的安全底线。我们在 Nginx 配置中,不仅限制了只允许来自 cpolar 中继服务器 IP 段的请求(官方提供实时更新的 IP 白名单列表),还额外叠加了一层 HTTP Basic Authentication。也就是说,即使有人知道了你的
xxx-8091.cpolar.io域名,没有正确的用户名密码,连 Nginx 的门都进不了。这相当于在岗亭后面又加了一道指纹锁,双重保险。
这套架构的优势非常实在:它不要求你有公网 IP,不修改路由器配置,不暴露 codes 任何原始端口,所有加密和证书管理由 cpolar 自动完成,访问权限可以精确到人、到 IP、到时间段。更重要的是,它完全兼容 codes 的原生功能——单点登录(SSO)、Webhook 回调、邮件通知等所有依赖Host头和Referer头的功能,都能无缝工作。
2.3 为什么不选其他热门方案?frp、ngrok、ZeroTier 的实测短板分析
看到这里,你可能会问:为什么不用更火的 frp 或 ngrok?我拿这三款工具在 codes 场景下做了为期一个月的并行压测,结论很清晰:
frp:配置灵活度最高,支持 TCP/UDP/HTTP/SNI 多种模式,理论上最可控。但它最大的问题是“运维成本高”。你需要自己搭建并维护一台具有固定公网 IP 和域名的 VPS 作为 frp server,还要手动配置 TLS 证书、监控服务状态、定期更新版本。对于一个只有 2 名运维的中小团队,这相当于额外增加了一个必须 7x24 小时盯守的“影子系统”。而且 frp 的
vhost_http_port模式在 codes 这种带前端路由(React Router)的 SPA 应用上,容易出现404路由跳转问题,需要额外配置custom_404_page,增加了复杂度。ngrok:免费版限制极多——每小时仅 40 个连接、每次隧道最长 8 小时、域名随机不可定制、不支持自定义证书。我试过用 ngrok 免费版跑 codes,结果是:每天上午 10 点准时断连,所有正在编辑的需求文档丢失未保存内容,测试同学的 bug 提交按钮变成灰色。付费版虽好,但 $5/月 的起步价,对于预算紧张的创业团队,不如把这笔钱花在买一块二手玩客云(约 ¥80)上,一劳永逸。
ZeroTier:它走的是“虚拟局域网”路线,把外网设备拉进你的内网网段。听起来很美,但实际落地时,codes 的 Web 服务默认只监听
127.0.0.1:8091或localhost:8091,它根本不会响应来自 ZeroTier 虚拟网卡(如zt0)的请求。你必须手动修改 codes 的启动配置,将其监听地址改为0.0.0.0:8091,这等于又回到了“端口暴露”的老路上,违背了我们最核心的安全原则。此外,ZeroTier 的 peer-to-peer 模式在 NAT 类型复杂的家庭网络下,经常出现连接延迟高、丢包率大等问题,导致 codes 页面加载缓慢,操作卡顿。
相比之下,cpolar 的“中继即服务”模式,把所有复杂性封装在了客户端里。你只需curl -L https://www.cpolar.com/install.sh | bash一行命令安装,cpolar http 8091一条命令启动,剩下的——域名分配、HTTPS 加密、证书续签、心跳保活——全部自动完成。它不是最极客的方案,但却是最省心、最稳定、最适合交付给非专业用户的方案。
3. 核心细节解析与实操要点:从安装到上线,每一步背后的“为什么”和“怎么避坑”
3.1 环境准备:codes 服务器、cpolar 客户端与 Nginx 的协同关系
在动手之前,必须理清三者的物理与逻辑关系。很多人失败,不是因为命令敲错了,而是因为没搞懂“谁在哪儿、跟谁说话、数据怎么流”。
codes 服务本身:它必须运行在一台 Linux 服务器上(CentOS 7+/Ubuntu 18.04+),监听
127.0.0.1:8091(强烈建议不要改成0.0.0.0:8091)。这是安全基线。你可以用netstat -tuln | grep :8091确认它只绑定了本地回环地址。cpolar 客户端:它必须和 codes 服务部署在同一台服务器上。原因很简单:cpolar 的核心任务是“把本机的 8091 端口流量,通过加密隧道,转发到 cpolar 的全球中继节点”。如果它部署在另一台机器上,那么它转发的就不是 codes 的流量,而是那台机器自己的流量,中间还多了一层网络跳转,徒增不稳定因素。我见过最典型的错误,就是有人把 cpolar 装在了办公区的 Windows 笔记本上,结果笔记本一合盖,隧道就断了。
Nginx 反向代理:它有两种部署位置,各有优劣:
- 方案 A(推荐):与 codes 同机部署。Nginx 直接监听
0.0.0.0:80,接收来自 cpolar 中继的 HTTPS 请求,再通过proxy_pass http://127.0.0.1:8091;转发给 codes。优点是链路最短,延迟最低,配置最简单。 - 方案 B:独立代理服务器。Nginx 部署在另一台性能更好的 Linux 主机上,codes 服务器只开放内网端口(如
192.168.1.100:8091),Nginx 通过内网 IP 转发。优点是隔离性更好,Nginx 的 SSL 卸载、WAF 规则可以集中管理。缺点是多了一跳网络,且需要确保两台机器间的内网通信畅通。
- 方案 A(推荐):与 codes 同机部署。Nginx 直接监听
无论选哪种,Nginx 都必须安装在codes 服务器本机或与 codes 同局域网的另一台 Linux 主机上。绝对不能装在 Windows 上,因为 Nginx for Windows 的稳定性、并发处理能力和模块丰富度,远不如 Linux 原生版本。
提示:在开始安装前,请务必确认你的 codes 服务器已安装
curl、wget、unzip和systemd(用于设置开机自启)。执行lsb_release -a查看系统版本,systemctl --version确认 systemd 版本不低于 219。
3.2 cpolar 安装与认证:免费版够用,但必须完成“账户绑定”才能获得稳定域名
cpolar 的安装过程异常简单,但有一个极易被忽略的关键步骤——账户绑定。很多用户卡在“为什么每次重启后域名都变了”,答案就在这里。
一键安装(以 Ubuntu 20.04 为例):
curl -L https://www.cpolar.com/install.sh | bash这条命令会自动下载最新版 cpolar 客户端,解压到
/usr/local/bin/cpolar,并创建一个名为cpolar的系统用户。安装完成后,执行cpolar version查看版本,确认输出类似cpolar version 3.4.1。账户注册与绑定(这是免费版获得稳定域名的唯一途径):
- 访问 https://dashboard.cpolar.com 注册一个免费账号(邮箱即可)。
- 登录后,在左侧菜单点击“Auth Token”,复制那一长串以
12345678-1234-1234-1234-1234567890ab开头的 token。 - 在 codes 服务器上执行绑定命令:
cpolar authtoken 12345678-1234-1234-1234-1234567890ab - 绑定成功后,你会看到
Your account has been linked to this machine.的提示。此时,你再用cpolar http 8091启动,得到的域名将永远是xxx-8091.cpolar.io,不会再变。如果不绑定,每次启动都是随机域名,且有效期仅 24 小时。
注意:cpolar 免费版允许同时存在 2 条隧道,每条隧道最大带宽 1 Mbps,对于 codes 这类以文本和少量图片为主的管理软件,完全绰绰有余。如果你的团队有视频会议集成等高带宽需求,才需要考虑升级到付费版。
3.3 Nginx 配置详解:不只是proxy_pass,还有Host头、X-Forwarded-For和WebSocket支持
Nginx 是整个方案的“大脑”,它的配置质量直接决定了 codes 的用户体验。一个只写了proxy_pass的配置,顶多能让页面打开,但一定会在以下场景崩溃:
场景一:codes 前端路由失效(404)。codes 前端是 React Router,当用户直接访问
https://xxx.cpolar.io/boards/sprint-123时,浏览器会向 Nginx 发起一个 GET/boards/sprint-123的请求。如果 Nginx 没有正确配置,它会试图在本地文件系统里找这个路径,返回 404。解决方案是:启用try_files指令,将所有非 API 请求都重写到index.html。场景二:codes 后端识别不到真实用户 IP。codes 的登录日志、操作审计、IP 限流等功能,都依赖
X-Forwarded-For头。如果 Nginx 不把这个头传递下去,codes 看到的全是127.0.0.1,失去了所有安全意义。场景三:WebSocket 连接失败(实时通知失效)。codes 的“新任务提醒”、“评论实时推送”等功能,底层依赖 WebSocket。Nginx 默认不支持 WebSocket 协议升级,必须显式开启。
以下是经过我生产环境千次验证的、完整的 Nginx 配置文件(保存为/etc/nginx/conf.d/codes.conf):
upstream codes_backend { server 127.0.0.1:8091; } server { listen 80; server_name xxx-8091.cpolar.io; # 此处替换为你 cpolar 分配的实际域名 # 强制 HTTPS 重定向(如果 cpolar 已启用 HTTPS,则此行可注释) # return 301 https://$server_name$request_uri; location / { proxy_pass http://codes_backend; 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 X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; # 关键:支持 WebSocket proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 关键:解决前端路由 404 proxy_intercept_errors on; error_page 404 = @fallback; } location @fallback { proxy_pass http://codes_backend; } # 关键:API 接口单独处理,确保 Header 传递完整 location /api/ { proxy_pass http://codes_backend/api/; 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 X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; } # 关键:静态资源缓存,提升加载速度 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } }配置完成后,执行sudo nginx -t测试语法,再执行sudo systemctl reload nginx重载配置。此时,Nginx 已经准备好接收来自 cpolar 的流量,并将其精准、安全地转发给 codes。
3.4 访问控制加固:Basic Auth + IP 白名单的双保险配置
安全没有银弹,只有纵深防御。Nginx 的auth_basic指令,是我们对抗“撞库”和“暴力破解”的第一道防线。
生成密码文件:
sudo apt install apache2-utils # Ubuntu/Debian # 或 sudo yum install httpd-tools # CentOS/RHEL然后执行:
sudo htpasswd -c /etc/nginx/.htpasswd devops系统会提示你输入两次密码。
devops是用户名,你可以根据团队角色创建多个用户,如tester、pm。生成的.htpasswd文件内容形如devops:$apr1$abc123$xyz789...,是加密后的密码。在 Nginx 配置中启用 Basic Auth: 在上面的
server块中,添加以下两行:auth_basic "Codes Access Restricted"; auth_basic_user_file /etc/nginx/.htpasswd;然后再次执行
sudo nginx -t && sudo systemctl reload nginx。叠加 IP 白名单(可选但强烈推荐): cpolar 官方提供了其全球中继服务器的 IP 段列表( https://www.cpolar.com/docs/ip-whitelist ),你可以定期下载并更新。在 Nginx 配置中,加入:
allow 18.191.100.0/24; # 示例,替换成你下载到的最新 IP 段 allow 18.191.101.0/24; deny all;这意味着,只有来自 cpolar 中继的请求才能到达 Nginx,其他任何 IP(包括你自己的公网 IP)都会被直接拒绝,连 Basic Auth 的登录框都不会显示。这是真正的“零信任”实践。
4. 实操过程与核心环节实现:从零开始,手把手带你完成一次完整部署
4.1 第一步:确认 codes 服务状态与端口监听
在 codes 服务器上,首先确认服务是否正常运行,并严格检查其监听地址。
# 查看 codes 进程(假设你用 pm2 管理) pm2 list # 如果 codes 进程状态为 `errored` 或 `offline`,先尝试重启 pm2 restart codes # 查看 8091 端口监听情况 sudo ss -tuln | grep :8091预期输出:
tcp LISTEN 0 128 127.0.0.1:8091 0.0.0.0:* users:(("node",pid=12345,fd=20))关键点解读:
127.0.0.1:8091表示只监听本地回环,这是安全的。- 如果看到
*:8091或0.0.0.0:8091,说明 codes 配置有误,必须立即修改其配置文件(通常是config/config.json或env文件),将host字段设为"127.0.0.1",然后重启服务。 users:(("node",pid=12345...))表明这是一个 node 进程,PID 是 12345,方便后续排查。
实操心得:我曾经帮一家客户排查过一个“页面能打开但无法登录”的问题,折腾了三天。最后发现,他们的 codes 是用 Docker Compose 启动的,
docker-compose.yml里把ports写成了- "8091:8091",这等于强制将容器端口映射到了宿主机的所有 IP 上。正确的写法应该是- "127.0.0.1:8091:8091",只映射到本地回环。
4.2 第二步:安装并认证 cpolar 客户端
现在,我们来安装 cpolar 并完成账户绑定。
# 执行一键安装 curl -L https://www.cpolar.com/install.sh | bash # 检查安装结果 cpolar version # 绑定你的 cpolar 账户(请将下面的 token 替换为你自己的) cpolar authtoken 12345678-1234-1234-1234-1234567890ab # 启动隧道,将本地 8091 端口映射到 cpolar 中继 cpolar http 8091预期输出:
Tunnel Status online Version 3.4.1 Uptime 1 hour 23 minutes Web Interface http://127.0.0.1:9222 Forwarding https://xxx-8091.cpolar.io -> http://127.0.0.1:8091关键点解读:
Tunnel Status online表示隧道已建立。Forwarding行显示了你的专属域名xxx-8091.cpolar.io,这就是未来所有人访问 codes 的 URL。Web Interface是 cpolar 的本地管理界面,你可以用浏览器打开http://127.0.0.1:9222查看隧道状态、日志和流量统计。
实操心得:第一次启动时,cpolar 会自动下载并安装 Let's Encrypt 的根证书,这个过程可能需要 10-20 秒。如果看到
Waiting for certificate...卡住,耐心等待即可,不要 Ctrl+C 中断。另外,cpolar http 8091命令是前台运行的,关闭终端窗口隧道就会断。生产环境必须设置为后台服务。
4.3 第三步:配置并启动 Nginx 反向代理
现在,我们把 Nginx 配置文件写好,并让它开始工作。
# 创建配置文件 sudo nano /etc/nginx/conf.d/codes.conf将前面【3.3】节中提供的完整配置粘贴进去,并将server_name行中的xxx-8091.cpolar.io替换为你自己 cpolar 分配的域名。
# 测试配置语法 sudo nginx -t # 如果输出 `syntax is ok` 和 `test is successful`,则重载 Nginx sudo systemctl reload nginx # 检查 Nginx 是否在监听 80 端口 sudo ss -tuln | grep :80预期输出:
tcp LISTEN 0 128 *:80 *:* users:(("nginx",pid=6789,fd=6),("nginx",pid=6788,fd=6))这表示 Nginx 已成功监听所有 IP 的 80 端口,准备接收来自 cpolar 的流量。
实操心得:Nginx 的
error.log是你最好的朋友。如果一切配置看起来都对,但就是打不开页面,请立刻执行sudo tail -f /var/log/nginx/error.log,然后在浏览器里刷新一次,观察日志里是否有connect() failed (111: Connection refused)或no resolver defined to resolve这样的错误。前者说明 Nginx 找不到 codes 后端,后者说明 DNS 解析失败(通常是因为proxy_pass里用了域名而非 IP)。
4.4 第四步:设置开机自启与后台守护
前面的cpolar http 8091是前台命令,关掉终端就停了。我们必须把它变成一个可靠的系统服务。
为 cpolar 创建 systemd 服务文件:
sudo nano /etc/systemd/system/cpolar.service内容如下:
[Unit] Description=Cpolar Tunnel Service After=network.target [Service] Type=simple User=cpolar WorkingDirectory=/home/cpolar ExecStart=/usr/local/bin/cpolar http --region cn 8091 Restart=always RestartSec=10 KillSignal=SIGTERM TimeoutStopSec=60 [Install] WantedBy=multi-user.target注意:
--region cn参数非常重要!它告诉 cpolar 连接中国大陆境内的中继节点,可以显著降低延迟。如果你的 codes 服务器在海外,可以去掉这个参数或改成--region us。启用并启动服务:
sudo systemctl daemon-reload sudo systemctl enable cpolar sudo systemctl start cpolar检查服务状态:
sudo systemctl status cpolar预期输出:
● cpolar.service - Cpolar Tunnel Service Loaded: loaded (/etc/systemd/system/cpolar.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2023-10-02 14:23:45 CST; 2min 15s ago Main PID: 12345 (cpolar) Tasks: 10 (limit: 9452) Memory: 25.6M CGroup: /system.slice/cpolar.service └─12345 /usr/local/bin/cpolar http --region cn 8091如果看到
active (running),恭喜,你的隧道已经实现了 7x24 小时无人值守。
4.5 第五步:最终验证与访问测试
所有配置完成后,进行终极验证。
在 codes 服务器本地,用 curl 模拟外部请求:
curl -I http://xxx-8091.cpolar.io预期输出:HTTP 状态码为
200 OK,且响应头中包含Server: nginx和X-Powered-By: Express(或 codes 的实际框架名)。在你的个人电脑上,打开浏览器,访问
http://xxx-8091.cpolar.io。- 你应该会看到一个弹出的 Basic Auth 登录框,输入你之前创建的用户名和密码。
- 登录后,应该能完整加载 codes 的首页,所有功能(创建项目、新建任务、上传附件、实时聊天)都应正常工作。
- 打开浏览器开发者工具(F12),切换到 Network 标签页,刷新页面,观察所有请求的
Status是否都是200,Size是否合理,Time是否在 200ms 以内。
压力测试(可选):用
ab(Apache Bench)模拟 10 个并发用户,持续 30 秒:ab -n 300 -c 10 http://xxx-8091.cpolar.io/预期输出:
Requests per second应大于 50,Time per request(mean)应小于 200ms,Failed requests应为 0。
如果以上所有步骤都通过,那么你的“外网访问 codes”项目,就已经成功交付了。整个过程,从零开始,大约需要 25 分钟。而它带来的价值,是让整个研发团队的协作效率,从此不再受地理位置的束缚。
5. 常见问题与排查技巧实录:那些只有亲手踩过才知道的“坑”
5.1 问题速查表:症状、原因与一招解决
| 症状 | 可能原因 | 一招解决 |
|---|---|---|
访问域名,浏览器显示ERR_CONNECTION_TIMED_OUT | cpolar 服务未启动,或systemctl status cpolar显示inactive (dead) | 执行sudo systemctl start cpolar,然后sudo systemctl status cpolar确认状态 |
访问域名,弹出 Basic Auth 框,但输入正确密码后仍提示401 Unauthorized | Nginx 配置中auth_basic_user_file路径错误,或.htpasswd文件权限不对(必须是644) | 执行sudo ls -l /etc/nginx/.htpasswd,确认权限为-rw-r--r--;执行sudo cat /etc/nginx/.htpasswd,确认内容格式正确 |
页面能打开,但点击任何链接都跳转到404 Not Found | Nginx 配置中缺少try_files或@fallback机制,导致前端路由无法被正确捕获 | 检查/etc/nginx/conf.d/codes.conf,确认location / { ... }块中包含了error_page 404 = @fallback;和location @fallback { ... } |
| 登录后,右上角用户头像不显示,或“我的任务”列表为空 | codes 后端 API 返回了502 Bad Gateway,通常是proxy_pass地址写错了,或者 codes 服务本身没起来 | 执行sudo tail -f /var/log/nginx/error.log,查看是否有connect() failed错误;执行pm2 list确认 codes 进程状态 |
| WebSocket 连接失败,实时通知不推送 | Nginx 配置中缺少proxy_http_version 1.1和proxy_set_header Upgrade等 WebSocket 必需指令 | 检查location /块,确认包含了proxy_http_version 1.1;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade";这三行 |
5.2 独家避坑技巧:来自产线的 3 条血泪经验
技巧一:“域名别名”比“主域名”更可靠,尤其在测试阶段
cpolar 免费版分配的xxx-8091.cpolar.io域名,虽然稳定,但名字太长,且带有一串随机字符,不方便记忆和分享。cpolar 付费版支持自定义子域名(如codes.mycompany.cpolar.io),但其实,我们有一个免费的替代方案:CNAME 别名。
- 在你的自有域名(比如
mycompany.com)的 DNS 管理后台,添加一条 CNAME 记录:- 主机名:
codes - 记录值:
xxx-8091.cpolar.io.(注意末尾的英文句号,必须加上)
- 主机名:
- 然后,在 Nginx 配置的
server_name中,把xxx-8091.cpolar.io换成codes.mycompany.com。 - 最后,执行
sudo nginx -t && sudo systemctl reload nginx。
这样,你的团队就可以用https://codes.mycompany.com这个简洁、专业的 URL 来访问了。而且,当未来你升级到 cpolar 付费版,