跳到主要内容

服务器单机模式安装

本页介绍在自己的 Linux 服务器部署单机 Runtime 的两种方式:使用 Soln 安装器通过 SSH 部署,或在服务器终端使用 CLI 部署。首次部署可按下面的安装器流程操作;需要自行管理服务器配置时,可使用后面的 CLI 教程。本机电脑安装见本机安装。

使用 Soln 安装器部署云服务器​

使用 Soln 安装器 1.0.1 或更新版本,在自己的电脑上连接服务器并完成部署。不需要先在电脑上安装 Docker,也不需要预先在服务器上安装 Soln CLI;Runtime、数据库和业务文件安装在目标服务器上。

开始前准备​

  • 服务器:当前自动部署支持 Ubuntu 24.04、systemd,CPU 架构为 x86_64 或 ARM64。建议使用专用服务器;发现已有容器或部署时,按检查结果确认归属,不能直接覆盖。
  • SSH 连接:准备服务器地址、SSH 用户名、端口,以及密码或私钥。SSH 用户需要是 root,或具有免密码 sudo 权限。安装器所在电脑必须能连接这个地址;内网 IP 只有在同一网络、VPN 等可达环境下才能使用。
  • Soln 账号:准备已有工作区和具有 tenant.runtime.deployment.manage 权限的成员账号;在浏览器中登录并授权工作区。
  • 访问地址与端口:准备完整 HTTPS 地址,例如 https://runtime.example.com。域名的 DNS 需要指向服务器,云安全组和服务器防火墙需放行 SSH、80 和 443 端口。自动证书验证使用公网 80 端口,不能只放行 HTTPS。
  • 容量与网络:服务器需能访问控制面、软件源、证书服务及镜像下载入口。根据业务数据、镜像下载解压和升级余量规划磁盘;内存和空间不足的建议不等于安装一定会失败或成功。

可填写 HTTPS 域名或 IP。使用 IP 自动申请证书时,必须是证书服务可验证的公网 IP;内网 IP 不能依靠此流程自动获取公网可信证书。域名在中国大陆访问时,还需确认备案及接入要求,且实际公网访问没有跳转到拦截页。详细环境要求见服务器环境准备。

第一步:连接云服务器​

  1. 在自己的电脑上打开 Soln 下载页,按电脑系统和 CPU 架构下载安装器。
  2. 打开 Soln,在「注册空间」菜单选择「云服务器部署」。已有空间列表中可通过「注册更多空间」进入同一流程。
  3. 填写「服务器地址」「SSH 用户名」,在「认证方式」选择「密码」或「SSH 私钥」并填写对应凭据。服务器地址只填 IP 或主机名,不带 https://、端口或路径;SSH 端口在「高级设置」填写,默认 22。
  4. 点击「连接并检查」。首次连接时,将显示的 SSH 主机指纹与云控制台或服务器管理员提供的指纹核对,一致后点击「信任并连接」。
  5. 查看操作系统、资源、Docker 和已有部署检查结果。此时只读取服务器信息;Docker 尚未安装会在后续部署阶段处理。先解决阻断项,再继续。

服务器重装后主机密钥通常会变化。收到主机密钥变化提示时,先在云控制台核实新指纹,再重新建立信任;不要仅因为 IP 相同就忽略提示。

第二步:登录并准备存储​

  1. 点击「登录 Soln」,在浏览器中完成登录并授权目标工作区,等待工作区信息返回安装器。
  2. 填写「访问地址」,必须是完整 HTTPS 地址,不带业务路径、查询参数或片段。「高级设置」可修改安装目录,默认 /opt/soln-tenant-runtime;数据目录默认 /srv/soln/data。
  3. 在存储方式下拉菜单中选择以下一种方案。
存储方式需要操作什么如何确认就绪
使用自动加密存储点击「检查可用容量」,按页面显示的范围选择加密卷容量,登录工作区后点击「创建加密存储」显示 LUKS2 卷已挂载、自动解锁已配置
使用已有云平台加密盘先在云控制台确认加密属性,并在服务器上挂载该盘;在安装器填写数据目录、检查数据盘,勾选已确认加密挂载及启动配置检查通过,且已确认云平台加密

自动加密存储创建的是服务器磁盘上的 LUKS2 文件卷,无需另购云盘。创建最小值为 11 GiB;实际可选范围由宿主文件系统可用空间和系统预留量决定,最小值不代表完整部署所需容量。文件卷会占用原磁盘空间,不会增加总容量。查看「首次部署容量规划」后再创建;识别到已有卷时会复用它,并按实际可用空间提供扩容入口,不重新格式化。

自动解锁密钥保存在服务器上,仅 root 可读取,重启后自动解锁。整机备份可能同时包含加密卷和密钥,应妥善保护备份。已有云平台加密盘的加密属性需在云控制台核实,SSH 检查不能独立证明云平台加密。

首次部署会配置业务数据及容器镜像存储使用加密数据存储。已有镜像存储不会在首次容量规划中自动迁移;需要迁移时,使用部署后的「查看空间详情」。系统盘保留操作系统和安装工具。更多规划说明见存储与容量管理。

  1. 确认证书服务条款;如果工作区已有 Runtime 登记,还需确认重新绑定。重新绑定会使原连接凭据失效,确认前核对工作区和目标服务器。
  2. 工作区授权、服务器检查、加密存储及必要勾选都就绪后,点击「开始部署」。

第三步:安装并打开空间​

安装器会安装所需服务器依赖,配置 HTTPS、证书自动续期并执行续期演练,获取部署包,安装镜像和服务,最后检查实际 HTTPS 访问地址。软件源及镜像入口见部署镜像。

「安装镜像和服务」显示「预计10–30分钟」及已执行时间。这是时间安排参考,下载速度、已有缓存和服务器配置都会影响耗时;以实际日志和状态为准。

  • 安装中:左侧「取消」会请求停止本次安装,右侧显示「安装中」。取消不会回滚已完成的步骤,也不会删除已有文件或服务。
  • 连接中断或无法获取状态:安装由服务器任务执行,失去连接不代表任务已停止。按提示重新连接并检查,确认原任务状态后再决定是否重试,不重复启动部署。
  • 安装失败:保留日志与现有文件,处理报错后点击「检查并重试」。需要修改部署信息时点击「上一步」;继续使用同一工作区、访问地址和目录。
  • 部署完成:安装及 HTTPS 健康检查通过后,当前访问地址自动加入空间列表,点击「打开空间」进入系统。若保存列表失败,点击「重试保存空间」。

健康检查成功后,安装器定向清理本次任务确认不再需要的临时下载文件,安装日志限量保留;业务数据、部署配置、运行依赖及证书续期文件会保留。已有迁移源数据和恢复资料仍需在确认部署正常后另行处理,不要直接删除数据目录或容器存储。

部署后管理​

在空间列表右键目标空间,选择「查看空间详情」。连接服务器,在页面内登录 Soln,确认安装目录后点击「读取服务器详情」。可用操作按实际存储和部署配置显示:

  • 扩容加密卷:仅对识别到的自动加密文件卷提供,且只支持增大;页面按实际可用空间计算范围。云平台加密盘先在云控制台扩容,再按支持情况在详情页扩展文件系统,或按云平台说明操作。
  • 迁移到其他数据盘:迁移同一服务器上当前空间的业务数据目录(含数据库和文件)、容器镜像及容器引擎存储。目标是另一块已挂载加密盘上的空目录;复制期间停止空间服务及容器引擎,校验后切换。旧数据保留供恢复,确认新存储正常后再处理。
  • 修改访问域名:在页面填写新的 HTTPS 地址并授权修改,安装器处理服务器配置和证书。新域名需提前完成 DNS 与公网端口配置;修改完成后空间列表同步新地址。证书申请失败时先检查公网访问与验证日志,不能通过更新租户版本解决 DNS 或拦截问题。

使用 CLI 部署​

下面的 CLI 教程在服务器终端执行;已使用安装器成功部署的空间,无需再执行首次登记与安装命令。

先通过 SSH 登录服务器,再执行 sudo -i 进入 root 终端。下面的 npm install -g、sl 和 docker 命令都在这个终端中运行;sudo 前缀保留,root 执行时同样可用。

以下示例使用 Ubuntu 24.04、部署目录 /opt/soln-tenant-runtime、加密数据目录 /srv/soln/data 和域名 runtime.example.com。复制命令前,把示例域名、租户子域名和邮箱换成自己的值。

开始前:填写部署信息​

本教程的主路线是 Ubuntu 24.04、systemd、单机服务器部署。第一次部署请选择这一条路线;已有数据库、Temporal 和对象存储的团队可使用外部服务模式。不同系统不要直接套用下面的安装命令。

必填信息从哪里获取示例(必须替换)
服务器公网 IP、SSH 用户及密钥云服务器控制台或服务器管理员实际服务器 IP;不能使用文档示例地址
租户子域名控制面租户信息example,是租户标识,不是访问域名或租户 UUID
有部署权限的成员邮箱该租户的成员账号operator@example.com,平台管理员账号不能直接代替
控制面 API 地址所属环境的管理员中国大陆示例 https://api.solncn.com,海外环境使用对应地址
租户访问域名自己管理的 DNSruntime.example.com,不是控制面的“自定义域名”字段
部署目录、数据目录在这台服务器规划/opt/soln-tenant-runtime、/srv/soln/data
数据卷方案确认新空盘或已有加密卷独立数据盘、已有加密卷、或按容量规划的加密文件卷

把表格填好后再开始,逐个命令块执行,对照该步骤的成功标志;同一步中前一个命令失败就停止。Docker、Node.js、Cosign 可独立准备,但全部依赖检查通过后才能安装 Runtime。域名、邮箱和 API 地址在后文都要替换。安装、登录、升级使用同一个服务器用户;本教程统一使用 root 终端。

正式部署的容量、自动恢复方案及后续扩容见存储与容量管理。

1. 准备服务器、账号与磁盘​

  1. 在控制面创建租户,准备有 tenant.runtime.deployment.manage 权限的租户成员账号。
  2. 按服务器环境准备选择小量测试或正式容量路线。按部署镜像:基础软件选择中国大陆镜像入口或官方入口,安装 Docker Engine、Compose、Buildx、Node.js 22+ 和 Cosign。入门配置为 2 核 4 GiB,小规格主机无 Swap 时按环境准备教程创建 2 GiB Swap。执行 docker version、docker compose version、docker buildx version、node -v、cosign version,确认均可运行。
  3. 从下方选择一种加密存储路线。云服务器需要无人值守恢复时,优先使用云平台原生加密数据盘:云平台处理加密,Linux 按文件系统 UUID 挂载,无需输入 LUKS 口令。使用 LUKS 时先解锁再挂载;下方口令示例需要重启后人工恢复。已有数据卷只复用,不格式化。准备好数据卷后,确认 数据目录本身确实是挂载点:
findmnt /srv/soln/data
stat -c '%a %U:%G %n' /srv/soln/data
df -h / /srv/soln/data

云平台原生加密盘的来源是数据设备,例如 /dev/vdb 或其分区,必须在云控制台核实加密状态和挂载到实例的磁盘身份;LUKS 的来源是 /dev/mapper/...。两种路线的目录权限都应为 700,权限和文件系统类型不能证明底层加密。云平台加密盘的 sl storage status 可能显示 encryption: unverified,因为 Linux 无法核实云平台底层加密。CLI 还要求部署目录所在文件系统至少有 10 GiB 可用空间;升级时会并存新旧镜像,应额外预留空间。当前完整单机部署以 2 核、4 GiB 内存作为入门支持配置,系统盘建议至少 60 GiB;业务负载仍需验证,详见容量规划。

从镜像入口安装 Cosign​

下载地址见部署镜像:文件下载。以下命令安装 Cosign v3.1.2,并自动选择 AMD64 或 ARM64 文件。

在服务器 root 终端执行。默认使用 GitCode;使用 GitHub 备份时,将 SOLN_COSIGN_DOWNLOAD_BASE 替换为 https://github.com/solnsu/soln-installer-releases/releases/download/v1.0.0:

(
set -e
SOLN_COSIGN_DOWNLOAD_BASE='https://gitcode.com/lunaris_soln/soln-installer-releases/releases/download/v1.0.0'
case "$(uname -m)" in
x86_64) SOLN_COSIGN_ARCH=amd64 ;;
aarch64) SOLN_COSIGN_ARCH=arm64 ;;
*) echo 'Unsupported architecture'; exit 1 ;;
esac
SOLN_COSIGN_TMP=$(mktemp -d)
trap 'rm -rf "$SOLN_COSIGN_TMP"' EXIT
curl -fL --connect-timeout 15 \
"$SOLN_COSIGN_DOWNLOAD_BASE/cosign_checksums.txt" \
-o "$SOLN_COSIGN_TMP/cosign_checksums.txt"
curl -fL --connect-timeout 15 \
"$SOLN_COSIGN_DOWNLOAD_BASE/cosign-linux-$SOLN_COSIGN_ARCH" \
-o "$SOLN_COSIGN_TMP/cosign-linux-$SOLN_COSIGN_ARCH"
(cd "$SOLN_COSIGN_TMP"; sha256sum --ignore-missing -c cosign_checksums.txt)
install -m 0755 "$SOLN_COSIGN_TMP/cosign-linux-$SOLN_COSIGN_ARCH" /usr/local/bin/cosign
cosign version
)

校验应输出 OK,cosign version 应显示 GitVersion: v3.1.2。使用其他版本时,按官方入口安装教程选择文件与校验值。

路线 A:云平台原生加密数据盘​

在云控制台创建与实例同地域、同可用区的加密数据盘,挂载到该实例,并核实加密状态与所需密钥权限。阿里云 ECS 使用的是实例块存储云盘,不是企业网盘。本路线不在 Linux 中额外创建 LUKS 加密层。

查看磁盘,将序列号或稳定设备标识与云控制台中的磁盘对应:

lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,UUID,SERIAL,MOUNTPOINTS
ls -l /dev/disk/by-id/
findmnt /srv/soln/data

已有数据: 使用已有文件系统,跳过格式化。如果租户已经使用其他数据卷,先按存储迁移流程处理,再切换挂载;下方新盘步骤不会迁移数据。

仅限新空盘: 将路径替换为已确认空盘的稳定设备标识。命令会拒绝分区、已有文件系统标记、已挂载设备及已安装的租户,并将整块空数据盘格式化为 ext4:

SOLN_DATA_DEVICE='/dev/disk/by-id/REPLACE_WITH_CONFIRMED_EMPTY_DATA_DISK'
(
set -e
test -b "$SOLN_DATA_DEVICE"
test "$(lsblk -dn -o TYPE "$SOLN_DATA_DEVICE")" = disk
test "$(lsblk -nr -o NAME "$SOLN_DATA_DEVICE" | wc -l)" -eq 1
test -z "$(lsblk -nr -o MOUNTPOINTS "$SOLN_DATA_DEVICE")"
test ! -f /opt/soln-tenant-runtime/.soln/deployment.json
test ! -e /dev/mapper/soln-tenant-data
if mountpoint -q /srv/soln/data; then
echo '数据目录已经挂载,停止'
exit 1
fi
if [ -d /srv/soln/data ]; then
test -z "$(find /srv/soln/data -mindepth 1 -maxdepth 1 -print -quit)"
fi
SOLN_DATA_SIGNATURES=$(wipefs --no-act --noheadings --output TYPE "$SOLN_DATA_DEVICE")
test -z "$SOLN_DATA_SIGNATURES"
lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,SERIAL,MOUNTPOINTS "$SOLN_DATA_DEVICE"
read -r -p '确认该云平台加密盘为空;输入完整设备路径继续:' SOLN_CONFIRMED_DEVICE
test "$SOLN_CONFIRMED_DEVICE" = "$SOLN_DATA_DEVICE"
mkfs.ext4 -m 0 -L soln-tenant-data "$SOLN_DATA_DEVICE"
)

单独配置持久挂载。已有 ext4 卷先将 SOLN_DATA_DEVICE 设为实际文件系统设备或分区。此步骤只在安装前、目标目录未挂载且为空时执行;/etc/fstab 已有该路径配置时,先检查原配置,不重复追加:

(
set -e
test -b "$SOLN_DATA_DEVICE"
test "$(blkid -s TYPE -o value "$SOLN_DATA_DEVICE")" = ext4
test -z "$(lsblk -nr -o MOUNTPOINTS "$SOLN_DATA_DEVICE")"
test ! -f /opt/soln-tenant-runtime/.soln/deployment.json
if mountpoint -q /srv/soln/data; then
echo '数据目录已经挂载,停止'
exit 1
fi
if [ -d /srv/soln/data ]; then
test -z "$(find /srv/soln/data -mindepth 1 -maxdepth 1 -print -quit)"
fi
awk '$1 !~ /^#/ && $2 == "/srv/soln/data" { found=1 } END { exit found ? 1 : 0 }' /etc/fstab
SOLN_DATA_UUID=$(blkid -s UUID -o value "$SOLN_DATA_DEVICE")
test -n "$SOLN_DATA_UUID"
cp -a /etc/fstab "/etc/fstab.soln-backup-$(date +%Y%m%d%H%M%S)"
install -d -m 0700 /srv/soln/data
printf '\nUUID=%s /srv/soln/data ext4 defaults,nofail,x-systemd.device-timeout=30s 0 2\n' "$SOLN_DATA_UUID" >> /etc/fstab
systemctl daemon-reload
mount /srv/soln/data
test "$(findmnt -n -o UUID --mountpoint /srv/soln/data)" = "$SOLN_DATA_UUID"
chmod 0700 /srv/soln/data
findmnt -o TARGET,SOURCE,FSTYPE,UUID --mountpoint /srv/soln/data
df -h / /srv/soln/data
)

记录文件系统 UUID,用于重启检查。nofail 允许磁盘不可用时主机仍可启动以便排障;下方 Docker 挂载保护仍会阻止租户在未挂载时启动。格式化或写入 fstab 后若挂载失败,只修复失败步骤,不重新格式化。跳过路线 B,继续「配置 Docker 挂载保护」。

路线 B:LUKS 人工口令加密​

主机自行管理加密时选择此路线。以下示例不配置无人值守解锁;需要自动恢复时,由管理员配置外部密钥服务,参见重启恢复与密钥管理。

新空数据盘或已有 LUKS 卷​

先只读检查,不做格式化:

lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS
findmnt /
findmnt /srv/soln/data
  • 已有加密数据卷:复用管理员提供的映射设备和挂载点,只解锁、挂载并校验,不能执行下面的格式化命令。
  • 新空数据盘:核对云控制台的磁盘容量、设备路径和上面的结果,确认不是系统盘、没有挂载、没有需要保留的数据。无法确认就停止,请服务器管理员确认。

下面会清空所选设备。只有确认新盘可清空后,才把 SOLN_DATA_DEVICE 改成实际设备路径;示例不会自动选择磁盘:

SOLN_DATA_DEVICE='/dev/REPLACE_WITH_CONFIRMED_EMPTY_DATA_DISK'

随后在同一个 root 终端执行:

(
set -e
test -b "$SOLN_DATA_DEVICE"
test ! -e /dev/mapper/soln-tenant-data
if mountpoint -q /srv/soln/data; then
echo '数据目录已经挂载,停止'
exit 1
fi
lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS "$SOLN_DATA_DEVICE"
read -r -p '确认该设备可清空;输入完整设备路径继续:' SOLN_CONFIRMED_DEVICE
test "$SOLN_CONFIRMED_DEVICE" = "$SOLN_DATA_DEVICE"
apt-get update
apt-get install -y cryptsetup
cryptsetup luksFormat "$SOLN_DATA_DEVICE"
cryptsetup open "$SOLN_DATA_DEVICE" soln-tenant-data
mkfs.ext4 -m 0 /dev/mapper/soln-tenant-data
install -d -m 0700 /srv/soln/data
mount /dev/mapper/soln-tenant-data /srv/soln/data
chmod 0700 /srv/soln/data
findmnt /srv/soln/data
)

记录实际设备路径、映射名称和解锁口令;它们用于重启后恢复。成功后跳过下面的加密文件卷步骤,继续「配置 Docker 挂载保护」。

可选:小容量 LUKS 文件卷​

如果没有独立数据盘,可以在系统盘创建 LUKS 文件卷。下面用 8 GiB 展示小容量部署;它不是正式业务的统一容量要求。格式化后约有 7.8 GiB,由数据库、附件和工作流数据共同使用。已有加密文件卷在容量足够且有备份时可继续正式使用;新企业部署仍优先独立数据盘。扩大系统盘不会自动扩大该文件卷。

以下命令只用于尚无 /var/lib/soln/tenant-data.luks、尚未安装租户的机器;已有数据卷时不要重做格式化。先确认系统盘空间足够,再执行命令块;cryptsetup luksFormat 会要求设置解锁口令:

(
set -e
df -h /
apt-get install -y cryptsetup
if [ -e /var/lib/soln/tenant-data.luks ] || [ -e /dev/mapper/soln-tenant-data ] || mountpoint -q /srv/soln/data; then
echo '已有数据文件或挂载点,停止;不要格式化现有数据'
exit 1
fi
install -d -m 0700 /var/lib/soln /srv/soln/data
fallocate -l 8G /var/lib/soln/tenant-data.luks
chmod 0600 /var/lib/soln/tenant-data.luks
cryptsetup luksFormat /var/lib/soln/tenant-data.luks
cryptsetup open /var/lib/soln/tenant-data.luks soln-tenant-data
mkfs.ext4 -m 0 /dev/mapper/soln-tenant-data
mount /dev/mapper/soln-tenant-data /srv/soln/data
chmod 0700 /srv/soln/data
findmnt /srv/soln/data
)

成功标志: findmnt /srv/soln/data 显示来源为 /dev/mapper/soln-tenant-data,stat -c '%a' /srv/soln/data 输出 700;重新执行 df -h / /srv/soln/data,部署目录所在系统盘仍至少有 10 GiB 可用空间。任一步失败即停止,不重复执行格式化来重试。

记住解锁口令;这个文件与系统盘共用物理空间,不是额外增加 8 GiB 容量。关机后需重新执行 cryptsetup open 和 mount 才能启动租户容器。

配置 Docker 挂载保护​

以上任一数据卷路线完成后都执行本节。

如果服务器专供这一套 Docker 容器使用,可阻止 Docker 在加密卷未挂载时启动:

sudo install -d /etc/systemd/system/docker.service.d
printf '[Unit]\nRequiresMountsFor=/srv/soln/data\nAssertPathIsMountPoint=/srv/soln/data\n' |
sudo tee /etc/systemd/system/docker.service.d/10-soln-data-mount.conf
sudo systemctl daemon-reload
sudo systemctl enable docker.service

路线 A 中,Docker 等待 fstab 配置的 UUID 挂载,无需输入 Linux 解锁口令。路线 B 中,这个依赖不会提供 LUKS 密钥:重启后需人工解锁、挂载,或在安装前配置外部密钥服务。共用 Docker 的主机不要设置这个全局条件。安装完成后按第 6 节实际重启验证恢复结果。

2. 准备域名与 HTTPS​

给 runtime.example.com 创建指向租户服务器公网 IPv4 的 DNS A 记录。阿里云 ECS 还需要在控制台选择这台实例,进入「安全组」,打开实例关联的安全组,在「入方向」添加以下两条规则:

字段HTTP 规则HTTPS 规则
授权策略允许允许
协议类型自定义 TCP自定义 TCP
来源/授权对象IPv4:0.0.0.0/0IPv4:0.0.0.0/0
目的端口范围80/80(单端口输入框填 80)443/443(单端口输入框填 443)

界面选择预置的 HTTP(80) 与填写 TCP 80 等价,HTTPS(443) 与 TCP 443 等价。规则必须添加到新租户 ECS 实际关联的安全组。SSH 22 按自己的管理 IP 授权,不需要开放数据库或容器内部端口。若启用了主机防火墙,也要放通 TCP 80、443。

成功标志: 安全组入方向能看到两条允许规则;稍后 Certbot 的 HTTP 验证能从公网访问 80 端口。证书申请出现连接超时时,先检查 DNS 是否指向这台 ECS,以及安全组和主机防火墙,而不是直接归为网络偶发故障。HTTP 80 的 ACME 验证目录需保留用于后续续期。

软件入口见部署镜像:域名与 HTTPS。在 Ubuntu 上安装 nginx 和 Certbot,然后确认 DNS:

sudo apt-get update
sudo apt-get install -y nginx certbot
sudo systemctl enable --now nginx
getent ahostsv4 runtime.example.com
sudo systemctl is-active nginx

已有该域名的 nginx 配置或证书时,先检查并复用;下面的创建及追加命令只用于首次配置。重试证书申请只重试 Certbot,不覆盖已有配置或重复追加 HTTPS server 块。

nginx 先提供 ACME 验证目录。把下面配置中的域名替换为自己的域名:

sudo install -d -m 0755 /var/www/letsencrypt
sudo tee /etc/nginx/sites-available/soln-tenant.conf >/dev/null <<'EOF'
server {
listen 80;
server_name runtime.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
default_type text/plain;
try_files $uri =404;
}
location / { return 301 https://$host$request_uri; }
}
EOF
sudo ln -sfn /etc/nginx/sites-available/soln-tenant.conf /etc/nginx/sites-enabled/soln-tenant.conf
sudo nginx -t && sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/letsencrypt -d runtime.example.com

成功标志: DNS 解析到这台租户服务器的公网 IP,nginx -t 成功,Certbot 提示证书保存路径。解析、端口验证或证书申请失败时停止,不继续追加 HTTPS 配置。

Certbot 会要求填写证书通知邮箱。获得证书后,保留上面的 80 端口配置,并追加 HTTPS 配置;证书目录也换成自己的域名:

sudo tee -a /etc/nginx/sites-available/soln-tenant.conf >/dev/null <<'EOF'

