#!/usr/bin/env bash # proxmox-lxc.sh — create an unprivileged Debian 12 LXC on a Proxmox VE host # and install Busbar Designer into it. Inspired by the community-scripts style. # # Run on the Proxmox host as root, e.g.: # # bash -c "$(curl -fsSL https://gitea.local/me/busbar-designer/raw/branch/main/deploy/proxmox-lxc.sh)" # # Interactive whiptail prompts; or pre-set everything via env to skip prompts: # # REPO_URL=https://gitea.local/me/busbar-designer.git \ # CTID=210 HOSTNAME=busbar DISK_SIZE=4 CORES=2 RAM=1024 \ # BRIDGE=vmbr0 IP=dhcp STORAGE=local-lvm \ # bash proxmox-lxc.sh set -euo pipefail # ---- colors ---------------------------------------------------------------- GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m' BLUE='\033[0;34m'; BOLD='\033[1m'; NC='\033[0m' log() { echo -e "${GREEN}▸${NC} $*"; } warn() { echo -e "${YELLOW}!${NC} $*"; } die() { echo -e "${RED}✗ $*${NC}" >&2; exit 1; } banner() { cat <<'EOF' ____ _ ____ _ | __ ) _ _ ___| |__ __ _ _ __ | _ \ ___ ___(_) __ _ _ __ ___ _ __ | _ \| | | / __| '_ \ / _` | '__| | | | |/ _ \/ __| |/ _` | '_ \ / _ \ '__| | |_) | |_| \__ \ |_) | (_| | | | |_| | __/\__ \ | (_| | | | | __/ | |____/ \__,_|___/_.__/ \__,_|_| |____/ \___||___/_|\__, |_| |_|\___|_| |___/ Proxmox VE LXC installer EOF } # ---- preflight ------------------------------------------------------------- [[ $EUID -eq 0 ]] || die "Run as root on the Proxmox host." command -v pveversion >/dev/null 2>&1 || die "pveversion not found — is this a Proxmox VE host?" command -v pct >/dev/null 2>&1 || die "pct not found — Proxmox VE tools missing?" banner # ---- defaults -------------------------------------------------------------- CTID_DEFAULT=$(pvesh get /cluster/nextid 2>/dev/null || echo "200") CTID="${CTID:-$CTID_DEFAULT}" HOSTNAME="${HOSTNAME:-busbar-designer}" DISK_SIZE="${DISK_SIZE:-4}" CORES="${CORES:-2}" RAM="${RAM:-1024}" SWAP="${SWAP:-512}" BRIDGE="${BRIDGE:-vmbr0}" IP="${IP:-dhcp}" STORAGE="${STORAGE:-local-lvm}" TEMPLATE_STORAGE="${TEMPLATE_STORAGE:-local}" REPO_URL="${REPO_URL:-}" BRANCH="${BRANCH:-main}" GIT_SSL_NO_VERIFY="${GIT_SSL_NO_VERIFY:-0}" # ---- interactive prompts (whiptail) ---------------------------------------- ask() { local var="$1" prompt="$2" default="$3" h="${4:-8}" w="${5:-60}" local val if [[ -t 0 ]] && command -v whiptail >/dev/null 2>&1; then val=$(whiptail --title "Busbar Designer" --inputbox "$prompt" "$h" "$w" "$default" \ 3>&1 1>&2 2>&3) || die "Cancelled." else read -rp "$prompt [$default]: " val val="${val:-$default}" fi printf -v "$var" '%s' "$val" } yesno() { local prompt="$1" default="${2:-no}" if [[ -t 0 ]] && command -v whiptail >/dev/null 2>&1; then if [[ "$default" == "yes" ]]; then whiptail --title "Busbar Designer" --yesno "$prompt" 8 60 else whiptail --title "Busbar Designer" --yesno "$prompt" --defaultno 8 60 fi else read -rp "$prompt [$default]: " val [[ "${val:-$default}" =~ ^(y|yes)$ ]] fi } if [[ -z "$REPO_URL" ]] || [[ -t 0 ]]; then ask CTID "Container ID" "$CTID" ask HOSTNAME "Hostname" "$HOSTNAME" ask DISK_SIZE "Root disk size (GB)" "$DISK_SIZE" ask CORES "CPU cores" "$CORES" ask RAM "RAM (MB)" "$RAM" ask STORAGE "Storage pool for rootfs (e.g. local-lvm, local-zfs)" "$STORAGE" 8 70 ask BRIDGE "Network bridge" "$BRIDGE" ask IP "IP config: 'dhcp' or 'a.b.c.d/24,gw=a.b.c.1'" "$IP" 8 70 ask REPO_URL "Git URL of busbar-designer repo (your Gitea / GitHub)" \ "${REPO_URL:-https://gitea.local/me/busbar-designer.git}" 10 70 ask BRANCH "Branch" "$BRANCH" if yesno "Skip TLS verification for git? (only if your Gitea uses a self-signed cert)"; then GIT_SSL_NO_VERIFY=1 fi fi [[ -n "$REPO_URL" ]] || die "REPO_URL is required." # ---- template -------------------------------------------------------------- log "Looking for a Debian 12 template..." TEMPLATE=$(pveam available --section system 2>/dev/null \ | awk '/debian-12-standard/ {print $2}' | sort -r | head -n 1) [[ -n "$TEMPLATE" ]] || die "Couldn't find debian-12-standard in 'pveam available'. Run 'pveam update' first." LOCAL_TEMPLATE="/var/lib/vz/template/cache/$TEMPLATE" if [[ ! -f "$LOCAL_TEMPLATE" ]]; then log "Downloading template $TEMPLATE..." pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" fi # ---- create LXC ------------------------------------------------------------ if pct status "$CTID" >/dev/null 2>&1; then die "Container $CTID already exists. Pick a different CTID." fi PASSWORD="$(openssl rand -base64 12 | tr -d '/+=' | cut -c1-16)" if [[ "$IP" == "dhcp" ]]; then NET="name=eth0,bridge=$BRIDGE,ip=dhcp" else NET="name=eth0,bridge=$BRIDGE,ip=$IP" fi log "Creating LXC $CTID ($HOSTNAME)..." pct create "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" \ --hostname "$HOSTNAME" \ --cores "$CORES" \ --memory "$RAM" \ --swap "$SWAP" \ --rootfs "$STORAGE:$DISK_SIZE" \ --net0 "$NET" \ --password "$PASSWORD" \ --features nesting=1 \ --unprivileged 1 \ --onboot 1 \ --start 1 \ --description "Busbar Designer · $REPO_URL ($BRANCH)" >/dev/null # ---- wait for network ------------------------------------------------------ log "Waiting for network in CT $CTID..." for i in {1..30}; do if pct exec "$CTID" -- bash -c "getent hosts deb.debian.org >/dev/null" 2>/dev/null; then break fi sleep 2 done # ---- run installer inside the LXC ------------------------------------------ log "Bootstrapping git + curl in the container..." pct exec "$CTID" -- bash -c " set -e export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq git ca-certificates curl " || die "Failed to install bootstrap packages in CT." log "Cloning repo and running deploy/install.sh inside CT $CTID..." pct exec "$CTID" -- bash -c " set -e ${GIT_SSL_NO_VERIFY:+export GIT_SSL_NO_VERIFY=true} rm -rf /opt/busbar-designer git clone --depth 1 -b '$BRANCH' '$REPO_URL' /opt/busbar-designer REPO_URL='$REPO_URL' BRANCH='$BRANCH' \ ${GIT_SSL_NO_VERIFY:+GIT_SSL_NO_VERIFY=1} \ bash /opt/busbar-designer/deploy/install.sh " || die "Installer failed. Inspect with: pct enter $CTID" # ---- report --------------------------------------------------------------- IP_ADDR=$(pct exec "$CTID" -- bash -c "hostname -I | awk '{print \$1}'" 2>/dev/null || true) [[ -n "$IP_ADDR" ]] || IP_ADDR="" echo log "================================================================" log " ${BOLD}✓ Busbar Designer LXC ready${NC}" log "" log " Container ID: $CTID" log " Hostname: $HOSTNAME" log " Root password: $PASSWORD" log " URL: http://$IP_ADDR:5000" log "" log " Update: pct exec $CTID -- bash /opt/busbar-designer/deploy/update.sh" log " Logs: pct exec $CTID -- journalctl -u busbar-designer -f" log " Enter: pct enter $CTID" log " Backup: pct exec $CTID -- cat /opt/busbar-designer/data/busbar.db > backup.db" log "================================================================"