Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save SQLDBAWithABeard/7c5746d6069a608a2a52f22cb3cdfa3a to your computer and use it in GitHub Desktop.

Select an option

Save SQLDBAWithABeard/7c5746d6069a608a2a52f22cb3cdfa3a to your computer and use it in GitHub Desktop.
proxmox remote dev
#!/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 "============================================================"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment