From 973e92206a7c9d2bb763a4a25f306e6f860591cc Mon Sep 17 00:00:00 2001 From: continuist Date: Fri, 5 Sep 2025 21:56:45 -0400 Subject: [PATCH] Fixes to how to start podman locally and in scripts --- CI_CD_PIPELINE_SETUP_GUIDE.md | 92 ++++++++++++++++++++++++++++------- secure_pip_setup.sh | 2 +- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/CI_CD_PIPELINE_SETUP_GUIDE.md b/CI_CD_PIPELINE_SETUP_GUIDE.md index b42be13..10f2c9d 100644 --- a/CI_CD_PIPELINE_SETUP_GUIDE.md +++ b/CI_CD_PIPELINE_SETUP_GUIDE.md @@ -944,41 +944,99 @@ sudo journalctl -u forgejo-runner.service -f --no-pager **CRITICAL**: Before proceeding with PiP containers, you must start the Podman host socket service that provides the UNIX socket for container communication. -#### 6.1 Start Podman Host Socket Service +#### 6.1 Install and Start Podman Host Socket Service (Security-Hardened) ```bash -# Switch to CI_SERVICE_USER (who will run the socket service) -sudo su - CI_SERVICE_USER +# Switch to CI_DEPLOY_USER (who has sudo privileges for system configuration) +sudo su - CI_DEPLOY_USER -# Enable lingering for CI_SERVICE_USER to allow systemd user services to start at boot -sudo loginctl enable-linger CI_SERVICE_USER +# Configuration +SVC_USER="CI_SERVICE_USER" +PODMAN="/usr/bin/podman" +UNIT_DST="/etc/systemd/user/podman-host-socket.service" -# Start the podman-host-socket service -systemctl --user enable --now podman-host-socket.service +# 0) Preconditions +ps -p 1 -o comm= | grep -qx systemd || { echo "PID1 is not systemd"; exit 1; } +command -v "$PODMAN" >/dev/null || { echo "podman not found at $PODMAN"; exit 1; } -# Verify the service is running -systemctl --user status podman-host-socket.service +# 1) Install the hardened unit (global user unit, root-owned, read-only) +sudo install -o root -g root -m 0644 /dev/stdin "$UNIT_DST" <<'EOF' +[Unit] +Description=Rootless Podman REST (UNIX socket only) +After=default.target -# Check that the UNIX socket was created -ls -la /run/user/$(id -u)/podman-host/podman.sock -# Should show: srw-rw---- 1 CI_SERVICE_USER CI_SERVICE_USER 0 ... /run/user/999/podman-host/podman.sock +[Service] +Type=simple +UMask=007 +NoNewPrivileges=yes +# %t expands to /run/user/$UID for *user* services +ExecStartPre=/usr/bin/mkdir -p %t/podman-host +ExecStartPre=/usr/bin/chmod 770 %t/podman-host +ExecStart=/usr/bin/podman --log-level=info system service --time=0 unix://%t/podman-host/podman.sock +Restart=always +RestartSec=2 -# Test socket connectivity -podman --url unix:///run/user/$(id -u)/podman-host/podman.sock version +[Install] +WantedBy=default.target +EOF + +sudo stat -c '%U:%G %a %n' "$UNIT_DST" | grep -q 'root:root 644' || { echo "Unit perms wrong"; exit 1; } + +# 2) Ensure rootless prerequisites (Ubuntu/Debian) +if command -v apt >/dev/null 2>&1; then + sudo apt-get update -y + sudo apt-get install -y dbus-user-session uidmap slirp4netns fuse-overlayfs +fi + +# Ensure subuid/subgid (safe if already present) +if ! grep -q "^${SVC_USER}:" /etc/subuid; then echo "${SVC_USER}:100000:65536" | sudo tee -a /etc/subuid >/dev/null; fi +if ! grep -q "^${SVC_USER}:" /etc/subgid; then echo "${SVC_USER}:100000:65536" | sudo tee -a /etc/subgid >/dev/null; fi + +# 3) Enable linger so the user's manager runs without login +sudo loginctl enable-linger "$SVC_USER" +loginctl show-user "$SVC_USER" | grep -q '^Linger=yes' || { echo "Linger not enabled"; exit 1; } + +# 4) Start the user's systemd instance and point to its bus +uid=$(id -u "$SVC_USER") +sudo systemctl start "user@${uid}.service" + +export XDG_RUNTIME_DIR=/run/user/$uid +export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus + +# 5) Enable+start the unit in the *user* manager (acting as the user) +sudo -u "$SVC_USER" XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \ + systemctl --user daemon-reload + +sudo -u "$SVC_USER" XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \ + systemctl --user enable --now podman-host-socket.service + +# 6) Verify directory, socket, and connectivity (as the user) +sudo -u "$SVC_USER" bash -lc ' + R="/run/user/$(id -u)" + ls -ld "$R" "$R/podman-host" + ls -l "$R/podman-host/podman.sock" + podman --url unix://$R/podman-host/podman.sock version + podman --url unix://$R/podman-host/podman.sock info +' + +# 7) Belt & suspenders: ensure no Docker/Podman TCP daemons +ss -ltnp | grep -E '(2375|2376)' && { echo "ERROR: TCP daemon detected"; exit 1; } || echo "No TCP sockets (good)" ``` **What this does**: -- **Enables lingering**: Allows systemd user services to start automatically +- **FHS compliance**: Moves service file to `/etc/systemd/user/` (standard system location) +- **Proper ownership**: Service file owned by root with appropriate permissions +- **Enables lingering**: Allows CI_SERVICE_USER's systemd services to start at boot - **Starts socket service**: Creates the UNIX socket that PiP containers will use - **Verifies operation**: Ensures the socket is properly created and accessible **If you see cgroup warnings**: ```bash # If you see warnings about systemd user session, enable lingering properly -sudo loginctl enable-linger $(id -u) +sudo loginctl enable-linger CI_SERVICE_USER # Verify lingering is enabled -loginctl show-user $(whoami) | grep Linger +sudo loginctl show-user CI_SERVICE_USER | grep Linger # Should show: Linger=yes ``` diff --git a/secure_pip_setup.sh b/secure_pip_setup.sh index d6137f6..892201d 100755 --- a/secure_pip_setup.sh +++ b/secure_pip_setup.sh @@ -32,7 +32,7 @@ chmod 660 "${SOCKET_PATH}" >/dev/null 2>&1 || true # Create ephemeral PiP client (no network, least privilege) podman run -d \ --name "${PIP_CONTAINER_NAME}" \ - --user ${PIP_UID}:${PIP_GID} \ + --user 0:0 \ -e HOME=/tmp \ --security-opt=no-new-privileges \ --cap-drop=ALL \