server {
listen 443 ssl;
server_name runtime.example.com;
ssl_certificate /etc/letsencrypt/live/runtime.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/runtime.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
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 Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
}
}
EOF
sudo nginx -t && sudo systemctl reload nginx

安装前本机 8080 端口上的 Runtime 还没启动,可执行:

curl -sS -o /dev/null -w '%{http_code}\n' https://runtime.example.com/health/ready

此时 502 是预期结果;必须同时确认 nginx -t 成功且 curl 没有证书错误。域名解析、连接或证书验证失败时先修复,不能继续安装。安装完成后健康接口应返回 200。

配置证书续期与 nginx 重载​

本页使用 certbot certonly --webroot,证书续期后需要让 nginx 重新加载证书。在上面的 HTTPS 配置通过 nginx -t 后执行:

sudo install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/soln-nginx-reload >/dev/null <<'EOF'
#!/bin/sh
set -eu
/usr/sbin/nginx -t
/usr/bin/systemctl reload nginx
EOF
sudo chmod 0755 /etc/letsencrypt/renewal-hooks/deploy/soln-nginx-reload
sudo systemctl enable --now certbot.timer
sudo systemctl list-timers --all certbot.timer

成功标志: 定时器列表显示 certbot.timer 已安排下次运行。deploy hook 只在证书成功续期后执行;nginx -t 不通过时会停止重载,修复配置后再重载 nginx。

验证续期及 hook:

sudo certbot renew --cert-name runtime.example.com --dry-run --run-deploy-hooks

把证书名换成 certbot certificates 中该域名实际的 Certificate Name,它可能带 -0001 后缀。成功标志: 模拟续期成功,hook 的 nginx 配置检查通过且无重载错误。失败时检查 ACME 验证目录、DNS、安全组、定时器及 nginx 配置;修复后重试,不重新创建租户。--dry-run 使用测试证书服务验证续期,--run-deploy-hooks 会实际重载 nginx,但不会把测试证书替换成线上证书。

3. 登录并生成部署文件​

在服务器安装 CLI,然后用租户成员登录控制面。按部署镜像:CLI选择中国大陆镜像入口或官方入口;国内服务器可把下面的安装命令替换为 npm install -g @soln/cli@latest --registry=https://registry.npmmirror.com。先核对镜像与 npm 官方源的包版本一致,避免安装滞后的 CLI。下面以邮件验证码为例;想用密码登录可省略 --method email:

npm install -g @soln/cli@latest
sl version
sl deployment login --base-url https://api.solncn.com \
--tenant example --email operator@example.com --method email
sl deployment status --json

确认显示的是目标租户。首次安装执行:

sl deployment register --dir /opt/soln-tenant-runtime \
--deployment-target server --deployment-mode singleMachine \
--runtime-origin https://runtime.example.com
sl deployment prepare --dir /opt/soln-tenant-runtime

成功标志: register 与 prepare 都无报错,部署目录中已生成 docker-compose.yml、.env.example 和 .soln-install-setup.json。失败时停止,保留原有文件,修复后重试失败步骤。

Origin 必须与浏览器实际访问地址一致,不能带路径或查询参数。安装授权文件 .soln-install-setup.json 包含 Agent 密钥,权限应为 600。如果 deployment status 已有登记,先确认是否为上次未完成的安装;不要为了重试就使用 register --force,它会更换 Agent 密钥。

4. 确认加密配置并安装​

下载地址统一列在部署镜像。以下镜像准备操作在 deployment prepare 完成后、安装前执行。

导入公共依赖镜像包​

能直接访问官方镜像仓库时可跳过此步骤,由安装命令拉取。需要使用镜像包时,从公共依赖镜像包下载地址选择与服务器架构匹配的文件。在下载目录执行对应命令;镜像包包含 PostgreSQL、MinIO、MinIO 客户端、Temporal 和 nginx,不包含 Docling、Soln 产品镜像。源码包无需导入 Docker。

# AMD64 / x86_64
(
set -e
printf '%s %s\n' \
'a2ecb08a4a23854e36d159f65c7a30ce1f80eed27e3ae83736ff9d6eb6d00a93' \
'soln-public-deps-linux-amd64.tar.gz' | sha256sum -c -
docker load -i soln-public-deps-linux-amd64.tar.gz
)
# ARM64
(
set -e
printf '%s %s\n' \
'433ad57439730b3bbbf60c2e4bad134fae0340f958018c3e5d5e4c6fbfc1d592' \
'soln-public-deps-linux-arm64.tar.gz' | sha256sum -c -
docker load -i soln-public-deps-linux-arm64.tar.gz
)

校验应输出 OK,随后显示五个镜像已加载。导入前按解压后的镜像大小预留磁盘空间。导入成功后可删除已下载的镜像压缩包,再执行 df -h /opt /srv/soln/data 和 docker system df 检查余量;不要删除刚导入的安装依赖镜像。

选择 Docling 镜像源​

地址见部署镜像:Docling。使用官方入口时保留生成的部署文件;中国大陆服务器可在 deployment prepare 完成后、首次安装前执行下面的替换命令,保持镜像 digest 不变:

sed -i \
's#quay.io/docling-project/docling-serve-cpu@sha256:061d35c03611bc15b73d024c8e8387bcf0624279f8b57c16c1567326f214ba56#quay.nju.edu.cn/docling-project/docling-serve-cpu@sha256:061d35c03611bc15b73d024c8e8387bcf0624279f8b57c16c1567326f214ba56#' \
/opt/soln-tenant-runtime/docker-compose.yml

