homelab/proxmox/adder/create-debian-template.sh
Samantha Atkins 759ef949bc K3s cluster on Proxmox with WireGuard mesh networking
Replaced Headscale (too buggy in 0.28.x — random node drops) with direct
WireGuard hub-and-spoke + full mesh. 7 Proxmox VMs across 3 hosts form a
K3s v1.34.6 cluster: 3 control-plane/etcd nodes, 4 workers.

Running services: postgres, mariadb, ghost (x3), forgejo, authentik.
All unpinned services use local-path StorageClass. Databases pinned to
pve-worker and adder-worker with local PVs.

Includes VM provisioning scripts (create-debian-template.sh, clone-vm.sh),
K3s manifests for all services, and full deployment docs in k3s/README.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 01:23:13 -04:00

80 lines
3.1 KiB
Bash

#!/bin/bash
# create-debian-template.sh
# Creates a Debian Trixie Cloud-Init VM template on Proxmox.
#
# Usage:
# ./create-debian-template.sh <VMID> <n> [STORAGE] [BRIDGE]
#
# Examples:
# ./create-debian-template.sh 9000 debian-trixie-template
# ./create-debian-template.sh 9000 debian-trixie-template local-lvm vmbr1
#
# Defaults:
# STORAGE = local-lvm
# BRIDGE = vmbr1
set -euo pipefail
VMID="${1:?Usage: $0 <VMID> <n> [STORAGE] [BRIDGE]}"
NAME="${2:?Usage: $0 <VMID> <n> [STORAGE] [BRIDGE]}"
STORAGE="${3:-local-lvm}"
BRIDGE="${4:-vmbr1}"
IMAGE="debian-13-genericcloud-amd64.qcow2"
IMAGE_URL="https://cloud.debian.org/images/cloud/trixie/latest/${IMAGE}"
TMPDIR="/tmp"
echo "==> Downloading Debian Trixie cloud image..."
wget -q --show-progress -O "${TMPDIR}/${IMAGE}" "${IMAGE_URL}"
echo "==> Installing libguestfs-tools if needed..."
apt-get install -y libguestfs-tools > /dev/null
echo "==> Customizing image (installing base tools + Tailscale repo)..."
virt-customize -a "${TMPDIR}/${IMAGE}" \
--install qemu-guest-agent,curl,wget,nano,rsync,htop,tmux,emacs-nox,nfs-common \
--run-command 'curl -fsSL https://pkgs.tailscale.com/stable/debian/trixie.noarmor.gpg -o /usr/share/keyrings/tailscale-archive-keyring.gpg' \
--run-command 'echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/debian trixie main" > /etc/apt/sources.list.d/tailscale.list' \
--run-command 'apt-get update -qq' \
--install tailscale \
--run-command 'mkdir -p /home/samantha/.ssh && echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPJq4fOOrPQKYAq5olwKWAXKGO5zv/rujveyTORxMrDp root@pve" > /home/samantha/.ssh/authorized_keys && chmod 700 /home/samantha/.ssh && chmod 600 /home/samantha/.ssh/authorized_keys' \
--run-command 'chown -R samantha:samantha /home/samantha' \
--run-command 'truncate -s 0 /etc/machine-id' \
--run-command 'rm -f /etc/ssh/ssh_host_*' \
--quiet
echo "==> Creating VM ${VMID} (${NAME})..."
qm create "${VMID}" \
--name "${NAME}" \
--memory 2048 \
--cores 2 \
--net0 "virtio,bridge=${BRIDGE}" \
--ostype l26
echo "==> Importing disk to ${STORAGE}..."
qm importdisk "${VMID}" "${TMPDIR}/${IMAGE}" "${STORAGE}"
echo "==> Configuring VM..."
qm set "${VMID}" --scsihw virtio-scsi-pci --scsi0 "${STORAGE}:vm-${VMID}-disk-0"
qm set "${VMID}" --boot c --bootdisk scsi0
qm set "${VMID}" --ide2 "${STORAGE}:cloudinit"
qm set "${VMID}" --vga std
qm set "${VMID}" --agent enabled=1
PUBKEY_FILE=$(mktemp)
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPJq4fOOrPQKYAq5olwKWAXKGO5zv/rujveyTORxMrDp root@pve" > "${PUBKEY_FILE}"
qm set "${VMID}" --ciuser samantha --cipassword "changeme" --sshkeys "${PUBKEY_FILE}"
rm -f "${PUBKEY_FILE}"
qm set "${VMID}" --ipconfig0 ip=dhcp
echo "==> Converting to template..."
qm template "${VMID}"
echo "==> Cleaning up..."
rm -f "${TMPDIR}/${IMAGE}"
echo ""
echo "Done. Template ${VMID} (${NAME}) created."
echo "Clone with: ./clone-vm.sh ${VMID} <NEW_VMID> <NEW_NAME> [CORES] [MEMORY_MB] [DISK_SIZE]"
echo ""
echo "After cloning, join the Headscale mesh:"
echo " tailscale up --login-server <headscale_server> --authkey mkey:..."