一键初始化 nginx
主机加进来后是裸 Linux 系统(可能装了 nginx 也可能没装),需要先把 nginx 跑起来。平台提供「一键初始化」按钮,9 步流水线全自动搞定,前端的步骤条 + 实时日志面板能完整看到每一步的执行结果。
入口
「主机管理」列表里点 「初始化 nginx」 按钮(nginx 状态非 INSTALLED_ACTIVE 的主机才能点)→ 弹出 NginxInitProgressModal:
- 左侧:竖向 9 步 Stepper,每个步骤的状态有
pending(灰)/in_progress(蓝,带 loading 图标)/done(绿勾)/failed(红叉) - 右侧:深色实时日志区(自动滚到底,含「📌 主机 IP / nginx 监听 / 防火墙端口」诊断信息)+ 终态 Alert(成功/部分完成/失败)
- 顶栏:连接状态 Tag(
已连接/连接中.../连接断开)+ 终态 Tag(成功/部分完成/失败)
modal 打开立刻 EventSource 连 /api/host/nginx-init-streaming/{hostUnCode},后端在同一个 SSE 连接里完成鉴权 + 注册 emitter + 提交 init 任务,事件不会丢。
9 步流水线
[1] CONNECT → [2] PROBE_OS → [3] INSTALL_NGINX → [4] ENABLE_NGINX →
[5] VERIFY_NGINX → [6] PROBE_HTTP → [7] CHECK_FIREWALL →
[8] OPEN_FIREWALL → [9] REPROBE_HTTP → [SUCCESS / PARTIAL / ERROR]1. CONNECT —— SSH 连接
从 host 表拿密文 → AES-256-GCM 解密 → MINA SSHD 2.13 SshClient.connect() 走 22 端口。
平台用的 SSH 客户端是 Apache MINA SSHD(sshd-core 2.13),不是 JSch / sshj。MINA SSHD 是异步 NIO 实现,长连接复用,适合高频 SSH 操作。
ed25519 公钥 / 私钥在 JDK 17 上要靠 I2P eddsa 0.3.0 解析,JDK 17 自带的 EdDSA 还没实装;BouncyCastle (bcprov-jdk18on 1.78) 兜底通用 JCA。平台启动时 SecurityProviderInitializer 把 I2P EdDSA 注册为 position 1,BC 注册为 position 2。
2. PROBE_OS —— 自动识别发行版
/etc/os-release 解析(HostProbeService 之前已跑过,这里复用 host.os_type)。UNKNOWN 直接 abort,提示用户先在「探测」按钮里手动确认。
3. INSTALL_NGINX —— 包管理器安装
按 os_type 选命令:
UBUNTU→apt-get install -y nginxCENTOS→yum install -y nginxROCKY→dnf install -y nginx
5 分钟超时。SSH channel 复用: 因为 Linux server 默认 MaxSessions=10,整个 init 流程里所有命令合并为 1 条尽量少的 channel(prepareNginxDirs / openFirewallPorts(80, 443) / diagnostics()),避免触发 SshChannelOpenException: open failed。
4. ENABLE_NGINX —— 启动服务
systemctl enable --now nginx(Ubuntu/Rocky) 或 chkconfig nginx on && service nginx start(CentOS 7)。
5. VERIFY_NGINX —— 校验
nginx -v 2>&1 && systemctl is-active nginx,期望输出 active。 失败:status 写 INSTALLED_INACTIVE,前端显示红叉 + 失败原因。
6. PROBE_HTTP —— 平台主动 HTTP 探测
关键设计: 不在主机内 curl 127.0.0.1:80,而是 后端用 java.net.http.HttpClient 主动发 GET 请求到 http://<host>:80/(模拟外部用户访问),5 秒 timeout。
| 返回 | 含义 |
|---|---|
HTTP 2xx / 3xx | 端口对外通,服务可用 |
HTTP 4xx | 服务在跑但路径不对(防火墙放行了,nginx 也起得来) |
HTTP 5xx | 服务在跑但应用层错误 |
ConnectException / ConnectTimeout | 端口不通(被防火墙 / 云安全组拦截) |
这一步是「外部访问」的真实验证,不是「主机自己访问」。如果不通,继续走 step 7-9 修防火墙。
7. CHECK_FIREWALL —— 防火墙状态
按 OS 选命令,鲁棒三段判断(not-installed / active / inactive):
UBUNTU→command -v ufw+ufw status | grep '^Status: active'CENTOS/ROCKY→command -v firewall-cmd+systemctl is-active firewalld | grep '^active'
鲁棒处理:
active→ 走 step 8inactive→ 尝试启动(UFW:yes | ufw enable;Firewalld:systemctl start firewalld),再checkFirewall复查,active 才继续not-installed/unknown→ 跳过 step 8,直接进 step 9 平台探测(可能云安全组已经放行,也可能完全封住,step 9 给出结论)
8. OPEN_FIREWALL —— 放行 80/443
按 OS 选命令,一条命令同时放行 80 + 443 + reload:
UBUNTU→ufw allow 80/tcp; ufw allow 443/tcpCENTOS/ROCKY→firewall-cmd --permanent --add-port=80/tcp; firewall-cmd --permanent --add-port=443/tcp; firewall-cmd --reload
注: 防火墙不可用(not-installed / unknown / 启动失败)时,这一步标 failed 但不中断流程——继续走 step 9 平台探测,看实际情况。
9. REPROBE_HTTP —— 重测,决定终态
再一次 java.net.http.HttpClient GET http://<host>:80/,终态判定:
| 终态 | 触发条件 | 显示 |
|---|---|---|
SUCCESS | HTTP 2xx/3xx | 绿色 banner + 访问地址 http://<host>/ |
PARTIAL(成功) | HTTP 4xx/5xx(服务在跑但配置错) | 黄色 banner,提示检查 nginx server_name / 站点目录 |
PARTIAL(失败) | 平台仍然连不上 | 黄色 banner + 5 条排查方向(云安全组 / SELinux / 公网 IP / nginx 监听 0.0.0.0 / 防火墙规则被覆盖)+ 完整诊断日志 |
ERROR | 任何中间 step 异常(如 OS 不支持) | 红色 banner + 异常信息 |
终态诊断日志(📌 部分)
step 9 后,无论成功失败,都会输出一条 ─── 诊断信息 ─── 区段,含 4 行:
─── 诊断信息 ───
📌 SSH 连接的主机(面板配置): 192.168.1.208
📌 主机网卡 IP: 192.168.1.208 10.0.0.1
📌 nginx 监听 (ss/netstat): LISTEN 0 511 *:80 *:* users:(("nginx",pid=1234,fd=6))
📌 防火墙端口: 80/tcp 443/tcp
──────────────单条命令合并,1 个 SSH channel 拿全 3 项(节省 MaxSessions=10 槽位)。失败时 fallback 提示"SSH server MaxSessions 限制,可在 /etc/ssh/sshd_config 调大 MaxSessions 重启 sshd"。
常见失败原因 & 排查
平台探测不到主机 80 端口
- 云安全组没放行 —— 腾讯云 / 阿里云 / AWS 安全组需在控制台放行 80/443,后端
firewall-cmd改的是主机内 iptables,管不到云侧 - SELinux 拦截 —— Rocky / CentOS 默认开启 SELinux,执行:bash
sudo setsebool -P httpd_can_network_connect 1 sudo setsebool -P httpd_can_network_relay 1 - 主机没公网 IP —— SSH 通的 IP 是内网,公网 80 进不来。检查
ip -4 addr show是否有公网网卡 - nginx 没监听 0.0.0.0:80 —— 检查
/etc/nginx/sites-enabled/default里listen 80 default_server是否被改成127.0.0.1 - 防火墙规则被覆盖 —— firewalld 重新加载后规则可能被 reset,检查
firewall-cmd --list-ports
探测输出 HTTP 5xx
- 服务在跑但
/var/www/html/index.html不存在或无权限 - nginx
root指令指向的目录不对 - 默认站点配置缺
index指令(找不到index.html)
SSH channel open failed
主机上 cat /etc/ssh/sshd_config | grep -i MaxSessions,默认 10,调大到 50:
sudo sed -i 's/^#MaxSessions 10/MaxSessions 50/' /etc/ssh/sshd_config
sudo systemctl restart sshd下一步
nginx 起来后,到 站点发布到主机 把构建产物推上去。