diff --git a/infra/start.sh b/infra/start.sh index 6c62396..446cd26 100755 --- a/infra/start.sh +++ b/infra/start.sh @@ -59,6 +59,51 @@ EOF echo "[hiy] Generated proxy/caddy.json for ${DOMAIN_SUFFIX}" +# ── Ensure cgroup swap accounting is enabled (required by runc/Podman) ──────── +# runc always writes memory.swap.max when the memory cgroup controller is +# present. On Raspberry Pi OS swap accounting is disabled by default, so that +# file simply does not exist and every container start fails with: +# "openat2 …/memory.swap.max: no such file or directory" +# Fix: add cgroup_memory=1 cgroup_enable=memory swapaccount=1 to the kernel +# boot cmdline and ask the user to reboot once. +_SWAP_OK=false +if [ -f /sys/fs/cgroup/memory.swap.max ] 2>/dev/null; then + _SWAP_OK=true +elif [ -d /sys/fs/cgroup/user.slice ] && \ + ls /sys/fs/cgroup/user.slice/*/memory.swap.max 2>/dev/null | head -1 | grep -q .; then + _SWAP_OK=true +fi +if [ "$_SWAP_OK" = "false" ]; then + echo "[hiy] WARNING: cgroup swap accounting is not enabled." + # Detect the Pi boot cmdline file (Bookworm: /boot/firmware/cmdline.txt, + # older releases: /boot/cmdline.txt). + _CMDLINE="" + for _f in /boot/firmware/cmdline.txt /boot/cmdline.txt; do + [ -f "$_f" ] && { _CMDLINE="$_f"; break; } + done + if [ -n "$_CMDLINE" ]; then + _CURRENT=$(cat "$_CMDLINE") + _CHANGED=false + if ! echo "$_CURRENT" | grep -q "swapaccount=1"; then + _CURRENT="$_CURRENT cgroup_enable=memory cgroup_memory=1 swapaccount=1" + _CHANGED=true + fi + if [ "$_CHANGED" = "true" ]; then + echo "[hiy] Patching $_CMDLINE to enable swap accounting…" + echo "$_CURRENT" | sudo tee "$_CMDLINE" > /dev/null + echo "[hiy] *** REBOOT REQUIRED ***" + echo "[hiy] Run: sudo reboot" + echo "[hiy] Then re-run ./infra/start.sh" + exit 0 + fi + else + echo "[hiy] Could not find /boot/cmdline.txt — add these to your kernel cmdline manually:" + echo "[hiy] cgroup_enable=memory cgroup_memory=1 swapaccount=1" + echo "[hiy] Then reboot and re-run this script." + exit 1 + fi +fi + # ── Ensure newuidmap/newgidmap setuid binaries are present ──────────────────── # These binaries (from the 'uidmap' package) allow rootless Podman to map a # full range of UIDs/GIDs in user namespaces. Without them Podman can only