feat: auto-restart stack on boot via systemd user service
- 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
This commit is contained in:
parent
031c3bdd41
commit
88f6e02d4e
2 changed files with 86 additions and 0 deletions
59
infra/boot.sh
Executable file
59
infra/boot.sh
Executable file
|
|
@ -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."
|
||||
|
|
@ -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" <<UNIT
|
||||
[Unit]
|
||||
Description=HostItYourself container stack
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=${SCRIPT_DIR}/boot.sh
|
||||
ExecStop=podman compose --env-file ${REPO_ROOT}/.env -f ${SCRIPT_DIR}/docker-compose.yml down
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
UNIT
|
||||
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable hiy.service
|
||||
loginctl enable-linger "$(id -un)" 2>/dev/null || true
|
||||
echo "[hiy] Boot service installed: systemctl --user status hiy.service"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue