#!/usr/bin/env bash # install.sh — one-shot installer for the vetting orchestrator on a # Proxmox LXC (or any Debian/Ubuntu host). # # What it does: # 1. apt-installs runtime dependencies (dnsmasq, iperf3, ca-certs). # 2. Creates the `vetting` system user with /var/lib/vetting homedir. # 3. Copies the pre-built `vetting` binary into /usr/local/bin. # 4. Drops the systemd unit and example config into /etc/vetting. # 5. Reminds the operator to edit the config before enabling # the service — we don't auto-start because the default bind # is loopback-only and needs at least a tweak to be useful. # # What it deliberately does NOT do: # - Build the orchestrator (this script assumes you ran # `make orchestrator-linux` beforehand and that bin/vetting-linux-amd64 # exists alongside this script, or pass --binary to locate it). # - Fetch TFTP iPXE payloads (that's pxe-setup.sh's job — it also # writes the pxe: block of vetting.yaml with first-time args). # # Live-image staging has two modes: # - Release bundle (new format): the bundle carries only a # live-image/VERSION pointer. We compare it to ${LIVE_DIR}/VERSION # and, on mismatch, fetch vmlinuz+initrd.img from the Gitea # generic registry at live-image//. Matched versions # skip the fetch (set FORCE_LIVE_IMAGE=1 to override). # - Repo checkout / legacy bundle: if vmlinuz+initrd.img are present # next to this script (${SCRIPT_DIR}/live-image/) or under # ${REPO_ROOT}/live-image/build/, they're copied straight in. # # Usage: # sudo ./install.sh [--binary PATH] [--config-dir /etc/vetting] # set -euo pipefail # ---- style helpers ----------------------------------------------------- # Identical block across proxmox-install.sh, install.sh, pxe-setup.sh. # Inlined (not sourced) so the curl|bash entrypoint renders without a # prior fetch. Respects NO_COLOR, non-TTY, and non-UTF-8 locales. _color=0; _unicode=0 if [[ -t 2 && -z "${NO_COLOR:-}" && "${TERM:-dumb}" != "dumb" ]]; then _color=1 fi case "${LC_ALL:-}${LANG:-}" in *UTF-8*|*utf8*|*UTF8*) _unicode=1 ;; esac if (( _color )); then _B=$'\033[1m'; _D=$'\033[2m'; _R=$'\033[0m' _C=$'\033[1;36m'; _G=$'\033[32m'; _Y=$'\033[33m'; _E=$'\033[31m' else _B=""; _D=""; _R=""; _C=""; _G=""; _Y=""; _E="" fi if (( _unicode )); then _S_STEP="▸"; _S_OK="✓"; _S_WARN="⚠"; _S_FAIL="✗"; _S_INFO="·" _B_TL="╭"; _B_TR="╮"; _B_BL="╰"; _B_BR="╯"; _B_H="─"; _B_V="│" else _S_STEP="-->"; _S_OK="[ok]"; _S_WARN="[!]"; _S_FAIL="[x]"; _S_INFO="*" _B_TL="+"; _B_TR="+"; _B_BL="+"; _B_BR="+"; _B_H="-"; _B_V="|" fi _start_epoch="$(date +%s)"; _step_epoch=""; _quiet_log=""; _spin_pid="" _fmt_dur() { local s=$1 if (( s < 60 )); then printf '%ds' "$s" elif (( s < 3600 )); then printf '%dm %ds' "$((s/60))" "$((s%60))" else printf '%dh %dm' "$((s/3600))" "$(((s%3600)/60))" fi } banner() { local inner=" $1 " w line="" i=0 w=${#inner} while (( i < w )); do line+="${_B_H}"; i=$((i+1)); done printf '\n %s%s%s%s%s\n' "${_C}" "${_B_TL}" "${line}" "${_B_TR}" "${_R}" >&2 printf ' %s%s%s%s%s%s%s%s%s\n' "${_C}" "${_B_V}" "${_R}" "${_B}" "${inner}" "${_R}" "${_C}" "${_B_V}" "${_R}" >&2 printf ' %s%s%s%s%s\n\n' "${_C}" "${_B_BL}" "${line}" "${_B_BR}" "${_R}" >&2 } step() { _step_epoch="$(date +%s)" printf '%s%s%s %s%s%s\n' "${_C}" "${_S_STEP}" "${_R}" "${_B}" "$1" "${_R}" >&2 } ok() { local tail="" if [[ -n "${_step_epoch}" ]]; then tail=" ${_D}($(_fmt_dur $(( $(date +%s) - _step_epoch ))))${_R}" fi printf ' %s%s%s %s%s\n' "${_G}" "${_S_OK}" "${_R}" "$1" "${tail}" >&2 _step_epoch="" } info() { printf ' %s%s %s%s\n' "${_D}" "${_S_INFO}" "$1" "${_R}" >&2; } warn() { printf ' %s%s %s%s\n' "${_Y}" "${_S_WARN}" "$1" "${_R}" >&2; } die() { printf '\n%s%s %s%s\n' "${_E}" "${_S_FAIL}" "$1" "${_R}" >&2 if [[ -n "${_quiet_log:-}" && -s "${_quiet_log}" ]]; then printf ' %s── last 40 lines of output ──%s\n' "${_D}" "${_R}" >&2 tail -n 40 "${_quiet_log}" | sed 's/^/ /' >&2 printf ' %sfull log: %s%s\n' "${_D}" "${_quiet_log}" "${_R}" >&2 fi exit 1 } _SPIN=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏") _start_spin() { (( _color && _unicode )) || return 0 local label="$1" ( local i=0 while :; do printf '\r %s%s%s %s ' "${_C}" "${_SPIN[i]}" "${_R}" "${label}" >&2 i=$(( (i+1) % ${#_SPIN[@]} )) sleep 0.1 done ) & _spin_pid=$! } _stop_spin() { [[ -n "${_spin_pid}" ]] || return 0 kill "${_spin_pid}" 2>/dev/null || true wait "${_spin_pid}" 2>/dev/null || true _spin_pid="" printf '\r\033[2K' >&2 } # run_quiet "