- Harness: bootstrap find/awk in distro-compatibility.py (AL2023, Tumbleweed, SLES BCI minimal images lack them; the source-level suites legitimately use both) - Python gate 3.11-3.14: Arch/Manjaro rolling ship only python 3.14 with no versioned fallback packages (same trap as Debian 13/#99); align scripts/update.sh, which had drifted to a 3.11-3.12 gate - Gentoo: add emerge as a supported installer package-manager path (install.sh, scripts/lib/pkg.sh, distro.py family, deps manifest); provision via slotted dev-lang/python:3.13 -> 3.12 - Tests: move out-of-range stubs above the new ceiling, shadow all locate_python candidate names (real python3.14/3.13 in Manjaro/ Gentoo images were winning over fixtures), cover the 7th manager - Catalog: Gentoo is no longer a documented expected failure Verified: test_lib 32/32, test_install 124/124, test_update 76/76, pytest test_serverkit_installer 46/46, and all 6 previously failing images now pass both quick and provision container probes (12/12).
serverkit_installer
Phase 5 foundation from the Installer/Updater/Uninstaller Hardening Plan (§8). A stdlib-only, import-safe, unit-tested Python port of the bash installer's detection and orchestration logic.
Additive, not a replacement.
install.shis still the canonical installer. This package exists so the stabilized multi-distro logic has a single, unit-testable home that the backend can eventually share. It is not wired intoinstall.shyet — per the plan's migration path, the bash scripts stay in charge until this is fully validated on real boxes.
Why it doesn't import app
The real bootstrap runs before the backend venv exists, so importing
app.utils.system (which pulls in Flask/SQLAlchemy) would fail. This package is
deliberately stdlib-only (plus PyYAML for the manifest) and mirrors
app/utils/system.py's run_privileged/sudo contract in _proc.py.
Modules
| Module | Mirrors | Responsibility |
|---|---|---|
distro.py |
install.sh:os_family_from + scripts/lib/env.sh |
OS family + container/WSL/systemd detection |
deps.py |
scripts/deps/manifest.yaml |
Load the manifest, resolve packages per family |
firewall.py |
scripts/lib/firewall.sh |
Detect backend, build open/close command lists |
service.py |
scripts/lib/init.sh |
Detect init system, build start/stop/enable commands |
main.py |
— | Compose a read-only install plan + CLI |
_proc.py |
app/utils/system.py |
sudo-aware subprocess helpers |
The command builders are pure functions returning argv lists, so they're tested without touching a real firewall/init system.
Usage
# Read-only: print what an install would do on the detected distro
python -m serverkit_installer plan
# Just the distro detection
python -m serverkit_installer detect --os-release /etc/os-release
# Force backends for a preview on any host
python -m serverkit_installer plan --firewall firewalld --init systemd
Tests
backend/tests/test_serverkit_installer.py (46 cases) — family mapping kept in
lockstep with os_family_from, manifest resolution for every family, the
firewall/service command builders, environment predicates, and the composed
plan. Pure logic, no host mutation:
cd backend && pytest tests/test_serverkit_installer.py