替换前核对生成文件中的 Docling 引用与示例一致;不同版本按实际引用替换。执行后检查 docker-compose.yml 中 document-parser.image 已是所选入口,不能仅凭 sed 返回成功判断替换完成。

安装命令会从所选入口拉取 Docling,也可以提前下载。ARM64 服务器将 linux/amd64 改为 linux/arm64:

# ARM64 服务器将 linux/amd64 改为 linux/arm64
docker pull --platform linux/amd64 \
quay.nju.edu.cn/docling-project/docling-serve-cpu@sha256:061d35c03611bc15b73d024c8e8387bcf0624279f8b57c16c1567326f214ba56

后续部署模板若指定其他 digest,以该模板为准。Soln 产品镜像由 CLI 按签名发布清单获取短期凭据、校验签名并拉取。

确认加密配置并执行安装​

再次确认数据卷仍已挂载。首次安装、尚无 .env 时修改 .env.example;失败重试时 CLI 会保留并读取已有 .env,必须修改实际文件,不能覆盖其中已生成的密钥。以下只显示四个非密钥配置项:

findmnt /srv/soln/data
SOLN_INSTALL_ENV=/opt/soln-tenant-runtime/.env.example
if [ -f /opt/soln-tenant-runtime/.env ]; then
SOLN_INSTALL_ENV=/opt/soln-tenant-runtime/.env
fi
grep -E '^(SOLN_DATA_ROOT|SOLN_DATA_AT_REST_ENCRYPTED|RUNTIME_ORIGIN|RUNTIME_BIND_PORT)=' \
"$SOLN_INSTALL_ENV"

如果 SOLN_DATA_ROOT=/srv/soln/data 与实际一致,且已确认该目录确实位于加密卷上,再设置:

(
set -e
mountpoint -q /srv/soln/data
test -f "$SOLN_INSTALL_ENV"
sed -i 's/^SOLN_DATA_AT_REST_ENCRYPTED=.*/SOLN_DATA_AT_REST_ENCRYPTED=true/' \
"$SOLN_INSTALL_ENV"
sl install --dir /opt/soln-tenant-runtime \
--setup-file /opt/soln-tenant-runtime/.soln-install-setup.json --yes
)

进入安装前: 依赖检查全部通过、加密卷正确挂载、数据目录权限为 700、系统盘剩余空间至少 10 GiB、HTTPS 证书有效。SOLN_DATA_AT_REST_ENCRYPTED=true 只声明状态,不能代替实际加密。

安装会检查环境、校验签名、拉取镜像、迁移数据库、启动服务并等待就绪。公共依赖镜像也可能从 Docker Hub 或 Quay 拉取;中国大陆镜像入口与官方入口见部署镜像:容器镜像,Docling 镜像源应在 deployment prepare 完成后、安装前配置。Docker CE 的阿里安装源不会加速这些容器镜像,详见网络与镜像加速。如果报连接超时,先解决相应仓库的网络,再重试同一条 sl install。不要重新登记租户。需要离线转运时,应使用与服务器相同的 linux/amd64 或 linux/arm64 架构,校验文件摘要后用 docker load 导入相同的镜像名与标签。

安装等待期间可在第二个 SSH 终端执行 docker ps -a --format 'table {{.Names}}\t{{.Status}}' 查看状态。迁移、MinIO 初始化和贴纸初始化容器 Exited (0) 是正常完成;长期运行的服务应正常运行。不要重复启动安装命令,也不要因没有新日志就删除容器。CLI 若没有阶段输出,先记录 sl version,不要套用其他版本的输出判断是否卡死。

5. 验证、清理与重启约束​

看到 Soln Tenant Runtime ... is ready 后执行:

sl status --dir /opt/soln-tenant-runtime --check --json
curl -fsS -o /dev/null -w '%{http_code}\n' \
https://runtime.example.com/health/ready
docker ps --format 'table {{.Names}}\t{{.Status}}'

runtimeReady 应为 true,健康接口应返回 200,主要服务应处于运行状态。任一项不满足都尚未完成安装,先保留授权文件并检查失败服务,不重新登记租户。全部通过后再删除一次性授权文件并退出部署登录:

rm /opt/soln-tenant-runtime/.soln-install-setup.json
sl deployment logout

不要删除 .env 或 .soln/deployment.json。升级前的数据库备份位于 <部署目录>/.soln/backups,由 CLI 加密,但不在 /srv/soln/data 加密卷上;备份和密钥仍需按你的存储策略保护。不要向公网开放 PostgreSQL、MinIO、Temporal 等内部端口。完成下方重启检查:云平台原生加密盘应自动挂载;人工口令 LUKS 路线需先解锁,Docker 才能启动。

6. 服务器重启后恢复​

安装完成后,在维护时段安排一次重启,重新 SSH 登录并进入 root 终端。按所选存储路线执行对应分支。恢复时不要执行 luksFormat 或 mkfs。

路线 A:验证自动挂载​

将 UUID 替换为路线 A 中记录的文件系统 UUID。先验证准确挂载点、Docker 和容器状态,不手动启动服务:

