Add Proxmox LXC installer script for pyMC Repeater with USB passthrough

This commit is contained in:
Lloyd
2026-02-24 09:29:43 +00:00
parent 4d2943087f
commit 496c5a960a
+203
View File
@@ -0,0 +1,203 @@
#!/usr/bin/env bash
# pyMC Repeater - Proxmox LXC Installer
# Creates an LXC container with USB passthrough and installs pyMC Repeater
#
# Usage (run on the Proxmox host):
# bash -c "$(curl -fsSL https://raw.githubusercontent.com/rightup/pyMC_Repeater/main/scripts/proxmox-install.sh)"
#
# License: MIT
# Source: https://github.com/rightup/pyMC_Repeater
set -euo pipefail
# ── Defaults ───────────────────────────────────────────────────────────────
REPO="https://github.com/rightup/pyMC_Repeater.git"
BRANCH="feat/E22p"
CT_TEMPLATE="debian-12-standard"
CT_RAM=1024
CT_SWAP=512
CT_DISK=4
CT_CORES=2
CT_HOSTNAME="pymc-repeater"
CT_BRIDGE="vmbr0"
CT_STORAGE="local-lvm"
CT_TEMPLATE_STORAGE="local"
CH341_VID="1a86"
CH341_PID="5512"
# ── Colors ─────────────────────────────────────────────────────────────────
RD="\033[01;31m" GN="\033[1;92m" YW="\033[33m" BL="\033[36m" BLD="\033[1m" CL="\033[m"
msg_info() { echo -e " ${BL}${CL} ${1}"; }
msg_ok() { echo -e " ${GN}${CL} ${1}"; }
msg_warn() { echo -e " ${YW}${CL} ${1}"; }
msg_error() { echo -e " ${RD}${CL} ${1}"; }
header() {
clear
echo -e "${BLD}"
echo "═══════════════════════════════════════════════════════════════"
echo " pyMC Repeater - Proxmox LXC Installer"
echo "═══════════════════════════════════════════════════════════════"
echo -e "${CL}"
}
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ] && [ -n "${CTID:-}" ] && pct status "$CTID" &>/dev/null; then
echo ""
read -p " Delete the failed container ${CTID}? [y/N]: " -r
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
pct stop "$CTID" 2>/dev/null || true
pct destroy "$CTID" 2>/dev/null || true
msg_ok "Container ${CTID} removed"
fi
fi
}
trap cleanup EXIT
# ── Preflight checks ──────────────────────────────────────────────────────
header
if ! command -v pct &>/dev/null; then
msg_error "This script must be run on a Proxmox VE host."
exit 1
fi
if [ "$EUID" -ne 0 ]; then
msg_error "Please run as root"
exit 1
fi
msg_ok "Running on Proxmox host as root"
# Check for CH341
echo ""
if lsusb -d "${CH341_VID}:${CH341_PID}" &>/dev/null; then
msg_ok "CH341 USB device detected"
else
msg_warn "CH341 USB device not found — plug it in before starting the repeater"
fi
# ── Interactive settings ──────────────────────────────────────────────────
echo ""
echo -e "${BLD}Container Settings${CL} (press Enter for defaults):"
echo ""
read -p " Hostname [${CT_HOSTNAME}]: " -r input; CT_HOSTNAME="${input:-$CT_HOSTNAME}"
read -p " RAM in MB [${CT_RAM}]: " -r input; CT_RAM="${input:-$CT_RAM}"
read -p " Disk in GB [${CT_DISK}]: " -r input; CT_DISK="${input:-$CT_DISK}"
read -p " CPU cores [${CT_CORES}]: " -r input; CT_CORES="${input:-$CT_CORES}"
read -p " Bridge [${CT_BRIDGE}]: " -r input; CT_BRIDGE="${input:-$CT_BRIDGE}"
AVAILABLE_STORAGES=$(pvesm status -content rootdir 2>/dev/null | awk 'NR>1 {print $1}' || echo "local-lvm")
echo " Available storages: ${AVAILABLE_STORAGES}"
read -p " Storage [${CT_STORAGE}]: " -r input; CT_STORAGE="${input:-$CT_STORAGE}"
read -p " Git branch [${BRANCH}]: " -r input; BRANCH="${input:-$BRANCH}"
# ── Get next CTID ─────────────────────────────────────────────────────────
CTID=$(pvesh get /cluster/nextid)
# ── Confirmation ──────────────────────────────────────────────────────────
echo ""
echo -e "${BLD}Summary:${CL}"
echo " CTID: ${CTID} Host: ${CT_HOSTNAME} RAM: ${CT_RAM}MB Disk: ${CT_DISK}GB"
echo " Cores: ${CT_CORES} Storage: ${CT_STORAGE} Bridge: ${CT_BRIDGE} Branch: ${BRANCH}"
echo " Mode: privileged (required for USB passthrough)"
echo ""
read -p " Proceed? [Y/n]: " -r
[[ "${REPLY:-Y}" =~ ^[Nn]$ ]] && { msg_warn "Aborted"; exit 0; }
# ── Download template ─────────────────────────────────────────────────────
echo ""
msg_info "Downloading Debian 12 template..."
TEMPLATE_FILE=$(pveam available -section system 2>/dev/null | grep "${CT_TEMPLATE}" | sort -t- -k4 -V | tail -1 | awk '{print $2}')
[ -z "$TEMPLATE_FILE" ] && { msg_error "Template not found. Run: pveam update"; exit 1; }
pveam list "$CT_TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE_FILE" || \
pveam download "$CT_TEMPLATE_STORAGE" "$TEMPLATE_FILE"
msg_ok "Template ready"
# ── Create container ──────────────────────────────────────────────────────
msg_info "Creating LXC container ${CTID}..."
pct create "$CTID" "${CT_TEMPLATE_STORAGE}:vztmpl/${TEMPLATE_FILE}" \
--hostname "$CT_HOSTNAME" \
--memory "$CT_RAM" \
--swap "$CT_SWAP" \
--cores "$CT_CORES" \
--rootfs "${CT_STORAGE}:${CT_DISK}" \
--net0 "name=eth0,bridge=${CT_BRIDGE},ip=dhcp" \
--unprivileged 0 \
--features nesting=1 \
--onboot 1 \
--start 0 \
--ostype debian
msg_ok "Container created"
# ── USB passthrough ───────────────────────────────────────────────────────
msg_info "Configuring USB passthrough..."
cat >> "/etc/pve/lxc/${CTID}.conf" <<'EOF'
# CH341 USB passthrough for pyMC Repeater
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/bus/usb dev/bus/usb none bind,optional,create=dir 0 0
EOF
msg_ok "USB passthrough configured"
# ── Host udev rule ────────────────────────────────────────────────────────
msg_info "Installing CH341 udev rule on host..."
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="5512", MODE="0666"' \
> /etc/udev/rules.d/99-ch341.rules
udevadm control --reload-rules
udevadm trigger --subsystem-match=usb --action=change
msg_ok "Host udev rule installed"
# ── Start container & wait for network ────────────────────────────────────
msg_info "Starting container..."
pct start "$CTID"
sleep 3
for _ in $(seq 1 30); do
pct exec "$CTID" -- ping -c1 -W1 8.8.8.8 &>/dev/null && break
sleep 1
done
msg_ok "Container running with network"
# ── Bootstrap: install git, clone repo ────────────────────────────────────
msg_info "Installing git inside container..."
pct exec "$CTID" -- bash -c "
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq && apt-get install -y git whiptail >/dev/null 2>&1
"
msg_ok "Git installed"
msg_info "Cloning pyMC_Repeater (branch: ${BRANCH})..."
pct exec "$CTID" -- bash -c "git clone --branch ${BRANCH} ${REPO} /root/pyMC_Repeater"
msg_ok "Repository cloned"
# ── Run manage.sh install ─────────────────────────────────────────────────
msg_info "Running manage.sh install (this will take several minutes)..."
echo ""
# Use lxc-attach with a pty so manage.sh gets an interactive terminal
lxc-attach -n "$CTID" -- bash -c "cd /root/pyMC_Repeater && TERM=xterm bash manage.sh install"
echo ""
msg_ok "manage.sh install completed"
# ── Get container IP ──────────────────────────────────────────────────────
sleep 2
CT_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}')
# ── Done ──────────────────────────────────────────────────────────────────
echo ""
echo -e "${BLD}"
echo "═══════════════════════════════════════════════════════════════"
echo " ✓ pyMC Repeater Installation Complete!"
echo "═══════════════════════════════════════════════════════════════"
echo -e "${CL}"
echo -e " Container: ${GN}${CTID}${CL} (${CT_HOSTNAME})"
echo -e " IP Address: ${GN}${CT_IP:-unknown}${CL}"
echo -e " Dashboard: ${GN}http://${CT_IP:-<ip>}:8000${CL}"
echo ""
echo " Next: open the dashboard and complete the setup wizard"
echo " Management: pct enter ${CTID}, then: cd /opt/pymc_repeater && bash manage.sh"
echo ""
echo "═══════════════════════════════════════════════════════════════"