Files
wireguard-ui-multi/scripts/proxmox-install.sh
T
sysopsandClaude Sonnet 5 f333623035 Run go mod tidy before build in all installers
go.sum was never committed (no local Go toolchain to generate it),
causing "missing go.sum entry" build failures on target hosts.
go mod tidy regenerates it automatically before go build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 17:53:20 +02:00

179 lines
5.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Runs on a Proxmox VE host. Creates a privileged LXC container prepared for
# WireGuard (kernel module + /dev/net/tun + CAP_NET_ADMIN + nftables), copies
# this repo into it, and runs scripts/install.sh inside the container.
#
# Privileged container is required: WireGuard needs CAP_NET_ADMIN and access
# to /dev/net/tun, which unprivileged LXC containers cannot reliably get.
set -euo pipefail
usage() {
cat >&2 <<EOF
Usage: $0 --vmid <id> --hostname <name> [options]
Required:
--vmid <id> numeric LXC container ID (e.g. 200)
--hostname <name> container hostname (e.g. wireguard-ui-multi)
Options:
--storage <name> Proxmox storage for rootfs (default: local-lvm)
--template <path> LXC template volid (default: auto-detect + download newest debian-* template)
--bridge <name> network bridge (default: vmbr0)
--ip <cidr|dhcp> static CIDR (e.g. 10.0.0.50/24) or "dhcp" (default: dhcp)
--gw <ip> gateway IP, required if --ip is a static CIDR
--disk <GB> rootfs size in GB (default: 4)
--memory <MB> RAM in MB (default: 512)
--cores <n> CPU cores (default: 1)
--repo-src <path> path to this repo on the Proxmox host (default: script's own repo root)
--start start the container after creation (default: created but stopped, then started to run the installer, left running)
EOF
exit 1
}
VMID=""
HOSTNAME=""
STORAGE="local-lvm"
TEMPLATE=""
BRIDGE="vmbr0"
IP="dhcp"
GW=""
DISK="4"
MEMORY="512"
CORES="1"
REPO_SRC=""
while [[ $# -gt 0 ]]; do
case "$1" in
--vmid) VMID="$2"; shift 2 ;;
--hostname) HOSTNAME="$2"; shift 2 ;;
--storage) STORAGE="$2"; shift 2 ;;
--template) TEMPLATE="$2"; shift 2 ;;
--bridge) BRIDGE="$2"; shift 2 ;;
--ip) IP="$2"; shift 2 ;;
--gw) GW="$2"; shift 2 ;;
--disk) DISK="$2"; shift 2 ;;
--memory) MEMORY="$2"; shift 2 ;;
--cores) CORES="$2"; shift 2 ;;
--repo-src) REPO_SRC="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown option: $1" >&2; usage ;;
esac
done
[[ -z "$VMID" || -z "$HOSTNAME" ]] && usage
if [[ "$(id -u)" -ne 0 ]]; then
echo "Must run as root on the Proxmox host." >&2
exit 1
fi
if ! command -v pct >/dev/null 2>&1; then
echo "pct not found - this script must run on a Proxmox VE host." >&2
exit 1
fi
if [[ -z "$REPO_SRC" ]]; then
REPO_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
fi
if [[ -z "$TEMPLATE" ]]; then
echo "No --template given, looking up newest debian-* template..."
pveam update >/dev/null
TEMPLATE_FILE="$(pveam available --section system \
| awk '{print $2}' \
| grep -E '^debian-[0-9]+-standard_' \
| sort -V \
| tail -n1)"
if [[ -z "$TEMPLATE_FILE" ]]; then
echo "Could not find any debian-* template via 'pveam available'." >&2
exit 1
fi
if ! pveam list "$STORAGE" | grep -q "$TEMPLATE_FILE"; then
echo "Downloading $TEMPLATE_FILE to storage $STORAGE..."
pveam download "$STORAGE" "$TEMPLATE_FILE"
fi
TEMPLATE="${STORAGE}:vztmpl/${TEMPLATE_FILE}"
echo "Using template: $TEMPLATE"
fi
NET_CONFIG="name=eth0,bridge=${BRIDGE},firewall=1"
if [[ "$IP" == "dhcp" ]]; then
NET_CONFIG="${NET_CONFIG},ip=dhcp"
else
if [[ -z "$GW" ]]; then
echo "--gw is required when --ip is a static CIDR." >&2
exit 1
fi
NET_CONFIG="${NET_CONFIG},ip=${IP},gw=${GW}"
fi
echo "Creating privileged LXC $VMID ($HOSTNAME)..."
pct create "$VMID" "$TEMPLATE" \
--hostname "$HOSTNAME" \
--storage "$STORAGE" \
--rootfs "${STORAGE}:${DISK}" \
--memory "$MEMORY" \
--cores "$CORES" \
--net0 "$NET_CONFIG" \
--unprivileged 0 \
--features "nesting=1,keyctl=1" \
--onboot 1
echo "Enabling /dev/net/tun and WireGuard kernel module passthrough..."
CONF="/etc/pve/lxc/${VMID}.conf"
{
echo "lxc.cgroup2.devices.allow: c 10:200 rwm"
echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file"
} >> "$CONF"
echo "Starting container..."
pct start "$VMID"
sleep 5
echo "Installing base dependencies inside container (Go, git, wireguard-tools, nftables)..."
pct exec "$VMID" -- bash -c "
set -e
apt-get update
apt-get install -y wireguard-tools nftables curl ca-certificates git
if ! command -v go >/dev/null 2>&1; then
ARCH=\$(dpkg --print-architecture)
curl -fsSL https://go.dev/dl/go1.22.5.linux-\${ARCH}.tar.gz -o /tmp/go.tar.gz
tar -C /usr/local -xzf /tmp/go.tar.gz
ln -sf /usr/local/go/bin/go /usr/local/bin/go
rm -f /tmp/go.tar.gz
fi
"
echo "Copying repo into container..."
TMP_TAR="$(mktemp)"
tar -C "$REPO_SRC" -czf "$TMP_TAR" --exclude=.git .
pct push "$VMID" "$TMP_TAR" /tmp/wireguard-ui-multi.tar.gz
rm -f "$TMP_TAR"
pct exec "$VMID" -- bash -c "
set -e
mkdir -p /opt/wireguard-ui-multi-src
tar -C /opt/wireguard-ui-multi-src -xzf /tmp/wireguard-ui-multi.tar.gz
rm -f /tmp/wireguard-ui-multi.tar.gz
"
echo "Running native installer inside container..."
pct exec "$VMID" -- bash -c "
set -e
cd /opt/wireguard-ui-multi-src
go mod tidy
go build -o wireguard-ui-multi ./cmd/wireguard-ui-multi
bash scripts/install.sh
"
echo
echo "Container $VMID ($HOSTNAME) is set up. wireguard-ui-multi is installed but not started."
echo "To enable and start it inside the container, run:"
echo
echo " pct exec $VMID -- systemctl enable --now wireguard-ui-multi.service"
echo
echo "Then check status with:"
echo
echo " pct exec $VMID -- systemctl status wireguard-ui-multi.service"
echo " pct exec $VMID -- journalctl -u wireguard-ui-multi.service -f"