Last active
June 23, 2026 19:11
-
-
Save SQLDBAWithABeard/7c5746d6069a608a2a52f22cb3cdfa3a to your computer and use it in GitHub Desktop.
proxmox remote dev
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # ===================================================================== | |
| # PROXMOX DEV LXC AUTOMATION SCRIPT | |
| # ===================================================================== | |
| # This script creates two Debian 12 development LXCs: | |
| # | |
| # 1. dev-general → Go, Node, Python, SQL clients | |
| # 2. dev-pwsh → PowerShell 7, SQL clients | |
| # | |
| # SSH KEY INSTRUCTIONS: | |
| # --------------------- | |
| # Create /root/dev-ssh-keys.txt containing either: | |
| # | |
| # - Public keys directly: | |
| # ssh-ed25519 AAAA... rob@laptop | |
| # ssh-ed25519 AAAA... rob@desktop | |
| # | |
| # - OR paths to .pub files: | |
| # /root/.ssh/laptop_id_ed25519.pub | |
| # /root/.ssh/desktop_id_ed25519.pub | |
| # | |
| # One entry per line. The script loads and validates them all. | |
| # | |
| # ===================================================================== | |
| # ---------------- CONFIG ---------------- | |
| TEMPLATE_STORAGE="local" | |
| CT_STORAGE="local-lvm" | |
| DEV_GENERAL_ID=201 | |
| DEV_PWSH_ID=202 | |
| DEV_GENERAL_HOSTNAME="dev-general" | |
| DEV_PWSH_HOSTNAME="dev-pwsh" | |
| DEV_GENERAL_IP="192.168.2.101/24" | |
| DEV_PWSH_IP="192.168.2.102/24" | |
| GATEWAY_IP="192.168.2.34" | |
| DEV_GENERAL_CORES=4 | |
| DEV_GENERAL_MEM=8192 | |
| DEV_PWSH_CORES=4 | |
| DEV_PWSH_MEM=8192 | |
| SSH_KEY_FILE="/root/dev-ssh-keys.txt" | |
| # DNS servers for LXCs | |
| DNS_PRIMARY="1.1.1.1" | |
| DNS_SECONDARY="8.8.8.8" | |
| DNS_FALLBACK="8.8.8.8" | |
| # ---------------- SSH KEY VALIDATION ---------------- | |
| if [ ! -f "$SSH_KEY_FILE" ]; then | |
| echo "ERROR: SSH key file not found at $SSH_KEY_FILE" | |
| exit 1 | |
| fi | |
| echo "Validating SSH keys..." | |
| TMP_KEYFILE=$(mktemp) | |
| while IFS= read -r line; do | |
| CLEANED=$(echo "$line" | tr -d '\r' | xargs || true) | |
| [[ -z "$CLEANED" ]] && continue | |
| # If the line is a path to a file, load that file | |
| if [[ -f "$CLEANED" ]]; then | |
| echo "Loading key from file: $CLEANED" | |
| while IFS= read -r kline; do | |
| K=$(echo "$kline" | tr -d '\r' | xargs || true) | |
| [[ -z "$K" ]] && continue | |
| if echo "$K" | grep -Eq '^(ssh-(rsa|ed25519)|ecdsa-ssh)'; then | |
| echo "$K" >> "$TMP_KEYFILE" | |
| echo "" >> "$TMP_KEYFILE" | |
| else | |
| echo "WARNING: Skipping invalid key in file $CLEANED:" | |
| echo " $kline" | |
| fi | |
| done < "$CLEANED" | |
| continue | |
| fi | |
| # Otherwise treat the line as a key | |
| if echo "$CLEANED" | grep -Eq '^(ssh-(rsa|ed25519)|ecdsa-ssh)'; then | |
| echo "$CLEANED" >> "$TMP_KEYFILE" | |
| echo "" >> "$TMP_KEYFILE" | |
| else | |
| echo "WARNING: Skipping invalid SSH key line:" | |
| echo " $line" | |
| fi | |
| done < "$SSH_KEY_FILE" | |
| if [[ ! -s "$TMP_KEYFILE" ]]; then | |
| echo "ERROR: No valid SSH keys found after processing $SSH_KEY_FILE" | |
| rm -f "$TMP_KEYFILE" | |
| exit 1 | |
| fi | |
| # ---------------- TEMPLATE ---------------- | |
| echo "Ensuring Debian 12 template exists..." | |
| if ! pveam list "$TEMPLATE_STORAGE" | grep -q "debian-12-standard"; then | |
| pveam update | |
| pveam download "$TEMPLATE_STORAGE" debian-12-standard_12.*_amd64.tar.zst | |
| fi | |
| # Extract ONLY the filename (strip storage prefix) | |
| TEMPLATE=$(pveam list "$TEMPLATE_STORAGE" | awk '$1 ~ /debian-12-standard/ {print $1; exit}' | sed 's/.*vztmpl\///') | |
| echo "Using template filename: $TEMPLATE" | |
| # ---------------- CREATE CT FUNCTION ---------------- | |
| create_ct () { | |
| local CTID=$1 | |
| local HOSTNAME=$2 | |
| local IPADDR=$3 | |
| local CORES=$4 | |
| local MEM=$5 | |
| echo "Creating CT $CTID ($HOSTNAME)..." | |
| pct create "$CTID" "$TEMPLATE_STORAGE":vztmpl/"$TEMPLATE" \ | |
| -hostname "$HOSTNAME" \ | |
| -storage "$CT_STORAGE" \ | |
| -rootfs "$CT_STORAGE":20 \ | |
| -memory "$MEM" \ | |
| -cores "$CORES" \ | |
| -nameserver "$DNS_PRIMARY" \ | |
| -swap 512 \ | |
| -net0 "name=eth0,bridge=vmbr0,ip=${IPADDR:-dhcp},gw=$GATEWAY_IP" \ | |
| -unprivileged 1 \ | |
| -features "nesting=1" \ | |
| -password "" \ | |
| -ssh-public-keys "$TMP_KEYFILE" | |
| pct start "$CTID" | |
| } | |
| # ---------------- CREATE LXCs ---------------- | |
| create_ct "$DEV_GENERAL_ID" "$DEV_GENERAL_HOSTNAME" "$DEV_GENERAL_IP" "$DEV_GENERAL_CORES" "$DEV_GENERAL_MEM" | |
| create_ct "$DEV_PWSH_ID" "$DEV_PWSH_HOSTNAME" "$DEV_PWSH_IP" "$DEV_PWSH_CORES" "$DEV_PWSH_MEM" | |
| # ---------------- BOOTSTRAP SCRIPTS ---------------- | |
| bootstrap_dev_general () { | |
| local CTID=$1 | |
| echo "Bootstrapping dev-general ($CTID)..." | |
| pct exec "$CTID" -- bash -lc " | |
| set -e | |
| apt update && apt upgrade -y | |
| # DNS configuration | |
| echo '[Resolve]' > /etc/systemd/resolved.conf | |
| echo 'DNS=${DNS_PRIMARY} ${DNS_SECONDARY}' >> /etc/systemd/resolved.conf | |
| echo 'FallbackDNS=${DNS_FALLBACK}' >> /etc/systemd/resolved.conf | |
| systemctl enable systemd-resolved | |
| systemctl restart systemd-resolved | |
| ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf | |
| apt install -y curl git build-essential ca-certificates | |
| apt install -y golang | |
| curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - | |
| apt install -y nodejs | |
| apt install -y python3 python3-pip python3-venv | |
| apt install -y postgresql-client mariadb-client | |
| curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - | |
| curl https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list | |
| apt update | |
| ACCEPT_EULA=Y apt install -y mssql-tools18 unixodbc-dev | |
| echo 'export PATH=\"\$PATH:/opt/mssql-tools18/bin\"' >> /root/.bashrc | |
| " | |
| } | |
| bootstrap_dev_pwsh () { | |
| local CTID=$1 | |
| echo "Bootstrapping dev-pwsh ($CTID)..." | |
| pct exec "$CTID" -- bash -lc " | |
| set -e | |
| apt update && apt upgrade -y | |
| # DNS configuration | |
| echo '[Resolve]' > /etc/systemd/resolved.conf | |
| echo 'DNS=${DNS_PRIMARY} ${DNS_SECONDARY}' >> /etc/systemd/resolved.conf | |
| echo 'FallbackDNS=${DNS_FALLBACK}' >> /etc/systemd/resolved.conf | |
| systemctl enable systemd-resolved | |
| systemctl restart systemd-resolved | |
| ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf | |
| apt install -y wget apt-transport-https software-properties-common curl git ca-certificates | |
| wget https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O /tmp/packages-microsoft-prod.deb | |
| dpkg -i /tmp/packages-microsoft-prod.deb | |
| apt update | |
| apt install -y powershell | |
| curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - | |
| curl https://packages.microsoft.com/config/debian/12/prod.list > /etc/apt/sources.list.d/mssql-release.list | |
| apt update | |
| ACCEPT_EULA=Y apt install -y mssql-tools18 unixodbc-dev | |
| echo 'export PATH=\"\$PATH:/opt/mssql-tools18/bin\"' >> /root/.bashrc | |
| apt install -y postgresql-client mariadb-client | |
| " | |
| } | |
| bootstrap_dev_general "$DEV_GENERAL_ID" | |
| bootstrap_dev_pwsh "$DEV_PWSH_ID" | |
| rm -f "$TMP_KEYFILE" | |
| echo "============================================================" | |
| echo " DONE!" | |
| echo "" | |
| echo " LXCs created:" | |
| echo " - dev-general → $DEV_GENERAL_ID ($DEV_GENERAL_IP)" | |
| echo " - dev-pwsh → $DEV_PWSH_ID ($DEV_PWSH_IP)" | |
| echo "" | |
| echo " Add to ~/.ssh/config on your laptop/desktop:" | |
| echo "" | |
| echo " Host dev-general" | |
| echo " HostName ${DEV_GENERAL_IP%/*}" | |
| echo " User root" | |
| echo "" | |
| echo " Host dev-pwsh" | |
| echo " HostName ${DEV_PWSH_IP%/*}" | |
| echo " User root" | |
| echo "" | |
| echo " Then connect via VS Code Remote-SSH." | |
| echo "============================================================" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Elementary, my dear Watson." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment