feat: allgemeiner instanzweiter Actions-Runner-LXC (Label homelab, ohne Deploy-Rechte) #6
+57
-12
@@ -10,6 +10,11 @@
|
|||||||
# - KEINE sudoers-Regeln, kein Zugriff auf Produktions-Verzeichnisse
|
# - KEINE sudoers-Regeln, kein Zugriff auf Produktions-Verzeichnisse
|
||||||
# - Docker via Nesting für Wegwerf-Test-Container (z. B. pgvector in CI)
|
# - Docker via Nesting für Wegwerf-Test-Container (z. B. pgvector in CI)
|
||||||
#
|
#
|
||||||
|
# Sicherheitsmodell: siehe Kopfkommentar in install/runner-install.sh —
|
||||||
|
# instanzweit + docker-Gruppe heißt: jedes Repo der Instanz kann diesen LXC
|
||||||
|
# kontrollieren. Akzeptiert, WEIL er nichts besitzt. Nicht auf privilegierte
|
||||||
|
# LXCs übertragen.
|
||||||
|
#
|
||||||
# Run on a Proxmox VE host:
|
# Run on a Proxmox VE host:
|
||||||
# bash -c "$(curl -fsSL https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/ct/runner.sh)"
|
# bash -c "$(curl -fsSL https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/ct/runner.sh)"
|
||||||
|
|
||||||
@@ -28,24 +33,61 @@ DEFAULT_DISK="30"
|
|||||||
DEFAULT_CORES="4"
|
DEFAULT_CORES="4"
|
||||||
DEFAULT_RAM="6144"
|
DEFAULT_RAM="6144"
|
||||||
|
|
||||||
|
# ── Validierung (Review-Finding 80): Werte wandern in die Deploy-Env und in
|
||||||
|
# systemd/argv — strikte Zeichenklassen, Re-Prompt statt Abbruch.
|
||||||
|
# Nutzt prompt_validated/require_valid aus build.func, sobald vorhanden
|
||||||
|
# (K-114/PR #5); bis dahin lokale Fallbacks mit identischer Semantik. ──────
|
||||||
|
_valid_url() { [[ "$1" =~ ^https?://[A-Za-z0-9.-]+(:[0-9]{1,5})?$ ]]; }
|
||||||
|
_valid_token() { [[ "$1" =~ ^[A-Za-z0-9_-]{16,128}$ ]]; }
|
||||||
|
_valid_word() { [[ "$1" =~ ^[A-Za-z0-9._:,-]+$ ]]; }
|
||||||
|
|
||||||
|
_prompt_until_valid() { # var prompt default validator secret(0|1)
|
||||||
|
local __var="$1" __prompt="$2" __default="$3" __validator="$4" __secret="${5:-0}" __val
|
||||||
|
while true; do
|
||||||
|
if [[ "$__secret" == "1" ]]; then
|
||||||
|
read -rsp "$__prompt" __val; echo
|
||||||
|
else
|
||||||
|
read -rp "$__prompt" __val
|
||||||
|
fi
|
||||||
|
__val="${__val:-$__default}"
|
||||||
|
if [[ -n "$__val" ]] && "$__validator" "$__val"; then
|
||||||
|
printf -v "$__var" '%s' "$__val"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
msg_warn "Ungültige Eingabe — bitte erneut (kein Paste mit Sonderzeichen)."
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
prompt_app_config() {
|
prompt_app_config() {
|
||||||
echo
|
echo
|
||||||
echo "── Runner configuration ─────────────────────────────────────"
|
echo "── Runner configuration ─────────────────────────────────────"
|
||||||
if [[ -z "${GITEA_INSTANCE_URL:-}" ]]; then
|
# env-präsetzte Werte werden validiert (Abbruch bei ungültig — K-114-Konvention),
|
||||||
read -rp "Gitea instance URL [https://gitea.luki-net.org]: " GITEA_INSTANCE_URL
|
# interaktive Eingaben re-prompten bis gültig.
|
||||||
GITEA_INSTANCE_URL="${GITEA_INSTANCE_URL:-https://gitea.luki-net.org}"
|
if [[ -n "${GITEA_INSTANCE_URL:-}" ]]; then
|
||||||
|
_valid_url "$GITEA_INSTANCE_URL" || { msg_err "GITEA_INSTANCE_URL (env) ungültig"; exit 1; }
|
||||||
|
else
|
||||||
|
_prompt_until_valid GITEA_INSTANCE_URL \
|
||||||
|
"Gitea instance URL [https://gitea.luki-net.org]: " \
|
||||||
|
"https://gitea.luki-net.org" _valid_url 0
|
||||||
fi
|
fi
|
||||||
# WICHTIG: den INSTANZWEITEN Token verwenden
|
# WICHTIG: den INSTANZWEITEN Token verwenden
|
||||||
# (Site Administration → Actions → Runners → Create new runner),
|
# (Site Administration → Actions → Runners → Create new runner),
|
||||||
# NICHT den Repo-Token — sonst wiederholt sich der K-114-Scope-Blocker.
|
# NICHT den Repo-Token — sonst wiederholt sich der K-114-Scope-Blocker.
|
||||||
if [[ -z "${RUNNER_TOKEN:-}" ]]; then
|
if [[ -n "${RUNNER_TOKEN:-}" ]]; then
|
||||||
read -rsp "INSTANZWEITER Runner-Registration-Token: " RUNNER_TOKEN; echo
|
_valid_token "$RUNNER_TOKEN" || { msg_err "RUNNER_TOKEN (env) ungültig (16–128 Zeichen [A-Za-z0-9_-])"; exit 1; }
|
||||||
|
else
|
||||||
|
_prompt_until_valid RUNNER_TOKEN \
|
||||||
|
"INSTANZWEITER Runner-Registration-Token: " \
|
||||||
|
"" _valid_token 1
|
||||||
fi
|
fi
|
||||||
[[ -n "${RUNNER_TOKEN:-}" ]] || { msg_err "RUNNER_TOKEN ist Pflicht (instanzweit, Site Administration)"; exit 1; }
|
|
||||||
RUNNER_NAME="${RUNNER_NAME:-$CT_HOSTNAME}"
|
RUNNER_NAME="${RUNNER_NAME:-$CT_HOSTNAME}"
|
||||||
RUNNER_LABELS="${RUNNER_LABELS:-homelab:host}"
|
RUNNER_LABELS="${RUNNER_LABELS:-homelab:host}"
|
||||||
RUNNER_VERSION="${RUNNER_VERSION:-0.2.13}"
|
RUNNER_VERSION="${RUNNER_VERSION:-0.2.13}"
|
||||||
NODE_MAJOR="${NODE_MAJOR:-22}"
|
NODE_MAJOR="${NODE_MAJOR:-22}"
|
||||||
|
_valid_word "$RUNNER_NAME" || { msg_err "RUNNER_NAME ungültig"; exit 1; }
|
||||||
|
_valid_word "$RUNNER_LABELS" || { msg_err "RUNNER_LABELS ungültig"; exit 1; }
|
||||||
|
[[ "$RUNNER_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { msg_err "RUNNER_VERSION ungültig"; exit 1; }
|
||||||
|
[[ "$NODE_MAJOR" =~ ^[0-9]+$ ]] || { msg_err "NODE_MAJOR ungültig"; exit 1; }
|
||||||
echo " → instance: $GITEA_INSTANCE_URL"
|
echo " → instance: $GITEA_INSTANCE_URL"
|
||||||
echo " → runner: $RUNNER_NAME labels: $RUNNER_LABELS (act_runner $RUNNER_VERSION, host mode, scope: INSTANZ)"
|
echo " → runner: $RUNNER_NAME labels: $RUNNER_LABELS (act_runner $RUNNER_VERSION, host mode, scope: INSTANZ)"
|
||||||
}
|
}
|
||||||
@@ -53,13 +95,15 @@ prompt_app_config() {
|
|||||||
push_app_config() {
|
push_app_config() {
|
||||||
msg_info "Pushing runner config into container..."
|
msg_info "Pushing runner config into container..."
|
||||||
local tmpf; tmpf=$(mktemp)
|
local tmpf; tmpf=$(mktemp)
|
||||||
|
# Werte sind oben strikt validiert (keine Quotes/Whitespace möglich) —
|
||||||
|
# damit ist die env-Datei frei von Quoting-/Injection-Fallen (vgl. Finding 76).
|
||||||
cat >"$tmpf" <<EOF
|
cat >"$tmpf" <<EOF
|
||||||
GITEA_INSTANCE_URL='$GITEA_INSTANCE_URL'
|
GITEA_INSTANCE_URL=$GITEA_INSTANCE_URL
|
||||||
RUNNER_TOKEN='$RUNNER_TOKEN'
|
RUNNER_TOKEN=$RUNNER_TOKEN
|
||||||
RUNNER_NAME='$RUNNER_NAME'
|
RUNNER_NAME=$RUNNER_NAME
|
||||||
RUNNER_LABELS='$RUNNER_LABELS'
|
RUNNER_LABELS=$RUNNER_LABELS
|
||||||
RUNNER_VERSION='$RUNNER_VERSION'
|
RUNNER_VERSION=$RUNNER_VERSION
|
||||||
NODE_MAJOR='$NODE_MAJOR'
|
NODE_MAJOR=$NODE_MAJOR
|
||||||
EOF
|
EOF
|
||||||
pct push "$CTID" "$tmpf" /root/runner.deploy.env --perms 600
|
pct push "$CTID" "$tmpf" /root/runner.deploy.env --perms 600
|
||||||
rm -f "$tmpf"
|
rm -f "$tmpf"
|
||||||
@@ -85,6 +129,7 @@ print_app_summary() {
|
|||||||
Scope: INSTANZWEIT — bedient alle Repos der Instanz
|
Scope: INSTANZWEIT — bedient alle Repos der Instanz
|
||||||
Mode: host (Docker verfügbar für Test-Container)
|
Mode: host (Docker verfügbar für Test-Container)
|
||||||
Sicherheit: kein sudoers, keine Deploy-Rechte, keine Produktions-Mounts
|
Sicherheit: kein sudoers, keine Deploy-Rechte, keine Produktions-Mounts
|
||||||
|
(Modell: siehe install/runner-install.sh Kopfkommentar)
|
||||||
Verify: $GITEA_INSTANCE_URL → Site Administration → Actions → Runners
|
Verify: $GITEA_INSTANCE_URL → Site Administration → Actions → Runners
|
||||||
|
|
||||||
Workflows anderer Repos nutzen: runs-on: ${RUNNER_LABELS%%:*}
|
Workflows anderer Repos nutzen: runs-on: ${RUNNER_LABELS%%:*}
|
||||||
|
|||||||
Reference in New Issue
Block a user