From 281a9cce9b6b8ba6529fa075358711df3ba388f2 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 19 Oct 2026 11:37:29 +0200 Subject: [PATCH 1/2] fix(ci): name the preserved environment for sudo-rs runners ubuntu-latest is rolling over to ubuntu-26.04, whose sudo is sudo-rs. It ignores `-E` ("preserving the entire environment is not supported") and hands the child only the explicit `env` assignments, so the swarm matrix died at import with `KeyError: 'INFINITO_SRC_DIR'` before any inventory existed (PR #1009, Nextcloud#0). Jobs that landed on ubuntu-24.04 kept passing. Every `sudo -E` now passes the caller's exported names through `--preserve-env="$(compgen -e | paste -sd, -)"`, which both classic sudo and sudo-rs honour. A lint rejects `sudo -E` and bare `--preserve-env`. Co-Authored-By: Claude Opus 5.5 (1M context) --- scripts/tests/deploy/ci/one.sh | 2 +- scripts/tests/deploy/swarm/routine/00_one.sh | 2 +- .../deploy/swarm/routine/01_bootstrap.sh | 2 +- .../test_no_sudo_preserve_whole_env.py | 42 +++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/lint/repository/test_no_sudo_preserve_whole_env.py diff --git a/scripts/tests/deploy/ci/one.sh b/scripts/tests/deploy/ci/one.sh index b33b41f50f..3d09526d7e 100755 --- a/scripts/tests/deploy/ci/one.sh +++ b/scripts/tests/deploy/ci/one.sh @@ -19,7 +19,7 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../.." && pwd)" . "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/pick.sh" filesystem_pick "${INFINITO_DEPLOY_MODE}/${apps}/${INFINITO_DISTRO}" runner if [ -n "${INFINITO_DOCKER_FILESYSTEM:-}" ]; then - sudo -E "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/docker_dataroot.sh" \ + sudo --preserve-env="$(compgen -e | paste -sd, -)" "${REPO_ROOT}/scripts/tests/deploy/utils/filesystem/docker_dataroot.sh" \ "${INFINITO_DOCKER_FILESYSTEM}" "${INFINITO_DOCKER_FILESYSTEM_REQUIRED}" 30G \ "${INFINITO_DEPLOY_MODE}-runner" fi diff --git a/scripts/tests/deploy/swarm/routine/00_one.sh b/scripts/tests/deploy/swarm/routine/00_one.sh index be215fdda2..b3c4ce4af1 100755 --- a/scripts/tests/deploy/swarm/routine/00_one.sh +++ b/scripts/tests/deploy/swarm/routine/00_one.sh @@ -165,7 +165,7 @@ fi matrix_cmd=(timeout "${step_timeout}" python3 -m utils.tests.swarm.matrix) if [ "$(id -u)" -ne 0 ]; then matrix_cmd=( - sudo -E env + sudo --preserve-env="$(compgen -e | paste -sd, -)" env "PATH=$PATH" "HOME=$HOME" "SWARM_NAME=${SWARM_NAME:-}" diff --git a/scripts/tests/deploy/swarm/routine/01_bootstrap.sh b/scripts/tests/deploy/swarm/routine/01_bootstrap.sh index b0b8ee7036..f974d43e31 100755 --- a/scripts/tests/deploy/swarm/routine/01_bootstrap.sh +++ b/scripts/tests/deploy/swarm/routine/01_bootstrap.sh @@ -26,7 +26,7 @@ if command -v apt-get >/dev/null 2>&1; then if [ "$(id -u)" -eq 0 ]; then timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error else - sudo -E timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error + sudo --preserve-env="$(compgen -e | paste -sd, -)" timeout -k 30 "${APT_TIMEOUT}" apt-get "${APT_OPTS[@]}" update -qq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error fi fi diff --git a/tests/lint/repository/test_no_sudo_preserve_whole_env.py b/tests/lint/repository/test_no_sudo_preserve_whole_env.py new file mode 100644 index 0000000000..b9d79918f1 --- /dev/null +++ b/tests/lint/repository/test_no_sudo_preserve_whole_env.py @@ -0,0 +1,42 @@ +"""Forbid ``sudo -E`` and bare ``sudo --preserve-env`` in tracked .yml and .sh files.""" + +from __future__ import annotations + +import re +import unittest +from pathlib import Path + +from utils.cache.files import iter_project_files, read_text + +from . import PROJECT_ROOT + +_WHOLE_ENV = re.compile(r"\bsudo\s+(?:-\w+\s+)*(?:-\w*E\w*|--preserve-env)(?=\s|$)") + + +class TestNoSudoPreserveWholeEnv(unittest.TestCase): + def test_no_whole_environment_preservation(self) -> None: + offenders: list[str] = [] + for path_str in iter_project_files( + extensions=(".yml", ".yaml", ".sh"), + exclude_tests=True, + exclude_dirs=("docs",), + ): + rel = Path(path_str).relative_to(PROJECT_ROOT).as_posix() + for lineno, line in enumerate(read_text(path_str).splitlines(), 1): + if line.lstrip().startswith("#"): + continue + if _WHOLE_ENV.search(line): + offenders.append(f"{rel}:{lineno}: {line.strip()}") + + if offenders: + self.fail( + f"{len(offenders)} sudo call(s) preserve the whole environment. " + "sudo-rs (default sudo on ubuntu-26.04 runners) ignores -E and " + "drops every caller variable; name them instead with " + '--preserve-env="$(compgen -e | paste -sd, -)".\n' + + "\n".join(offenders) + ) + + +if __name__ == "__main__": + unittest.main() From c4f340d7b4e80959b75a99778fc9487e252fdbb9 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 19 Oct 2026 12:02:23 +0200 Subject: [PATCH 2/2] fix(sys-svc-container): install iptables-nft with docker on RedHat On Fedora 44, dnf satisfies docker-ce's `(iptables-nft or iptables)` requirement with iptables-legacy. The legacy backend needs the ip_tables module, which ubuntu-26.04 runners no longer have loaded, and the compose container cannot load it because it mounts no /lib/modules. The MSS clamp task then failed with `modprobe: FATAL: Module ip_tables not found` and `can't initialize iptables table 'mangle'` (Nextcloud#10, Gitea#0, Jellyfin#0 on fedora). CentOS 10 already resolves to iptables-nft from the same plan and deploys green on the same image. Naming iptables-nft in the docker transaction makes Fedora use the nf_tables backend as well. Co-Authored-By: Claude Opus 5.5 (1M context) --- roles/sys-svc-container/meta/packages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/sys-svc-container/meta/packages.yml b/roles/sys-svc-container/meta/packages.yml index cb905aea76..56315d6b55 100644 --- a/roles/sys-svc-container/meta/packages.yml +++ b/roles/sys-svc-container/meta/packages.yml @@ -20,5 +20,6 @@ docker-cli: - docker-ce - docker-ce-cli - docker-compose-plugin + - iptables-nft repo: managed_externally: sys-svc-container configures the download.docker.com repository per distro before installing