Files
opsx-vpn/docs/deploy.md
T

80 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/` 保存数据库、加密密钥和各实例配置,升级时不得删除或覆盖。
## 首次构建与启动
```bash
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 实例进程与健康状态。
```bash
cd /home/ubuntu/opsx-vpn
git status --short
curl --fail http://127.0.0.1:18080/api/health
sudo cp -p opsx-vpn "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 实例**。确认端口释放后替换并启动:
```bash
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 实例状态。若新版本无法启动,停掉新管理进程,复制最近的 `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 暴露到公网。详见 [接入说明](../README.md#openvpn-飞书--oidc-浏览器认证)。
该域名须由你控制并解析到公网入口。管理员可在“设置 → 域名与证书”保存 `test-link.appx365.com`,并选择 Go 或 Nginx 入口模式;`VPN_TLS_DOMAIN` 和 `VPN_TLS_MODE` 环境变量优先于页面配置。两种模式只能选一种来占用 TCP 80/443,保存配置并不会安装 Nginx、开放安全组或签发证书。
Go 模式(默认)使用 `golang.org/x/crypto/acme/autocert` 监听 80/443,处理 HTTP-01、自动签发和续签;首次访问 `https://test-link.appx365.com/api/health` 才开始签发。证书和 ACME 账号密钥在 `data/acme`,须备份。此模式下 80 的非挑战请求会跳转 HTTPS,443 的管理站点沿用 Gin 路由,**不会**对未知路径执行 Nginx `return 444`。如需严格的公网路径白名单,使用下面的 Nginx 模式。端口空闲、公网 DNS 和云安全组 TCP 80/443 通畅是两种模式的共同前置条件。
### Nginx 模式:HTTP-01 与路径白名单
“设置 → 首次引导”先检查 root、默认出口、IPv4 转发;管理员可单独启用 IPv4 转发。OpenVPN、WireGuard、IPSec 等依赖仍在“创建专线”选择相应协议时单独安装,不会因进入引导页而批量安装。“可选 · HTTPS 公网入口 → 准备 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):
1. 在设置页安装 `nginx`、`certbot`,检查云安全组 TCP 80/443 和域名 A/AAAA 记录;保存公网域名与 Nginx 入口模式,重启 opsx-vpn 使模式生效。页面的“启用站点并申请证书”会核对已有站点和端口冲突,拒绝覆盖非默认站点;发行版默认软链接移至 `/etc/nginx/opsx-vpn-default.disabled`。Go 与 Nginx 不能同时监听 80/443。
2. 点击启用操作后,服务生成 HTTP-01 站点并校验 `nginx -t`,使用 `certbot certonly --webroot` 申请证书;失败时页面展示过程与错误,并保留 HTTP 验证站点供重试。Certbot 当前使用无邮箱注册,续签异常不会发送邮件提醒。
3. 证书签出后程序自动追加 HTTPS 站点、检查配置并重载,同时安装固定续签钩子(`nginx -t` + `systemctl reload nginx`)。确认 Certbot 续签定时器运行,执行 `certbot renew --dry-run` 检查续签;生产验证时再核对 `--run-deploy-hooks` 对钩子的实际效果。证书状态页读取实际的证书到期日;不要仅以站点文件存在判断公网可用。
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 拨号用户不会自动绑定飞书用户。