(
set -e
SOLN_EXPECTED_DATA_UUID='REPLACE_WITH_RECORDED_FILESYSTEM_UUID'
mountpoint -q /srv/soln/data
findmnt -o TARGET,SOURCE,FSTYPE,UUID --mountpoint /srv/soln/data
test "$(findmnt -n -o UUID --mountpoint /srv/soln/data)" = "$SOLN_EXPECTED_DATA_UUID"
systemctl is-active docker.service
docker ps --format 'table {{.Names}}\t{{.Status}}'
)

部署文件中长期运行的服务使用 restart: unless-stopped;重启前被手动停止的服务不会自动启动,一次性初始化容器可以保持正常退出。等待启动健康检查完成,再执行 sl status --dir /opt/soln-tenant-runtime --check --json,并检查 https://runtime.example.com/health/ready 返回 200。启动期间短暂 502 不能直接判为失败,持续异常需检查服务日志。

自动挂载失败时,检查云盘挂载到实例的状态、密钥权限、/etc/fstab,以及 journalctl -u srv-soln-data.mount -b --no-pager。修复原因后,先恢复已配置的挂载并核对 UUID,再启动 Docker:

(
set -e
SOLN_EXPECTED_DATA_UUID='REPLACE_WITH_RECORDED_FILESYSTEM_UUID'
systemctl daemon-reload
systemctl reset-failed srv-soln-data.mount
if ! mountpoint -q /srv/soln/data; then
mount /srv/soln/data
fi
test "$(findmnt -n -o UUID --mountpoint /srv/soln/data)" = "$SOLN_EXPECTED_DATA_UUID"
systemctl reset-failed docker.service docker.socket
systemctl start docker.service
docker version --format '{{.Server.Version}}'
)

此命令用于故障恢复;修复后仍需再次重启验证无人值守恢复。

路线 B:解锁并挂载 LUKS​

LUKS 独立数据盘使用安装时记录的设备路径;加密文件卷使用 /var/lib/soln/tenant-data.luks。已有卷按管理员提供的路径和映射名称填写。已配置外部密钥服务时,先检查其解锁和挂载单元,不直接执行人工口令步骤。

SOLN_DATA_SOURCE='/替换为安装时记录的数据设备或LUKS文件路径'

Docker 报 Cannot connect to the Docker daemon 时,先检查 findmnt /srv/soln/data。如果 Docker 日志显示 AssertPathIsMountPoint 未满足,说明挂载保护阻止了启动;反复查询还可能使 docker.socket 出现 trigger-limit-hit。不要删除保护配置,按下面恢复挂载并清除失败状态。

先恢复加密卷和 Docker。任何一步失败就停止;口令在终端输入,已有映射或挂载会跳过对应操作:

(
set -e
test -e "$SOLN_DATA_SOURCE"
if ! cryptsetup status soln-tenant-data >/dev/null 2>&1; then
cryptsetup open "$SOLN_DATA_SOURCE" soln-tenant-data
fi
if ! mountpoint -q /srv/soln/data; then
mount /dev/mapper/soln-tenant-data /srv/soln/data
fi
findmnt /srv/soln/data
test "$(findmnt -n -o SOURCE --target /srv/soln/data)" = /dev/mapper/soln-tenant-data
systemctl daemon-reload
systemctl reset-failed docker.service docker.socket
systemctl start docker.socket docker.service
docker version --format '{{.Server.Version}}'
)

成功标志: 挂载来源为 /dev/mapper/soln-tenant-data,最后输出 Docker 服务端版本号。

检查或恢复租户服务​

两条存储路线完成后均按本节检查。如果容器已自动恢复,只执行状态与 HTTP 检查;需要重新启动服务时,再执行下方 Compose 命令。

安装尚未成功结束: 保留安装授权文件,重试原来的 sl install;不要运行下面的已安装部署恢复命令,也不要重新登记或格式化。

已安装部署: 从部署状态读取实际发布覆盖文件,避免使用模板里的默认产品镜像:

(
set -e
SOLN_RELEASE_OVERRIDE=$(node -e '
const fs = require("node:fs");
const state = JSON.parse(fs.readFileSync("/opt/soln-tenant-runtime/.soln/deployment.json", "utf8"));
if (typeof state.releaseOverrideFile !== "string" || !state.releaseOverrideFile) process.exit(1);
process.stdout.write(state.releaseOverrideFile);
')
test -f "$SOLN_RELEASE_OVERRIDE"
docker compose --project-directory /opt/soln-tenant-runtime \
--env-file /opt/soln-tenant-runtime/.env \
-f /opt/soln-tenant-runtime/docker-compose.yml \
-f "$SOLN_RELEASE_OVERRIDE" up -d
sl status --dir /opt/soln-tenant-runtime --check --json
curl -fsS -o /dev/null -w '%{http_code}\n' \
https://runtime.example.com/health/ready
)

确认 runtimeReady: true,并检查公网健康接口返回 200 后再使用。首次启动依赖服务可能仍在健康检查中;报错时检查对应服务。路径或映射名称与示例不同的,必须同步替换。Docker 仍无法启动时执行 systemctl status docker.service docker.socket --no-pager -l 和 journalctl -u docker.service -n 80 --no-pager,不要重新安装租户。

下一步:服务器升级与回滚。

需要更换已部署 Runtime 的访问地址时,参见更换租户访问域名。