From ad04edec5b9db37a8f92e38487794f84b24e4532 Mon Sep 17 00:00:00 2001 From: "l.kirchner" Date: Fri, 12 Jun 2026 13:25:42 +0200 Subject: [PATCH] =?UTF-8?q?feat(runner):=20Installer=20=E2=80=94=20act=5Fr?= =?UTF-8?q?unner=20instanzweit=20als=20unprivilegierter=20User,=20Docker,?= =?UTF-8?q?=20ohne=20sudoers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install/runner-install.sh | 136 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 install/runner-install.sh diff --git a/install/runner-install.sh b/install/runner-install.sh new file mode 100644 index 0000000..12d9364 --- /dev/null +++ b/install/runner-install.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# Runner installer — runs inside the LXC, called by ct/runner.sh +# +# Allgemeiner, INSTANZWEITER Gitea-Actions-Runner ohne Deploy-Rechte: +# - Node.js (für actions/checkout im Host-Mode) + git + rsync +# - Docker (für Wegwerf-Test-Container in CI, z. B. pgvector) +# - act_runner als unprivilegierter User "runner" (Mitglied der docker-Gruppe, +# KEIN sudo, keine sudoers-Datei — bewusst, vgl. Kopfkommentar in ct/runner.sh) +# - systemd-Unit act-runner.service +# +# Idempotent: erneuter Lauf überspringt vorhandene Registrierung/Pakete. + +set -euo pipefail + +LIB_URL="${LIB_URL:-https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/lib}" +source <(curl -fsSL "$LIB_URL/install.func") + +[[ "$EUID" -eq 0 ]] || { msg_err "Must run as root"; exit 1; } + +CONF="/root/runner.deploy.env" +[[ -f "$CONF" ]] || { msg_err "$CONF not found (host bootstrap incomplete)"; exit 1; } +set -a; . "$CONF"; set +a +: "${GITEA_INSTANCE_URL:?missing GITEA_INSTANCE_URL}" +: "${RUNNER_TOKEN:?missing RUNNER_TOKEN}" +RUNNER_NAME="${RUNNER_NAME:-$(hostname)}" +RUNNER_LABELS="${RUNNER_LABELS:-homelab:host}" +RUNNER_VERSION="${RUNNER_VERSION:-0.2.13}" +NODE_MAJOR="${NODE_MAJOR:-22}" + +APP_USER="runner" +APP_HOME="/opt/runner" +RUNNER_DIR="$APP_HOME/data" + +run_user() { runuser -u "$APP_USER" -- env HOME="$APP_HOME" "$@"; } + +# ── Pakete: git/rsync, Node (checkout-Action), Docker (Test-Container) ──────── +setup_base_apt git rsync ca-certificates curl + +NODE_HAVE="$(command -v node >/dev/null 2>&1 && node -v | sed -E 's/^v([0-9]+).*/\1/' || echo 0)" +if [[ "$NODE_HAVE" != "$NODE_MAJOR" ]]; then + msg_info "Installing Node.js ${NODE_MAJOR}.x (NodeSource)..." + curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - >/dev/null + apt-get install -y -qq nodejs >/dev/null + msg_ok "Node $(node -v) installed" +else + msg_warn "Node $(node -v) already present, skipping" +fi + +if ! command -v docker >/dev/null 2>&1; then + msg_info "Installing Docker (get.docker.com)..." + curl -fsSL https://get.docker.com | sh >/dev/null + msg_ok "Docker $(docker --version | awk '{print $3}' | tr -d ',')" +else + msg_warn "Docker already present, skipping" +fi + +# ── act_runner binary ───────────────────────────────────────────────────────── +if [[ ! -x /usr/local/bin/act_runner ]]; then + ARCH="$(dpkg --print-architecture)" + case "$ARCH" in amd64|arm64) ;; *) msg_err "unsupported arch: $ARCH"; exit 1 ;; esac + msg_info "Downloading act_runner $RUNNER_VERSION ($ARCH)..." + curl -fsSL "https://dl.gitea.com/act_runner/${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-${ARCH}" \ + -o /usr/local/bin/act_runner + chmod +x /usr/local/bin/act_runner + msg_ok "act_runner $(/usr/local/bin/act_runner --version 2>/dev/null | head -n1)" +else + msg_warn "act_runner already present, skipping download" +fi + +# ── User (docker-Gruppe VOR dem Daemon-Start — Lesson aus nexus K-103: +# Gruppenmitgliedschaften werden beim Prozessstart eingefroren) ───────────── +create_system_user "$APP_USER" "$APP_HOME" +usermod -aG docker "$APP_USER" +mkdir -p "$RUNNER_DIR" +chown -R "$APP_USER:$APP_USER" "$APP_HOME" + +# ── Registrierung (idempotent) ──────────────────────────────────────────────── +if [[ ! -f "$RUNNER_DIR/.runner" ]]; then + msg_info "Registering runner '$RUNNER_NAME' [$RUNNER_LABELS] with $GITEA_INSTANCE_URL (instance scope)..." + run_user bash -c "cd '$RUNNER_DIR' && /usr/local/bin/act_runner register \ + --no-interactive \ + --instance '$GITEA_INSTANCE_URL' \ + --token '$RUNNER_TOKEN' \ + --name '$RUNNER_NAME' \ + --labels '$RUNNER_LABELS'" + chown -R "$APP_USER:$APP_USER" "$RUNNER_DIR" + msg_ok "Runner registered" +else + msg_warn "Runner already registered (.runner exists), skipping" +fi + +# ── systemd-Unit (bewusst KEINE sudoers-Datei) ──────────────────────────────── +cat >/etc/systemd/system/act-runner.service <"$CRED_FILE" </dev/null || rm -f "$CONF" +apt_cleanup +msg_ok "runner installation finished"