feat(nexus): runtime provisioning for the decided stack (nexus-hub K-101)
- new install/nexus-runtime.sh (idempotent, re-runnable on an existing LXC): uv for the nexus user (manages Python 3.12), tesseract deu+eng, nexus-worker.service unit (ConditionPathExists guards the skeleton phase), sudoers extended to cover the worker service - nexus-install.sh: RUNTIME section now invokes nexus-runtime.sh at the end of the install (after base sudoers/units, which it extends)
This commit is contained in:
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
# nexus runtime provisioning — idempotent, runs inside the nexus LXC as root.
|
||||
#
|
||||
# Added by nexus-hub card K-101 (stack scaffold). Installs everything the
|
||||
# decided stack (nexus-hub ADR-0002) needs at runtime ON TOP of the base
|
||||
# nexus-install.sh provisioning:
|
||||
# - uv for the `nexus` user (manages Python 3.12 per pyproject.toml)
|
||||
# - tesseract OCR with deu+eng language packs (ingest cards K-107+)
|
||||
# - nexus-worker.service systemd unit (analysis worker, queue with K-105)
|
||||
# - sudoers extension so the Actions runner may also restart the worker
|
||||
#
|
||||
# Called by install/nexus-install.sh (RUNTIME section) during fresh installs.
|
||||
# To retrofit an EXISTING LXC (documented K-101 follow-up step), run inside it:
|
||||
#
|
||||
# curl -fsSL https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/install/nexus-runtime.sh | bash
|
||||
#
|
||||
# Safe to re-run at any time.
|
||||
|
||||
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; }
|
||||
|
||||
APP_USER="nexus"
|
||||
APP_HOME="/opt/nexus"
|
||||
CURRENT_DIR="$APP_HOME/current"
|
||||
|
||||
run_user() { runuser -u "$APP_USER" -- env HOME="$APP_HOME" PATH="$APP_HOME/.local/bin:/usr/local/bin:/usr/bin:/bin" "$@"; }
|
||||
|
||||
id "$APP_USER" >/dev/null 2>&1 || { msg_err "user $APP_USER missing — run nexus-install.sh first"; exit 1; }
|
||||
|
||||
# ── OCR stack (ING-3: tesseract deu+eng) ──────────────────────────────────────
|
||||
msg_info "Installing tesseract (deu+eng)..."
|
||||
apt-get install -y -qq tesseract-ocr tesseract-ocr-deu tesseract-ocr-eng >/dev/null
|
||||
msg_ok "tesseract $(tesseract --version 2>/dev/null | head -n1 | awk '{print $2}')"
|
||||
|
||||
# ── uv for the nexus user (provides Python 3.12 via pyproject/uv.lock) ────────
|
||||
if [[ ! -x "$APP_HOME/.local/bin/uv" ]]; then
|
||||
msg_info "Installing uv for $APP_USER..."
|
||||
run_user bash -c "curl -LsSf https://astral.sh/uv/install.sh | sh" >/dev/null
|
||||
msg_ok "uv $(run_user "$APP_HOME/.local/bin/uv" --version | awk '{print $2}') installed"
|
||||
else
|
||||
msg_warn "uv already present ($(run_user "$APP_HOME/.local/bin/uv" --version | awk '{print $2}')), skipping"
|
||||
fi
|
||||
run_user "$APP_HOME/.local/bin/uv" python install 3.12 >/dev/null 2>&1 || true
|
||||
msg_ok "Python 3.12 toolchain available via uv"
|
||||
|
||||
# ── nexus-worker.service ──────────────────────────────────────────────────────
|
||||
cat >/etc/systemd/system/nexus-worker.service <<EOF
|
||||
[Unit]
|
||||
Description=nexus — analysis worker (job queue arrives with K-105)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# Skeleton-safe: only start once the deploy artifact provides the entrypoint.
|
||||
ConditionPathExists=$CURRENT_DIR/start-worker.sh
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$APP_USER
|
||||
Group=$APP_USER
|
||||
WorkingDirectory=$CURRENT_DIR
|
||||
EnvironmentFile=/etc/nexus/env
|
||||
ExecStart=$CURRENT_DIR/start-worker.sh
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=full
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# ── sudoers: extend the narrow rule to cover the worker service ───────────────
|
||||
cat >/etc/sudoers.d/nexus-deploy <<EOF
|
||||
$APP_USER ALL=(root) NOPASSWD: /usr/bin/systemctl restart nexus.service, /usr/bin/systemctl start nexus.service, /usr/bin/systemctl stop nexus.service, /usr/bin/systemctl status nexus.service, /usr/bin/systemctl restart nexus-worker.service, /usr/bin/systemctl start nexus-worker.service, /usr/bin/systemctl stop nexus-worker.service, /usr/bin/systemctl status nexus-worker.service
|
||||
EOF
|
||||
chmod 440 /etc/sudoers.d/nexus-deploy
|
||||
visudo -cf /etc/sudoers.d/nexus-deploy >/dev/null
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable nexus-worker.service >/dev/null 2>&1
|
||||
msg_ok "nexus-worker.service installed + enabled (starts once a deploy ships start-worker.sh)"
|
||||
|
||||
msg_ok "nexus runtime provisioning finished (idempotent — safe to re-run)"
|
||||
Reference in New Issue
Block a user