From 100149241ccad589005365e8dea8cc244c404e24 Mon Sep 17 00:00:00 2001 From: eduard256 Date: Thu, 16 Apr 2026 17:51:19 +0000 Subject: [PATCH] Sync all scripts to main --- scripts/proxmox-test.sh | 9 + scripts/proxmox.sh | 423 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 432 insertions(+) create mode 100755 scripts/proxmox-test.sh create mode 100755 scripts/proxmox.sh diff --git a/scripts/proxmox-test.sh b/scripts/proxmox-test.sh new file mode 100755 index 0000000..27abc4c --- /dev/null +++ b/scripts/proxmox-test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +SCRIPT_URL="https://raw.githubusercontent.com/eduard256/Strix/main/scripts/proxmox.sh" + +whiptail --title " Strix " --yesno "Run Strix installer?" 8 40 || { clear; exit 0; } + +tmpfile=$(mktemp /tmp/strix-proxmox.XXXXXX) +curl -fsSL "$SCRIPT_URL" -o "$tmpfile" 2>/dev/null || { echo "Download failed"; exit 1; } +bash "$tmpfile" +rm -f "$tmpfile" diff --git a/scripts/proxmox.sh b/scripts/proxmox.sh new file mode 100755 index 0000000..b228b42 --- /dev/null +++ b/scripts/proxmox.sh @@ -0,0 +1,423 @@ +#!/usr/bin/env bash +# ============================================================================= +# Strix -- proxmox.sh (navigator for Proxmox) +# ============================================================================= + +set -o pipefail + +BACKTITLE="Strix Installer" +WT_H=16 +WT_W=60 + +command -v whiptail &>/dev/null || { echo "whiptail required"; exit 1; } + +# Parameters +INSTALL_MODE="" +FRIGATE_URL="" +GO2RTC_URL="" +STRIX_PORT="4567" +LXC_HOSTNAME="strix" +LXC_MEMORY="2048" +LXC_CORES="2" +LXC_DISK="32" +LXC_SWAP="512" +LXC_IP="dhcp" +LXC_GATEWAY="" +LXC_BRIDGE="" +LXC_STORAGE="" + +# --------------------------------------------------------------------------- +# Simple flow +# --------------------------------------------------------------------------- +simple_flow() { + local step=1 + while true; do + case $step in + 1) # Mode + INSTALL_MODE=$(whiptail --backtitle "$BACKTITLE" --title " Install Mode " \ + --menu "" $WT_H $WT_W 3 \ + "1" "Strix only" \ + "2" "Strix + Frigate" \ + "3" "Advanced setup" \ + 3>&1 1>&2 2>&3) || { clear; exit 0; } + + case "$INSTALL_MODE" in + 1) INSTALL_MODE="strix"; step=2 ;; + 2) INSTALL_MODE="strix-frigate"; step=3 ;; + 3) advanced_flow; return ;; + esac + ;; + + 2) # Frigate URL (strix only) + FRIGATE_URL=$(whiptail --backtitle "$BACKTITLE" --title " Frigate " \ + --inputbox "Frigate URL (empty to skip):\n\nExample: http://192.168.1.100:5000" \ + $WT_H $WT_W "${FRIGATE_URL:-http://}" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + + [[ "$FRIGATE_URL" == "http://" || "$FRIGATE_URL" == "https://" ]] && FRIGATE_URL="" + step=3 + ;; + + 3) # Confirm + local s="Mode: ${INSTALL_MODE}\nPort: ${STRIX_PORT}\n" + [[ -n "$FRIGATE_URL" ]] && s+="Frigate: ${FRIGATE_URL}\n" + s+="\nLXC: auto (${LXC_HOSTNAME}, ${LXC_MEMORY}MB, ${LXC_CORES}cpu, ${LXC_DISK}GB)" + + whiptail --backtitle "$BACKTITLE" --title " Confirm " \ + --yesno "$s" $WT_H $WT_W || { step=1; continue; } + break + ;; + esac + done +} + +# --------------------------------------------------------------------------- +# Advanced flow +# --------------------------------------------------------------------------- +advanced_flow() { + local step=1 + INSTALL_MODE="${INSTALL_MODE:-strix}" + + while true; do + case $step in + 1) # Mode + local choice + choice=$(whiptail --backtitle "$BACKTITLE" --title " Mode " \ + --menu "" $WT_H $WT_W 2 \ + "strix" "Strix only" \ + "strix-frigate" "Strix + Frigate" \ + --default-item "$INSTALL_MODE" \ + 3>&1 1>&2 2>&3) || { clear; exit 0; } + INSTALL_MODE="$choice"; step=2 ;; + + 2) # Port + local val + val=$(whiptail --backtitle "$BACKTITLE" --title " Port " \ + --inputbox "Strix port:" 9 $WT_W "$STRIX_PORT" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + STRIX_PORT="${val:-4567}"; step=3 ;; + + 3) # Frigate + val=$(whiptail --backtitle "$BACKTITLE" --title " Frigate " \ + --inputbox "Frigate URL (empty to skip):" 9 $WT_W "${FRIGATE_URL:-http://}" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + [[ "$val" == "http://" || "$val" == "https://" ]] && val="" + FRIGATE_URL="$val"; step=4 ;; + + 4) # go2rtc + val=$(whiptail --backtitle "$BACKTITLE" --title " go2rtc " \ + --inputbox "go2rtc URL (empty to skip):" 9 $WT_W "${GO2RTC_URL:-http://}" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + [[ "$val" == "http://" || "$val" == "https://" ]] && val="" + GO2RTC_URL="$val"; step=5 ;; + + 5) # Hostname + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC Hostname " \ + --inputbox "Hostname:" 9 $WT_W "$LXC_HOSTNAME" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_HOSTNAME="${val:-strix}"; step=6 ;; + + 6) # RAM + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC RAM " \ + --inputbox "RAM (MB):" 9 $WT_W "$LXC_MEMORY" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_MEMORY="${val:-2048}"; step=7 ;; + + 7) # CPU + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC CPU " \ + --inputbox "CPU cores:" 9 $WT_W "$LXC_CORES" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_CORES="${val:-2}"; step=8 ;; + + 8) # Disk + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC Disk " \ + --inputbox "Disk (GB):" 9 $WT_W "$LXC_DISK" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_DISK="${val:-32}"; step=9 ;; + + 9) # Swap + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC Swap " \ + --inputbox "Swap (MB):" 9 $WT_W "$LXC_SWAP" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_SWAP="${val:-512}"; step=10 ;; + + 10) # IP + val=$(whiptail --backtitle "$BACKTITLE" --title " LXC Network " \ + --inputbox "IP (dhcp or CIDR e.g. 10.0.20.110/24):" 9 $WT_W "$LXC_IP" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_IP="${val:-dhcp}" + [[ "$LXC_IP" != "dhcp" ]] && step=11 || step=12 + ;; + + 11) # Gateway + val=$(whiptail --backtitle "$BACKTITLE" --title " Gateway " \ + --inputbox "Gateway:" 9 $WT_W "$LXC_GATEWAY" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_GATEWAY="$val"; step=12 ;; + + 12) # Bridge + val=$(whiptail --backtitle "$BACKTITLE" --title " Bridge " \ + --inputbox "Network bridge (empty=auto):" 9 $WT_W "$LXC_BRIDGE" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_BRIDGE="$val"; step=13 ;; + + 13) # Storage + val=$(whiptail --backtitle "$BACKTITLE" --title " Storage " \ + --inputbox "Storage (empty=auto):" 9 $WT_W "$LXC_STORAGE" \ + 3>&1 1>&2 2>&3) || { step=1; continue; } + LXC_STORAGE="$val"; step=14 ;; + + 14) # Confirm + local s="Mode: ${INSTALL_MODE}\nPort: ${STRIX_PORT}\n" + [[ -n "$FRIGATE_URL" ]] && s+="Frigate: ${FRIGATE_URL}\n" + [[ -n "$GO2RTC_URL" ]] && s+="go2rtc: ${GO2RTC_URL}\n" + s+="\nLXC:\n" + s+=" ${LXC_HOSTNAME} | ${LXC_MEMORY}MB | ${LXC_CORES}cpu | ${LXC_DISK}GB\n" + s+=" IP: ${LXC_IP}" + [[ -n "$LXC_GATEWAY" ]] && s+=" gw ${LXC_GATEWAY}" + s+="\n" + [[ -n "$LXC_BRIDGE" ]] && s+=" Bridge: ${LXC_BRIDGE}\n" || s+=" Bridge: auto\n" + [[ -n "$LXC_STORAGE" ]] && s+=" Storage: ${LXC_STORAGE}\n" || s+=" Storage: auto\n" + + whiptail --backtitle "$BACKTITLE" --title " Confirm " \ + --yesno "$s" 18 $WT_W || { step=1; continue; } + break + ;; + esac + done +} + +# --------------------------------------------------------------------------- +# Colors +# --------------------------------------------------------------------------- +C_RESET="\033[0m" +C_BOLD="\033[1m" +C_DIM="\033[2m" +C_GREEN="\033[32m" +C_RED="\033[31m" +C_YELLOW="\033[33m" +C_CYAN="\033[36m" +C_WHITE="\033[97m" +C_MAGENTA="\033[35m" + +# --------------------------------------------------------------------------- +# Worker runner: streams JSON events and prints status lines +# --------------------------------------------------------------------------- +SCRIPTS_BASE="https://raw.githubusercontent.com/eduard256/Strix/main/scripts" + +# Download a worker script to /tmp +download_worker() { + local name="$1" + local dest="/tmp/strix-${name}" + curl -fsSL "${SCRIPTS_BASE}/${name}" -o "$dest" 2>/dev/null + echo "$dest" +} + +# Run a worker and display its JSON events as status lines +run_worker() { + local script="$1" + shift + local label="$1" + shift + + echo "" + echo -e " ${C_MAGENTA}${C_BOLD}--- ${label} ---${C_RESET}" + echo "" + + bash "$script" "$@" 2>/dev/null | while IFS= read -r line; do + local type msg + type=$(echo "$line" | grep -oP '"type"\s*:\s*"\K[^"]+' | head -1) + msg=$(echo "$line" | grep -oP '"msg"\s*:\s*"\K[^"]+' | head -1) + + case "$type" in + check) echo -e " ${C_CYAN}[..]${C_RESET} ${msg}" ;; + ok) echo -e " ${C_GREEN}[OK]${C_RESET} ${msg}" ;; + miss) echo -e " ${C_YELLOW}[--]${C_RESET} ${msg}" ;; + install) echo -e " ${C_CYAN}[>>]${C_RESET} ${msg}" ;; + error) echo -e " ${C_RED}[XX]${C_RESET} ${msg}" ;; + done) ;; # handled after loop + esac + done + + echo "" +} + +# Extract a field from JSON done line +json_field() { + echo "$1" | grep -oP "\"$2\"\s*:\s*\"\K[^\"]*" | head -1 +} + +# --------------------------------------------------------------------------- +# Show final URLs +# --------------------------------------------------------------------------- +show_urls() { + local ip="$1" + local port="$2" + local mode="$3" + + echo "" + echo -e " ${C_GREEN}${C_BOLD}====================================${C_RESET}" + echo -e " ${C_GREEN}${C_BOLD} Installation Complete${C_RESET}" + echo -e " ${C_GREEN}${C_BOLD}====================================${C_RESET}" + echo "" + echo -e " ${C_WHITE}${C_BOLD}Strix:${C_RESET} ${C_CYAN}http://${ip}:${port}${C_RESET}" + + if [[ "$mode" == "strix-frigate" ]]; then + echo -e " ${C_WHITE}${C_BOLD}Frigate:${C_RESET} ${C_CYAN}http://${ip}:8971${C_RESET}" + echo -e " ${C_WHITE}${C_BOLD}Frigate API:${C_RESET} ${C_CYAN}http://${ip}:5000${C_RESET}" + echo -e " ${C_WHITE}${C_BOLD}go2rtc:${C_RESET} ${C_CYAN}http://${ip}:1984${C_RESET}" + fi + + echo "" + echo -e " ${C_DIM}Press Enter to exit${C_RESET}" + read -r +} + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- +simple_flow + +clear +echo "" +echo -e " ${C_MAGENTA}${C_BOLD}STRIX INSTALLER${C_RESET}" +echo -e " ${C_DIM}Mode: ${INSTALL_MODE} | Port: ${STRIX_PORT}${C_RESET}" +echo "" + +# Step 1: Create LXC container +lxc_script=$(download_worker "proxmox-lxc-create.sh") + +lxc_args="" +[[ -n "$LXC_HOSTNAME" ]] && lxc_args="$lxc_args --hostname $LXC_HOSTNAME" +[[ -n "$LXC_MEMORY" ]] && lxc_args="$lxc_args --memory $LXC_MEMORY" +[[ -n "$LXC_CORES" ]] && lxc_args="$lxc_args --cores $LXC_CORES" +[[ -n "$LXC_DISK" ]] && lxc_args="$lxc_args --disk $LXC_DISK" +[[ -n "$LXC_SWAP" ]] && lxc_args="$lxc_args --swap $LXC_SWAP" +[[ -n "$LXC_BRIDGE" ]] && lxc_args="$lxc_args --bridge $LXC_BRIDGE" +[[ -n "$LXC_STORAGE" ]] && lxc_args="$lxc_args --storage $LXC_STORAGE" +[[ "$LXC_IP" != "dhcp" && -n "$LXC_IP" ]] && lxc_args="$lxc_args --ip $LXC_IP" +[[ -n "$LXC_GATEWAY" ]] && lxc_args="$lxc_args --gateway $LXC_GATEWAY" + +# Run LXC creation and capture full output +lxc_output=$(bash "$lxc_script" $lxc_args 2>/dev/null) +lxc_done=$(echo "$lxc_output" | grep '"type":"done"') + +# Display LXC creation events +echo "$lxc_output" | while IFS= read -r line; do + local type msg + type=$(echo "$line" | grep -oP '"type"\s*:\s*"\K[^"]+' | head -1) + msg=$(echo "$line" | grep -oP '"msg"\s*:\s*"\K[^"]+' | head -1) + case "$type" in + check) echo -e " ${C_CYAN}[..]${C_RESET} ${msg}" ;; + ok) echo -e " ${C_GREEN}[OK]${C_RESET} ${msg}" ;; + miss) echo -e " ${C_YELLOW}[--]${C_RESET} ${msg}" ;; + install) echo -e " ${C_CYAN}[>>]${C_RESET} ${msg}" ;; + error) echo -e " ${C_RED}[XX]${C_RESET} ${msg}" ;; + esac +done + +# Check if LXC creation succeeded +lxc_ok=$(echo "$lxc_done" | grep -oP '"ok"\s*:\s*\K[a-z]+' | head -1) +if [[ "$lxc_ok" != "true" ]]; then + echo "" + echo -e " ${C_RED}${C_BOLD}LXC creation failed. Aborting.${C_RESET}" + rm -f "$lxc_script" + exit 1 +fi + +# Extract LXC data +CT_ID=$(json_field "$lxc_done" "id") +CT_IP=$(json_field "$lxc_done" "ip") +CT_PASS=$(json_field "$lxc_done" "password") + +echo "" +echo -e " ${C_GREEN}${C_BOLD}LXC ${CT_ID} ready${C_RESET} -- IP: ${C_WHITE}${CT_IP}${C_RESET}" + +# Step 2: Run prepare.sh inside LXC (install Docker) +echo "" +echo -e " ${C_MAGENTA}${C_BOLD}--- Installing Docker ---${C_RESET}" +echo "" + +prepare_script=$(download_worker "prepare.sh") +pct push "$CT_ID" "$prepare_script" /tmp/prepare.sh &>/dev/null + +pct exec "$CT_ID" -- bash /tmp/prepare.sh 2>/dev/null | while IFS= read -r line; do + type=$(echo "$line" | grep -oP '"type"\s*:\s*"\K[^"]+' | head -1) + msg=$(echo "$line" | grep -oP '"msg"\s*:\s*"\K[^"]+' | head -1) + case "$type" in + check) echo -e " ${C_CYAN}[..]${C_RESET} ${msg}" ;; + ok) echo -e " ${C_GREEN}[OK]${C_RESET} ${msg}" ;; + miss) echo -e " ${C_YELLOW}[--]${C_RESET} ${msg}" ;; + install) echo -e " ${C_CYAN}[>>]${C_RESET} ${msg}" ;; + error) echo -e " ${C_RED}[XX]${C_RESET} ${msg}" ;; + esac +done + +# Step 3: Deploy Strix (or Strix + Frigate) +if [[ "$INSTALL_MODE" == "strix-frigate" ]]; then + echo "" + echo -e " ${C_MAGENTA}${C_BOLD}--- Deploying Strix + Frigate ---${C_RESET}" + echo "" + + deploy_script=$(download_worker "strix-frigate.sh") + pct push "$CT_ID" "$deploy_script" /tmp/deploy.sh &>/dev/null + + deploy_args="--port $STRIX_PORT" + [[ -n "$GO2RTC_URL" ]] && deploy_args="$deploy_args --go2rtc-url $GO2RTC_URL" + + deploy_output=$(pct exec "$CT_ID" -- bash /tmp/deploy.sh $deploy_args 2>/dev/null) + deploy_done=$(echo "$deploy_output" | grep '"type":"done"') + + echo "$deploy_output" | while IFS= read -r line; do + type=$(echo "$line" | grep -oP '"type"\s*:\s*"\K[^"]+' | head -1) + msg=$(echo "$line" | grep -oP '"msg"\s*:\s*"\K[^"]+' | head -1) + case "$type" in + check) echo -e " ${C_CYAN}[..]${C_RESET} ${msg}" ;; + ok) echo -e " ${C_GREEN}[OK]${C_RESET} ${msg}" ;; + miss) echo -e " ${C_YELLOW}[--]${C_RESET} ${msg}" ;; + install) echo -e " ${C_CYAN}[>>]${C_RESET} ${msg}" ;; + error) echo -e " ${C_RED}[XX]${C_RESET} ${msg}" ;; + esac + done + +else + echo "" + echo -e " ${C_MAGENTA}${C_BOLD}--- Deploying Strix ---${C_RESET}" + echo "" + + deploy_script=$(download_worker "strix.sh") + pct push "$CT_ID" "$deploy_script" /tmp/deploy.sh &>/dev/null + + deploy_args="--port $STRIX_PORT" + [[ -n "$FRIGATE_URL" ]] && deploy_args="$deploy_args --frigate-url $FRIGATE_URL" + [[ -n "$GO2RTC_URL" ]] && deploy_args="$deploy_args --go2rtc-url $GO2RTC_URL" + + deploy_output=$(pct exec "$CT_ID" -- bash /tmp/deploy.sh $deploy_args 2>/dev/null) + deploy_done=$(echo "$deploy_output" | grep '"type":"done"') + + echo "$deploy_output" | while IFS= read -r line; do + type=$(echo "$line" | grep -oP '"type"\s*:\s*"\K[^"]+' | head -1) + msg=$(echo "$line" | grep -oP '"msg"\s*:\s*"\K[^"]+' | head -1) + case "$type" in + check) echo -e " ${C_CYAN}[..]${C_RESET} ${msg}" ;; + ok) echo -e " ${C_GREEN}[OK]${C_RESET} ${msg}" ;; + miss) echo -e " ${C_YELLOW}[--]${C_RESET} ${msg}" ;; + install) echo -e " ${C_CYAN}[>>]${C_RESET} ${msg}" ;; + error) echo -e " ${C_RED}[XX]${C_RESET} ${msg}" ;; + esac + done +fi + +# Show final URLs +deploy_ok=$(echo "$deploy_done" | grep -oP '"ok"\s*:\s*\K[a-z]+' | head -1) +if [[ "$deploy_ok" == "true" ]]; then + show_urls "$CT_IP" "$STRIX_PORT" "$INSTALL_MODE" +else + echo "" + echo -e " ${C_RED}${C_BOLD}Deployment failed.${C_RESET}" + echo -e " ${C_DIM}LXC ${CT_ID} (${CT_IP}) is still running. Check logs inside.${C_RESET}" + echo "" +fi + +# Cleanup +rm -f "$lxc_script" "$prepare_script" "$deploy_script" 2>/dev/null