11 KiB
opsx-vpn 部署与升级
本文件根据服务器上的 /home/ubuntu/depoly.md 整理;以代码仓库中的步骤为准,实际主机、端口、访问凭据和安全组规则按环境调整。不要将管理员密码、SQLite 数据库、data/secret.key 或实例私钥提交到仓库。
服务器准备
- Ubuntu 24.04;安装 Git、Go、Node.js、npm 和项目所需的协议软件包。运行 OpenVPN 专线还需要
openvpn、easy-rsa、iproute2与iptables。OIDC 专线要求 OpenVPN 2.6.2+,另需安装openvpn-auth-oauth2到PATH或data/bin/。 - 在 VPN 网关上开启 IPv4 转发,按实际启用的协议开放 VPN 数据端口。管理端
18080应仅供可信网络或 SSH 隧道访问。运行账户需要管理 TUN 和防火墙的权限。 - 服务在仓库目录运行;默认数据目录为
./data。data/保存数据库、加密密钥和各实例配置,升级时不得删除或覆盖。
首次构建与启动
git clone https://gitea.91ai.io/rlwj-lab/opsx-vpn.git
cd opsx-vpn
cd frontend && npm ci && npm run build && cd ..
go build -ldflags="-s -w" -o opsx-vpn ./backend
sudo sh -c 'VPN_LISTEN_ADDR=:18080 setsid nohup ./opsx-vpn > /tmp/opsx-vpn.log 2>&1 < /dev/null &'
curl --fail http://127.0.0.1:18080/api/health
前端资源在构建 Go 二进制时内嵌,修改前端后须重新执行 两个构建步骤。首次登录请立即修改初始密码并启用适当的管理端保护。
在现有服务器上升级
先确认服务器工作树干净且仓库地址、分支符合预期。以下操作以 /home/ubuntu/opsx-vpn 和管理端口 18080 为例;升级前记录已有 VPN 实例进程与健康状态。
cd /home/ubuntu/opsx-vpn
git status --short
curl --fail http://127.0.0.1:18080/api/health
sudo install -d -m 700 /tmp/opsx-vpn-backups
sudo cp -p opsx-vpn "/tmp/opsx-vpn-backups/opsx-vpn.bak-$(date +%Y%m%d-%H%M%S)"
git pull --ff-only origin master
cd frontend && npm run build && cd ..
go build -ldflags="-s -w" -o opsx-vpn.new ./backend
编译通过后,按监听端口核对管理程序 PID,精确停止该进程;不要停止仍在运行的 OpenVPN 实例。确认端口释放后替换并启动:
sudo ss -tlnp | grep ':18080'
# 确认 PID 确实属于 opsx-vpn 后:sudo kill <管理程序PID>
sudo mv opsx-vpn.new opsx-vpn
sudo chmod 755 opsx-vpn
sudo sh -c 'cd /home/ubuntu/opsx-vpn && VPN_LISTEN_ADDR=:18080 setsid nohup ./opsx-vpn > /tmp/opsx-vpn.log 2>&1 < /dev/null &'
curl --fail http://127.0.0.1:18080/api/health
sudo ss -tlnp | grep ':18080'
再检查页面静态资源、/tmp/opsx-vpn.log 和原有 VPN 实例状态。备份只放在 /tmp/opsx-vpn-backups,验证成功后仅保留最新两份。若新版本无法启动,停掉新管理进程,复制该目录中最近的 opsx-vpn.bak-* 到 opsx-vpn 并按上面的方式启动;如涉及数据模型变更,先依据对应变更的迁移说明处理数据库,不能直接覆盖 data/。
飞书 / OIDC 登录入口
http://121.4.111.208:18080 是旧管理入口,不是 OIDC issuer 或安全的凭据配置入口。当前内置飞书身份服务启用后以现有可信 HTTPS 域名的 /id 为 issuer,提供发现文档、JWKS、授权、令牌和用户信息接口;飞书应用上游回调是 https://<域名>/id/feishu/callback,OpenVPN 认证组件的回调是 https://<域名>/oauth2/callback。管理端通过 HTTPS 保存飞书 App ID/Secret 与允许的 tenant_key,VPN Client Secret 系统生成、服务器内部传递,不通过管理 API 回显。发行者禁用时不能将管理域名充当 issuer。
内置方案复用管理域名与证书;先在「设置 → 飞书身份」启用身份服务并同步公网路由,Nginx 仅允许固定 /id/ 身份路径。创建并启动唯一一条使用当前域名的 OpenVPN OIDC 测试专线后再次同步,才会把 /oauth2/ 转发到其本机认证组件 127.0.0.1:19090+。未启动专线时不会开放 /oauth2/ 路由。不要把认证端口或 OpenVPN 管理 socket 暴露到公网。详见 接入说明。
该域名须由你控制并解析到公网入口。管理员可在“设置 → 域名与证书”保存 test-link.appx365.com,由 Nginx 处理公网监听;VPN_TLS_DOMAIN 等环境变量优先于页面配置。保存配置并不会自动安装 Nginx、开放安全组或签发证书。HTTP 可以使用 IPv4 与自定义端口。HTTPS IPv4 证书为约六天的短期证书,需要 Certbot 5.4+(支持 IP webroot 与短期 profile)、公网 80 可达和有效定时续签;服务器现有 Ubuntu Certbot 2.9.0 不具备此能力,不能仅凭页面保存地址就认为已启用 IP HTTPS。
旧实例如果显式配置 data/tls-mode=autocert 或 VPN_TLS_MODE=autocert,仍沿用 Go 直监听 80/443 以避免升级时断网,但页面不再提供切换入口模式,也不允许在旧模式下保存新的公网入口。迁移时先备份入口模式、程序和证书,在维护窗口内准备 Nginx/Certbot 与可回退的站点配置,停用占用公网端口的 Go 管理进程,将入口模式显式改为 nginx,启用 Nginx 站点,再启动管理进程并核对登录、OIDC 发现文档、OpenVPN 浏览器回调和证书续签。任何验证失败都应恢复备份的配置、站点和程序。不能只修改模式文件后重启:未准备好站点会让公网入口不可用。新实例未写模式配置时默认为 nginx,不会自行监听公网端口。
Nginx 模式:HTTP-01 与路径白名单
“设置 → 首次引导”先检查 root、默认出口、IPv4 转发;管理员可单独启用 IPv4 转发。OpenVPN、WireGuard、IPSec 等依赖仍在“创建专线”选择相应协议时单独安装,不会因进入引导页而批量安装。“Nginx 入口与证书 → 准备 Nginx / Certbot”会读取 /etc/os-release,仅在 Ubuntu 使用 apt-get、TencentOS Server 4 使用 dnf 安装 Nginx/Certbot,并创建 /var/lib/opsx-vpn/acme/.well-known/acme-challenge。页面会实时显示安装日志;需以 root 运行平台,其他系统显示不支持。Ubuntu 上如果已有 /usr/sbin/policy-rc.d,初始化会拒绝覆盖该文件;安装期间临时阻止软件包脚本自动启动 Nginx,正常结束后移除临时策略。若进程在安装时被强制杀死,检查并移除该临时策略后再试。TencentOS 上安装后也需核实发行版的软件包脚本没有启动默认站点;如发行版仓库没有 Certbot,页面报告失败,由管理员检查软件源。初始化不改写已有站点,不会主动启用 80/443,也不会签发证书。
“预览 Nginx 配置”仅生成当前域名和后端实际注册 API 路由对应的两段站点配置,不会写入系统目录或启动服务。第一段监听 80,仅从 /var/lib/opsx-vpn/acme 提供 /.well-known/acme-challenge/;其他路径 return 444。第二段在证书已签发后监听 443:只反代已知前端页面、构建资源和已注册 API,其余路径 return 444;未知 TLS 主机名拒绝握手。切换模式必须按以下顺序进行(先备份现有站点,检查是否已有服务占用 80/443):
- 在设置页安装
nginx、certbot,检查云安全组 TCP 80/443 和域名 A/AAAA 记录;保存公网域名与 Nginx 入口模式,重启 opsx-vpn 使模式生效。页面的“启用站点并申请证书”会核对已有站点和端口冲突,拒绝覆盖非默认站点;发行版默认软链接移至/etc/nginx/opsx-vpn-default.disabled。Go 与 Nginx 不能同时监听 80/443。 - 点击启用操作后,服务生成 HTTP-01 站点并校验
nginx -t,使用certbot certonly --webroot申请证书;失败时页面展示过程与错误,并保留 HTTP 验证站点供重试。Certbot 当前使用无邮箱注册,续签异常不会发送邮件提醒。 - 证书签出后程序自动追加 HTTPS 站点、检查配置并重载,同时安装固定续签钩子(
nginx -t+systemctl reload nginx)。确认 Certbot 续签定时器运行,执行certbot renew --dry-run检查续签;生产验证时再核对--run-deploy-hooks对钩子的实际效果。证书状态页读取实际的证书到期日;不要仅以站点文件存在判断公网可用。
新版续签钩子仅在 Certbot 成功续签并重载 Nginx 后追加时间和证书标识到权限受限的 /var/log/opsx-vpn/cert-renewals.log,证书页展示最近记录;没有记录不代表续签失败,可能尚未到期。定时检查与失败原因查 systemctl status certbot.timer、journalctl -u certbot.service 和 /var/log/letsencrypt/letsencrypt.log。HTTP(包括 HTTP IP)不使用证书,也没有续签记录。
2026-10-22 生产实例已启用 test-link.appx365.com,证书有效至 2027-01-19,certbot renew --dry-run --run-deploy-hooks --non-interactive 模拟续签成功。当前管理服务仍在公网 :18080 监听,沿用 HTTP 地址的客户端可绕过 Nginx 的路径白名单;完成客户端地址迁移后,需限制 18080 仅回环访问。模拟续签执行钩子时 nginx -t 的正常 stderr 被 Certbot 记录为警告,但退出成功。
4. 确认入口模式为 Nginx,启动或重启 opsx-vpn 并设置 VPN_LISTEN_ADDR=127.0.0.1:18080;确认 https://<域名>/api/health、登录及各业务页面可用,未知路径断开,80 的挑战仍可读,然后收紧 18080 公网安全组。若现有业务必须从公网直连 18080,先迁移这些客户端。
不要只开放 /oauth2/callback:认证组件还需要 /oauth2/ 下的登录入口。内置身份服务方案通过设置页同步已托管的 Nginx 站点;外部发行者或独立认证域名仍须单独配置,不能直接复用管理站点路径。若代理和 VPN 主机分离,预览里的 127.0.0.1 指代理主机自身,应改成受限私网地址并保护传输链路。回退时恢复原 Nginx 配置,运行 nginx -t 后重载,不删除 data/、签名密钥或已有证书。
内置 issuer 的发现文档位于 https://<域名>/id/.well-known/openid-configuration,不属于 ACME 路径;Nginx 仅放行固定 /id/ 身份端点、HTTP-01 验证路径及已配置专线的 /oauth2/ 前缀,其余保持 444。认证端口默认 19090,仅监听回环;新增 OIDC 专线自动递增并跳过已配置或已监听的端口,仍以启动时冲突检测为准。
启用飞书认证前,需安装并验证 openvpn-auth-oauth2、准备身份提供方凭据、配置 HTTPS 反代,并用支持 WebAuth 的客户端联调。现有 LDAP 拨号用户不会自动绑定飞书用户。