Files
proxmox-scripts/ct/nexus.sh

122 lines
5.2 KiB
Bash

#!/usr/bin/env bash
# nexus — Family Knowledge Hub deployed via a self-hosted Gitea Actions runner
#
# Creates an unprivileged Debian 12 LXC that:
# - installs Node.js + a Gitea act_runner in HOST mode (no Docker, no inbound port)
# - prepares /opt/nexus/current as the live copy and a (placeholder) nexus.service
# - lets the repo's .gitea/workflows/ci.yml and deploy.yml build, test & deploy
# on every push (deploy-as-code; the runner polls Gitea outbound)
#
# NOTE: The nexus tech stack is not yet decided (nexus-hub Project Brief, open
# point 2). This template provisions the stable parts: runner, user, dirs,
# sudoers, service skeleton. The stack-introducing SDD card extends the
# RUNTIME section of install/nexus-install.sh and replaces the service unit.
#
# Run on a Proxmox VE host:
# bash -c "$(curl -fsSL https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/ct/nexus.sh)"
set -euo pipefail
APP="nexus"
APP_DESCRIPTION="nexus (Family Knowledge Hub) deployed via a self-hosted Gitea Actions runner (deploy-as-code)"
APP_PORT="${APP_PORT:-8080}"
LIB_URL="${LIB_URL:-https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/lib}"
INSTALL_SCRIPT_URL="${INSTALL_SCRIPT_URL:-https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/install/nexus-install.sh}"
# LXC defaults (CI builds + future API/worker need headroom; DBs live elsewhere)
DEFAULT_HOSTNAME="nexus"
DEFAULT_DISK="40"
DEFAULT_CORES="4"
DEFAULT_RAM="8192"
# App / runner defaults (all overridable via env)
DEFAULT_GITEA_INSTANCE_URL="https://gitea.luki-net.org"
DEFAULT_REPO_URL="https://gitea.luki-net.org/l.kirchner/nexus-hub.git"
DEFAULT_NODE_MAJOR="22"
DEFAULT_RUNNER_VERSION="0.2.13"
DEFAULT_RUNNER_LABELS="nexus:host"
source <(curl -fsSL "$LIB_URL/build.func")
# ── app-specific prompts (host TTY; each skipped if the var is preset) ───────
prompt_app_config() {
echo
echo "── App / runner configuration ───────────────────────────────"
if [[ -z "${GITEA_INSTANCE_URL:-}" ]]; then
read -rp "Gitea instance URL [$DEFAULT_GITEA_INSTANCE_URL]: " GITEA_INSTANCE_URL
GITEA_INSTANCE_URL="${GITEA_INSTANCE_URL:-$DEFAULT_GITEA_INSTANCE_URL}"
fi
# Repo → Settings → Actions → Runners → "Create new runner" gives this token.
if [[ -z "${RUNNER_TOKEN:-}" ]]; then
read -rsp "Gitea runner registration token: " RUNNER_TOKEN; echo
fi
[[ -n "${RUNNER_TOKEN:-}" ]] || { msg_err "RUNNER_TOKEN is required (Repo → Settings → Actions → Runners)"; exit 1; }
if [[ -z "${REPO_URL:-}" ]]; then
read -rp "nexus repo URL (informational) [$DEFAULT_REPO_URL]: " REPO_URL
REPO_URL="${REPO_URL:-$DEFAULT_REPO_URL}"
fi
NODE_MAJOR="${NODE_MAJOR:-$DEFAULT_NODE_MAJOR}"
RUNNER_VERSION="${RUNNER_VERSION:-$DEFAULT_RUNNER_VERSION}"
RUNNER_LABELS="${RUNNER_LABELS:-$DEFAULT_RUNNER_LABELS}"
RUNNER_NAME="${RUNNER_NAME:-$CT_HOSTNAME}"
echo " → instance: $GITEA_INSTANCE_URL"
echo " → runner: $RUNNER_NAME labels: $RUNNER_LABELS (act_runner $RUNNER_VERSION, host mode)"
echo " → node: $NODE_MAJOR app port: $APP_PORT"
}
# ── push gathered config into the container for the installer to consume ─────
push_app_config() {
msg_info "Pushing deploy config into container..."
local tmpf; tmpf=$(mktemp)
cat >"$tmpf" <<EOF
GITEA_INSTANCE_URL='$GITEA_INSTANCE_URL'
RUNNER_TOKEN='$RUNNER_TOKEN'
RUNNER_NAME='$RUNNER_NAME'
RUNNER_LABELS='$RUNNER_LABELS'
RUNNER_VERSION='$RUNNER_VERSION'
REPO_URL='$REPO_URL'
APP_PORT='$APP_PORT'
NODE_MAJOR='$NODE_MAJOR'
EOF
pct push "$CTID" "$tmpf" /root/nexus.deploy.env --perms 600
rm -f "$tmpf"
}
# ── trailing summary ──────────────────────────────────────────────────────────
print_app_summary() {
local runner_state
runner_state=$(pct exec "$CTID" -- systemctl is-active nexus-runner.service 2>/dev/null | tr -d '\r\n')
cat <<EOF
nexus API: http://$IP_CT:$APP_PORT (live after the first deploy;
service unit is a skeleton until the stack-introducing card lands)
→ point your existing reverse proxy at this address when ready
Gitea Actions runner: $RUNNER_NAME [$RUNNER_LABELS] — $runner_state
Instance: $GITEA_INSTANCE_URL
Mode: host (no Docker, outbound poll — no inbound port)
Verify: $GITEA_INSTANCE_URL → repo/Settings → Actions → Runners
Deploy-as-code — already in the nexus-hub repo:
.gitea/workflows/ci.yml (runs-on: ${RUNNER_LABELS%%:*})
.gitea/workflows/deploy.yml (runs-on: ${RUNNER_LABELS%%:*}, manual until stack lands)
Logs: pct exec $CTID -- journalctl -u nexus -u nexus-runner -f
Notes file: /root/nexus.credentials (inside the LXC)
EOF
}
# ── orchestrate (custom: inject app config + standard bootstrap) ─────────────
trap _on_error ERR
preflight_pve
show_header "$APP" "$APP_DESCRIPTION"
prompt_lxc_config
prompt_app_config
resolve_debian_template
create_lxc
push_app_config
bootstrap_install_script "$INSTALL_SCRIPT_URL"
print_summary