diff --git a/install/nexus-install.sh b/install/nexus-install.sh new file mode 100644 index 0000000..a71518a --- /dev/null +++ b/install/nexus-install.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env bash +# nexus installer — runs inside the LXC, called by ct/nexus.sh +# +# Sets up the deploy target for nexus (Family Knowledge Hub): +# - Node.js (NodeSource) + git + rsync + sudo (Node also needed by checkout action in host mode) +# - act_runner in HOST mode (no Docker), registered to the Gitea instance, +# running as the unprivileged `nexus` user and polling Gitea outbound +# - a SKELETON systemd service (nexus.service) — the stack-introducing SDD +# card in nexus-hub provides /opt/nexus/current/start.sh and may extend +# the RUNTIME section below (DB clients, Python/uv, etc.) +# - a narrow sudoers rule so the runner may only restart that one service +# +# The actual build/test/deploy logic lives in the nexus-hub repo workflows +# (.gitea/workflows/ci.yml + deploy.yml) — deploy-as-code. + +set -euo pipefail + +APP="nexus" +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; } + +# ── load deploy config pushed in by the host script ────────────────────────── +CONF="/root/nexus.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}" +APP_PORT="${APP_PORT:-8080}" +NODE_MAJOR="${NODE_MAJOR:-22}" +RUNNER_VERSION="${RUNNER_VERSION:-0.2.13}" +RUNNER_LABELS="${RUNNER_LABELS:-nexus:host}" +RUNNER_NAME="${RUNNER_NAME:-$(hostname)}" + +APP_USER="nexus" +APP_HOME="/opt/nexus" +RUNNER_DIR="$APP_HOME/runner" +CURRENT_DIR="$APP_HOME/current" +DATA_DIR="$APP_HOME/data" +CONF_DIR="/etc/nexus" +ENV_FILE="$CONF_DIR/env" + +run_user() { runuser -u "$APP_USER" -- env HOME="$APP_HOME" "$@"; } + +# ── packages: git + rsync + sudo ; Node.js via NodeSource ───────────────────── +setup_base_apt git rsync sudo + +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 + +# ── RUNTIME (extended by the stack-introducing SDD card in nexus-hub) ───────── +# The nexus tech stack is not yet decided (nexus-hub Project Brief, open point 2). +# When the stack card lands, it adds the runtime here (e.g. Python/uv, DB client +# libs) AND documents the change in nexus-hub docs/agent-rules.md → Projekt-Kommandos. +msg_warn "RUNTIME section is a placeholder until the nexus stack decision (see nexus-hub)" + +# ── 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 + dirs ─────────────────────────────────────────────────────────────── +create_system_user "$APP_USER" "$APP_HOME" +mkdir -p "$RUNNER_DIR" "$CURRENT_DIR" "$DATA_DIR" "$CONF_DIR" +chown -R "$APP_USER:$APP_USER" "$APP_HOME" + +# ── env file (runtime config; populated further by the stack card) ──────────── +cat >"$ENV_FILE" </etc/sudoers.d/nexus-deploy </dev/null + +# ── systemd units ───────────────────────────────────────────────────────────── +# nexus.service: SKELETON. The deploy workflow populates /opt/nexus/current and +# the stack card provides current/start.sh. Enabled (starts on boot) but not +# started now — first successful deploy starts it via the sudoers-allowed restart. +cat >/etc/systemd/system/nexus.service </etc/systemd/system/nexus-runner.service </dev/null 2>&1 +systemctl enable --now nexus-runner.service +msg_ok "systemd units installed (runner started; nexus.service enabled, starts on first deploy)" + +# ── notes / summary file ────────────────────────────────────────────────────── +CRED_FILE="/root/nexus.credentials" +cat >"$CRED_FILE" < Settings -> Actions) + - The LXC needs outbound HTTPS to $GITEA_INSTANCE_URL and to github.com + (the latter only to fetch actions/checkout, unless you self-host actions) +EOF +chmod 600 "$CRED_FILE" + +# registration token already consumed → drop the bootstrap env file +shred -u "$CONF" 2>/dev/null || rm -f "$CONF" + +apt_cleanup +msg_ok "$APP installation finished"