From db7fbfec46f961600d36b364e194b20e61df40ec Mon Sep 17 00:00:00 2001 From: Lemon-miaow Date: Sun, 27 Sep 2026 17:34:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(preflight):=20=E6=8E=A2=E6=B5=8B=20k3s=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=99=A8=E5=9C=A8=20SELinux=20=E4=B8=BB?= =?UTF-8?q?=E6=9C=BA=E4=B8=8A=E8=A6=81=E7=94=A8=E7=9A=84=20rpm.rancher.io?= =?UTF-8?q?=EF=BC=8C=E8=BF=90=E7=BB=B4=E6=89=8B=E5=86=8C=E5=88=97=E5=87=BA?= =?UTF-8?q?=20FELIS=5FARTIFACT=5FDIR=20=E5=AE=89=E8=A3=85=E4=BB=8D?= =?UTF-8?q?=E8=A6=81=E6=94=BE=E8=A1=8C=E7=9A=84=E5=9C=B0=E5=9D=80=EF=BC=8C?= =?UTF-8?q?README=20=E4=B8=8D=E5=86=8D=E8=AF=B4=E5=86=85=E7=BD=91=E4=B8=BB?= =?UTF-8?q?=E6=9C=BA=E8=83=BD=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- deploy/bootstrap.sh | 21 +++++++++++++++++++- deploy/bootstrap_test.sh | 43 +++++++++++++++++++++++++++++++++++++++- docs/operations.md | 28 ++++++++++++++++++++++---- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1454af3..bacd6a3 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ curl -fsSL https://raw.githubusercontent.com/FelisMC/Felis/main/deploy/bootstrap 脚本将自动安装 K3s,在 K3s 内部署 PostgreSQL 与控制平面,并启动设置向导。完成后浏览器访问已配置的域名进入控制面板即可使用。 -安装发布版时,二进制、全部镜像与 Velocity 插件都取自该版本在 CI 里预构建好的 release 附件,逐个核对 `SHA256SUMS` 后导入,主机上无需 Docker、Gradle 或 Go,也不从 Docker Hub 拉取;某个附件缺失或校验不符时,只有那一个镜像退回到本机构建,并给出提示(见 [故障排查 §15c](docs/troubleshooting.md))。内网或受限网络的主机可以先把 release 附件拷到本机,再用 `FELIS_ARTIFACT_DIR=<绝对路径>` 安装(见 [运维手册 §1](docs/operations.md#1-supported-hosts))。旧版本装在宿主上的 PostgreSQL 会在重跑时整库迁进 K3s,宿主上的那份停用保留,供回退(见 [运维手册 §4](docs/operations.md#4-upgrading-the-pieces-around-felis))。 +安装发布版时,二进制、全部镜像与 Velocity 插件都取自该版本在 CI 里预构建好的 release 附件,逐个核对 `SHA256SUMS` 后导入,主机上无需 Docker、Gradle 或 Go,也不从 Docker Hub 拉取;某个附件缺失或校验不符时,只有那一个镜像退回到本机构建,并给出提示(见 [故障排查 §15c](docs/troubleshooting.md))。附件也可以先拷到本机,再用 `FELIS_ARTIFACT_DIR=<绝对路径>` 安装,Felis 自己的二进制、镜像和插件就都取自这个目录;k3s 及其镜像、JRE、cloudflared、Velocity 和 Via 插件照旧从 GitHub 与 PaperMC 下载,RHEL、Fedora、openSUSE Leap 这类开着 SELinux 的主机还要从 rpm.rancher.io 装 k3s-selinux,系统软件包来自发行版的源。所以出网受限的主机要放行这几处的 HTTPS(或设 `https_proxy`),preflight 会在改动主机之前逐个探测,完全断网的主机目前装不了(地址清单见 [运维手册 §1](docs/operations.md#1-supported-hosts))。旧版本装在宿主上的 PostgreSQL 会在重跑时整库迁进 K3s,宿主上的那份停用保留,供回退(见 [运维手册 §4](docs/operations.md#4-upgrading-the-pieces-around-felis))。 动手之前,脚本先检查内存、磁盘、端口、网段冲突、已有的 Kubernetes 和外网连通,把所有问题一次列出并停下,主机上什么都没改(检查项见 [运维手册 §1](docs/operations.md#1-supported-hosts))。 diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 72e5518..f80b717 100644 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -1228,6 +1228,20 @@ systemd_is_init() { [ -d /run/systemd/system ]; } mem_total_kb() { awk '/^MemTotal:/ { print $2 }' /proc/meminfo; } +# k3s_adds_selinux_rpm reports whether k3s's install.sh will install k3s-selinux from +# Rancher's RPM repository (rpm.rancher.io), mirroring its setup_selinux and +# install_selinux_rpm: on a host with an SELinux policy directory that is Red Hat-like (one +# of these release files) or names suse first in ID_LIKE. dnf or zypper failing to reach the +# repository fails the k3s install. $1 is a root to read under, for the tests. +k3s_adds_selinux_rpm() { + local root="${1:-}" f + [ -d "${root}/usr/share/selinux" ] || return 1 + for f in redhat-release centos-release oracle-release fedora-release system-release; do + [ -r "${root}/etc/${f}" ] && return 0 + done + [ "${OS_ID_LIKE%% *}" = suse ] +} + preflight_platform() { case "$(uname -m)" in x86_64|amd64|aarch64|arm64) ;; @@ -1436,7 +1450,12 @@ preflight_hosts() { printf '%s\n' "api.github.com required" fi fi - [ -x "$K3S_BIN" ] || printf '%s\n' "raw.githubusercontent.com required" + if ! [ -x "$K3S_BIN" ]; then + printf '%s\n' "raw.githubusercontent.com required" + if k3s_adds_selinux_rpm; then + printf '%s\n' "rpm.rancher.io required" + fi + fi [ -n "$FELIS_VELOCITY_FORK_JAR" ] || printf '%s\n' "fill-data.papermc.io required" if host_builds_expected; then printf '%s\n' "registry-1.docker.io required" diff --git a/deploy/bootstrap_test.sh b/deploy/bootstrap_test.sh index 56041af..a50126a 100644 --- a/deploy/bootstrap_test.sh +++ b/deploy/bootstrap_test.sh @@ -3473,7 +3473,8 @@ run_pf() { pid_unit() { printf "%s\n" "${PF_UNITS:-}" | awk -v p="$1" "\$1 == p { print \$2 }"; } existing_ancestor() { printf "%s\n" "$1"; } path_populated() { case " ${PF_POPULATED:-} " in *" $1 "*) return 0 ;; esac; return 1; } - preflight; echo "WENT ON"' 2>&1 + k3s_adds_selinux_rpm() { [ -n "${PF_SELINUX_RPM:-}" ]; } + if [ -n "${PF_HOSTS:-}" ]; then preflight_hosts; else preflight; echo "WENT ON"; fi' 2>&1 } out="$(run_pf)" expect "a healthy host passes preflight" "OK: preflight passed" "$out" @@ -3580,6 +3581,46 @@ out="$(PF_TUI=1 PF_DOWN=api.github.com run_pf)" expect "the setup console only warns without it: its binary is already here" "WARN: preflight: cannot reach api.github.com" "$out" expect "and goes on" "OK: preflight passed" "$out" +# k3s's install.sh installs k3s-selinux from Rancher's RPM repository on an SELinux host of +# the Red Hat or SUSE family (the CentOS Stream VM has its rancher-k3s-common.repo), and the +# k3s install fails when dnf cannot reach it. +out="$(PF_SELINUX_RPM=1 PF_DOWN=rpm.rancher.io run_pf)" +expect "k3s's SELinux package repository is required where its installer adds it" "cannot reach rpm.rancher.io over HTTPS" "$out" +out="$(PF_DOWN=rpm.rancher.io run_pf)" +expect "and not probed where it does not" "OK: preflight passed" "$out" +: > "$pfroot/k3s"; chmod +x "$pfroot/k3s" +out="$(PF_SELINUX_RPM=1 PF_DOWN=rpm.rancher.io run_pf)" +expect "nor once k3s is installed" "OK: preflight passed" "$out" +rm -f "$pfroot/k3s" +# The same test install.sh makes, against a root laid out as each family's host is. +selroot="$(mktemp -d)" +adds_rpm() { OS_ID_LIKE="$1" bash -c "$(awk '/^k3s_adds_selinux_rpm\(\) \{/,/^}/' "$BS")"' + if k3s_adds_selinux_rpm "$0"; then echo yes; else echo no; fi' "$selroot"; } +mkdir -p "$selroot/etc" +: > "$selroot/etc/centos-release" +expect "a Red Hat-like host without an SELinux policy directory gets no k3s-selinux" no "$(adds_rpm "rhel fedora")" +mkdir -p "$selroot/usr/share/selinux" +rm "$selroot/etc/centos-release" +for f in redhat-release centos-release oracle-release fedora-release system-release; do + : > "$selroot/etc/$f" + expect "a host with /etc/$f and an SELinux policy directory gets k3s-selinux" yes "$(adds_rpm "")" + rm "$selroot/etc/$f" +done +expect "so does one whose ID_LIKE names suse first (openSUSE Leap)" yes "$(adds_rpm "suse opensuse")" +expect "install.sh adds no repository where suse comes second (Tumbleweed)" no "$(adds_rpm "opensuse suse")" +expect "nor on Debian with SELinux policies installed" no "$(adds_rpm debian)" +rm -rf "$selroot" + +# docs/operations.md lists the hosts an install from FELIS_ARTIFACT_DIR still downloads from, +# for a network that admits only those: every host preflight probes there must be in it. +ops="$(dirname "$BS")/../docs/operations.md" +artdoc="$(awk '/^`FELIS_ARTIFACT_DIR=` installs/,/^### /' "$ops" 2>/dev/null)" +hosts="$(PF_HOSTS=1 PF_ARTIFACT_DIR=/srv/felis-release PF_SELINUX_RPM=1 run_pf)" +expect "an install from FELIS_ARTIFACT_DIR probes GitHub" "github.com required" "$hosts" +for h in $(printf '%s\n' "$hosts" | awk '{ print $1 }'); do + expect "operations.md names ${h} for an install from FELIS_ARTIFACT_DIR" "| \`${h}\`" "$artdoc" +done + # Three problems, one report, nothing done. out="$(PF_MEM_KB=1000000 PF_ARCH=armv7l PF_DOWN=github.com run_pf)" expect "every problem is in the one report" "preflight found 3 problem(s); nothing on this host has been changed" "$out" diff --git a/docs/operations.md b/docs/operations.md index c583355..190efb1 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -60,8 +60,10 @@ once, then stops with nothing touched **[SH-TESTED]**: (a Docker network there is the usual case); a wider route such as a `10.0.0.0/8` VPN is a warning; - HTTPS to the hosts it downloads from: GitHub and PaperMC's download API always, Docker - Hub when it builds images on the host. A host counts as reachable once a TLS handshake - with it completes, and each gets three tries two seconds apart. Installing a release, an + Hub when it builds images on the host, Rancher's RPM repository where k3s's installer + adds it (the list is under "Where the binary and the images come from"). A host counts + as reachable once a TLS handshake with it completes, and each gets three tries two + seconds apart. Installing a release, an unreachable Docker Hub is a warning (it is needed only if an asset turns out unusable); from `FELIS_ARTIFACT_DIR` it is not checked. @@ -144,10 +146,28 @@ the images are in the registry, when: release's assets downloaded there (every `felis-*` file and `SHA256SUMS`), or the directory `deploy/build-release-artifacts.sh ` wrote. Nothing of Felis's own is downloaded or built (except the game images under `FELIS_GAME_STACK=latest`, which no release -ships), so an asset the directory lacks, or one failing its checksum, stops the install; k3s, -the JRE, cloudflared and Velocity still come from GitHub and PaperMC. It +ships), so an asset the directory lacks, or one failing its checksum, stops the install. It cannot be combined with `FELIS_REF` or `FELIS_SKIP_FETCH`, which name a source too. +The rest of the host's software still downloads, so the host needs outbound HTTPS to these, +directly or through `https_proxy`. A host with no outbound access cannot be installed yet +**[SH-TESTED]**: + +| Host | What comes from it | +|---|---| +| `github.com`, and the githubusercontent.com hosts its release downloads redirect to | k3s and its images (`k3s-airgap-images-.tar.zst`), cloudflared, the Temurin JRE, ViaVersion, ViaBackwards and ViaRewind | +| `raw.githubusercontent.com` | k3s's install script, until k3s is installed | +| `rpm.rancher.io` | k3s-selinux, which k3s's install script adds on an SELinux host of the Red Hat or SUSE family (CentOS Stream, RHEL, Rocky, Alma, Fedora, openSUSE Leap), until k3s is installed | +| `fill-data.papermc.io` | the Velocity jar, unless `FELIS_VELOCITY_FORK_JAR` supplies one | +| the distribution's package mirrors | the base packages (CA certificates, OpenSSL, curl and tar where missing), and container-selinux beside k3s-selinux | + +Preflight probes each named host above before it changes anything and lists every one it +cannot reach in one refusal (`cannot reach … over HTTPS`); the package manager reports its +own mirrors. An override adds a host the download itself tries: `FELIS_JRE_VERSION` reads +`api.adoptium.net`, a `FELIS_VELOCITY_VERSION` other than the pinned one reads +`fill.papermc.io`, and `FELIS_GAME_STACK=latest` builds its images on the host from Docker +Hub (which preflight probes), PaperMC, Limbo's CI and LuckPerms. + ``` # on a machine with access: the release's assets for the host's architecture gh release download v1.4.0 --repo FelisMC/Felis --dir felis-v1.4.0 \