From 88f6e02d4e32063886ec1902920613e6715a38c2 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 12:22:34 +0000 Subject: [PATCH] feat: auto-restart stack on boot via systemd user service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add infra/boot.sh: lightweight startup (no build) that brings up the Podman stack — used by the systemd unit on every system boot - start.sh now installs/refreshes hiy.service (a systemd --user unit) and enables loginctl linger so it runs without an active login session After the next `infra/start.sh` run the Pi will automatically restart the stack after a reboot or power cut. https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH --- infra/boot.sh | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ infra/start.sh | 27 +++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100755 infra/boot.sh diff --git a/infra/boot.sh b/infra/boot.sh new file mode 100755 index 0000000..350119e --- /dev/null +++ b/infra/boot.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# boot.sh — bring up the HIY stack without rebuilding images. +# Called on system boot by the hiy.service systemd user unit. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# ── Load .env ────────────────────────────────────────────────────────────────── +if [ -f "$REPO_ROOT/.env" ]; then + set -a; source "$REPO_ROOT/.env"; set +a +fi + +# ── Ensure subuid/subgid entries exist ──────────────────────────────────────── +_HIY_USER="$(id -un)" +if ! grep -q "^${_HIY_USER}:" /etc/subuid 2>/dev/null; then + echo "${_HIY_USER}:100000:65536" | sudo tee -a /etc/subuid > /dev/null +fi +if ! grep -q "^${_HIY_USER}:" /etc/subgid 2>/dev/null; then + echo "${_HIY_USER}:100000:65536" | sudo tee -a /etc/subgid > /dev/null +fi + +# ── Allow rootless processes to bind ports 80/443 ───────────────────────────── +# /etc/sysctl.conf should persist this across reboots, but apply it immediately +# in case the kernel hasn't picked it up yet. +if [ "$(sysctl -n net.ipv4.ip_unprivileged_port_start)" -gt 80 ]; then + sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80 +fi + +# ── Ensure XDG_RUNTIME_DIR exists and is writable ───────────────────────────── +_HIY_XDG="/run/user/$(id -u)" +if [ ! -d "$_HIY_XDG" ]; then + sudo mkdir -p "$_HIY_XDG" +fi +if [ ! -w "$_HIY_XDG" ]; then + sudo chown "$(id -u):$(id -g)" "$_HIY_XDG" + sudo chmod 0700 "$_HIY_XDG" +fi +export XDG_RUNTIME_DIR="$_HIY_XDG" + +PODMAN_SOCK="${_HIY_XDG}/podman.sock" +export PODMAN_SOCK +export DOCKER_HOST="unix://${PODMAN_SOCK}" + +# ── Start Podman socket if not already running ───────────────────────────────── +if ! [ -S "$PODMAN_SOCK" ]; then + echo "[hiy] Starting Podman socket…" + podman system service --time=0 "unix://${PODMAN_SOCK}" & + for i in 1 2 3 4 5; do + [ -S "$PODMAN_SOCK" ] && break + sleep 1 + done +fi +[ -S "$PODMAN_SOCK" ] || { echo "ERROR: Podman socket did not appear"; exit 1; } + +# ── Bring up the stack ───────────────────────────────────────────────────────── +podman system migrate +podman compose --env-file "$REPO_ROOT/.env" -f "$SCRIPT_DIR/docker-compose.yml" up -d +echo "[hiy] Stack is up." diff --git a/infra/start.sh b/infra/start.sh index 650d818..933d619 100755 --- a/infra/start.sh +++ b/infra/start.sh @@ -186,3 +186,30 @@ make -C "$SCRIPT_DIR" build podman system migrate podman compose --env-file "$REPO_ROOT/.env" -f "$SCRIPT_DIR/docker-compose.yml" down podman compose --env-file "$REPO_ROOT/.env" -f "$SCRIPT_DIR/docker-compose.yml" up -d + +# ── Install systemd user service for auto-start on boot ─────────────────────── +# Uses a user-level (rootless) service so Podman's UID namespace is preserved. +# loginctl enable-linger lets the service start even without an active login. +SERVICE_DIR="$HOME/.config/systemd/user" +SERVICE_FILE="$SERVICE_DIR/hiy.service" +mkdir -p "$SERVICE_DIR" +cat > "$SERVICE_FILE" </dev/null || true +echo "[hiy] Boot service installed: systemctl --user status hiy.service"