Skip to content

主机管理

平台支持把构建好的 VitePress / VuePress 站点 一键发布到远程 Linux 主机。所有要发布的目标主机都集中在「主机管理」面板统一管理,SSH 凭据用 AES-256-GCM 加密存储,任何明文都不落盘。


核心特性

  • 🔒 AES-256-GCM 加密:SSH 密码 / 私钥 / passphrase 全部加密后存 host 表,平台只持有 THINK_HOST_CRYPTO_KEY 这个 256 bit 主密钥
  • 一键初始化 nginx:SSH 进主机 → 装包 → 启服务 → 校验 → 平台主动 HTTP 探测 → 防火墙放行,9 步流水线
  • 🚀 一键发布站点:选站点 + 选主机 → 后端 build + SCP + 解压 + reload nginx,全异步 SSE 实时进度
  • :terminal: Web 终端:xterm.js + WebSocket + PTY 直连主机 shell,排查问题不用 ssh 进堡垒机
  • 🔄 版本回滚:每次发布独立 build task,一键回到任意历史版本

主机实体

每台主机在 host 表里一行,关键字段:

字段说明
un_code业务主键 UUID,平台内唯一标识
name主机别名(运维侧自定义,如 prod-web-01)
hostSSH 目标 IP 或域名,也是平台 HTTP 探测的目标
portSSH 端口(默认 22)
usernameSSH 登录用户名
auth_typePASSWORD / PUBLIC_KEY 两种认证方式
os_type自动探测:UBUNTU / CENTOS / ROCKY / UNKNOWN
os_version/etc/os-release 的 VERSION_ID 字段
nginx_statusnginx 当前状态:NOT_INSTALLED / INSTALLED_ACTIVE / INSTALLED_INACTIVE / INIT_FAILED
nginx_web_root站点根目录,默认 /var/www/html
nginx_config_dirnginx 配置目录,默认 /etc/nginx
nginx_conf_d_dirconf.d 目录,默认 /etc/nginx/conf.d
keep_versions每个站点在该主机上保留的历史版本数(默认 3)
last_check_at / last_check_success / last_check_message最近一次 SSH 连通性探测结果
last_init_at / last_init_success / last_init_message最近一次 nginx 初始化结果

凭据加密

HostCryptoServiceTHINK_HOST_CRYPTO_KEY 这个 32 字节 hex 主密钥(从环境变量读),把凭据加密成 ciphertext 存 host 表。

加密算法:AES-256-GCM

  • key = THINK_HOST_CRYPTO_KEY(env,hex 编码,32 字节)
  • IV = 12 字节随机,每条记录独立
  • 密文格式:base64(IV 12B || ciphertext || GCM tag 16B)(共 ≥ IV+ciphertext+tag 三段,直接拼接后整体 base64)

启动校验: AdminApplication 启动时会检查 THINK_HOST_CRYPTO_KEY 是否已设置,缺失直接 fail-fast 退出(防止用空 key 启动后给空加密)。

使用流程: 任何需要 SSH 的接口都走 HostService.requireWithSecret(unCode) → 取出记录 → AES-GCM 解密 → 返回带明文密码的 DTO(内存用,绝不写日志/响应)。

yaml
# application.yml
host-crypto:
  key: ${THINK_HOST_CRYPTO_KEY}  # 必须设,32 字节 hex,启动校验
bash
# 生成强 key
openssl rand -hex 32
# 输出:9f3a1b... 64 字符 hex
# 设到环境变量 / .env / K8s Secret
export THINK_HOST_CRYPTO_KEY=9f3a1b...

连通性探测

点击主机行的「探测」按钮 → HostProbeService 异步 SSH 登录 + 解析 /etc/os-release + systemctl is-active nginx + 探测公网 HTTP 80 是否通。

自动识别 的 OS(读取 /etc/os-releaseID 字段,fallback 到 ID_LIKE):

ID映射到备注
ubuntu / linuxmint / popUBUNTUDebian 系
centos / rhel / olCENTOSRHEL 7 / 8 系
rocky / almalinux / almaROCKYRHEL 8+ 系
fedora / amzn / amazoneuler / tencentos / opencloudosCENTOSdnf 系
debian暂不支持提示用户升级到 Ubuntu 或手动适配
其它UNKNOWN提示用户手动确认是否兼容

探测结果回写 last_check_* 字段,前端实时刷新。


Web 终端

主机行的「终端」按钮 → xterm.js + WebSocket 直连主机 PTY。

链路:

xterm.js (browser) 
  → WebSocket /api/ws/host/shell?hostUnCode=...&token=...
  → Umi dev 代理 /ws
  → Spring WebSocket / HostShellWebSocketHandler
  → SshConnection.openShellChannel() 拿到 PtyChannel
  → stdin/stdout 双向透传到 xterm

鉴权: WebSocket upgrade 不支持 header,token 走 query ?token=xxx,WebSocket handler 内部用 AuthHelper.authenticate(request, token) 手动验,失败立即 close session。

安全限制:

  • 仅 admin 角色可连接
  • 单个主机同时只允许一个终端 session(后续接了会收到 "session busy" 关闭帧)

下一步

基于 VitePress 构建