- Update patterns/vm-management/README.md: Add comprehensive automation workflows - Cloud-init deployment strategies and post-install automation - SSH key management integration and security hardening patterns - Implementation workflows for new and existing VM provisioning - Add complete VM management examples and reference documentation - examples/vm-management/: Proxmox automation and provisioning examples - reference/vm-management/: Troubleshooting guides and best practices - scripts/vm-management/: Operational scripts for automated VM setup - Update reference/docker/tdarr-monitoring-configuration.md: API monitoring integration - Document new tdarr_monitor.py integration with existing Discord monitoring - Add API-based health checks and cron scheduling examples - Enhanced gaming scheduler integration with health verification - Update Tdarr operational scripts with stability improvements - scripts/tdarr/start-tdarr-gpu-podman-clean.sh: Resource limits and CDI GPU access - scripts/tdarr/tdarr-schedule-manager.sh: Updated container name references - scripts/monitoring/tdarr-timeout-monitor.sh: Enhanced completion monitoring 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
8.7 KiB
8.7 KiB
Proxmox VM Automation - Complete Examples
Complete working examples for automated VM provisioning in Proxmox environments using cloud-init and post-installation scripts.
Overview
This guide provides real-world examples for automating Ubuntu Server VM deployment with:
- SSH key-based authentication
- Docker environment setup
- Security hardening
- System updates and maintenance
Example 1: Cloud-Init VM Creation
Proxmox VM Setup
# Create VM with cloud-init support in Proxmox
# VM ID: 200, Name: homelab-docker-01, IP: 10.10.0.200
# 1. Create VM through Proxmox web interface or CLI
pvesh create /nodes/pve/qemu -vmid 200 -name homelab-docker-01 \
-memory 2048 -cores 2 -sockets 1 -cpu cputype=host \
-net0 virtio,bridge=vmbr0 \
-ide2 local:cloudinit \
-boot c -bootdisk scsi0 \
-scsi0 local-lvm:10 \
-ostype l26
Cloud-Init Configuration
Use the complete cloud-init-user-data.yaml template:
#cloud-config
hostname: homelab-docker-01
timezone: America/New_York
users:
- name: cal
groups: [sudo, docker]
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDVVK02rOeeIw1e... homelab-cal@nobara-pc
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCPzqHDgdK9TlN4uzumBZKEOGt... emergency-homelab-cal@nobara-pc
ssh_pwauth: false
disable_root: true
package_update: true
package_upgrade: true
# Docker installation and configuration...
# (Full template available in scripts/vm-management/cloud-init-user-data.yaml)
Deployment Process
- Create VM with cloud-init drive attached
- Paste cloud-init config into User Data field
- Set network configuration (IP: 10.10.0.200/24, Gateway: 10.10.0.1)
- Start VM - automatic provisioning begins
- Wait 3-5 minutes for first boot provisioning
- Test connectivity:
ssh cal@10.10.0.200
Example 2: Post-Installation Script
Scenario: Existing VM Needs Provisioning
# VM already exists at 10.10.0.150 with password authentication
# Need to configure SSH keys, Docker, and security hardening
# Run the post-installation script
cd /mnt/NV2/Development/claude-home
./scripts/vm-management/vm-post-install.sh 10.10.0.150 cal
Script Execution Flow
🔐 Starting VM provisioning for 10.10.0.150 as user cal
✅ System updates completed
✅ SSH key authentication successful
✅ SSH hardened (password authentication disabled)
✅ Docker and Docker Compose installed successfully
✅ User environment configured
🎉 VM provisioning completed successfully!
=== PROVISIONING SUMMARY ===
VM IP: 10.10.0.150
User: cal
Hostname: homelab-vm-03
Docker: Docker version 24.0.7, build afdd53b
Example 3: Bulk VM Provisioning
Multiple VM Deployment Script
#!/bin/bash
# Bulk VM provisioning for home lab expansion
# Creates and configures multiple VMs with sequential IPs
VM_BASE_ID=300
VM_BASE_IP="10.10.0"
VM_COUNT=3
for i in $(seq 1 $VM_COUNT); do
VM_ID=$((VM_BASE_ID + i))
VM_IP="${VM_BASE_IP}.$((200 + i))"
VM_NAME="homelab-worker-$(printf "%02d" $i)"
echo "Creating VM: $VM_NAME (ID: $VM_ID, IP: $VM_IP)"
# Create VM in Proxmox (adapt to your environment)
pvesh create /nodes/pve/qemu -vmid $VM_ID -name $VM_NAME \
-memory 2048 -cores 2 \
-net0 virtio,bridge=vmbr0 \
-ide2 local:cloudinit \
-scsi0 local-lvm:20
# Set cloud-init configuration
pvesh set /nodes/pve/qemu/$VM_ID/config \
-ipconfig0 ip=$VM_IP/24,gw=10.10.0.1 \
-nameserver 10.10.0.16 \
-user cal \
-sshkeys /path/to/encoded/ssh-keys
# Start VM
pvesh create /nodes/pve/qemu/$VM_ID/status/start
echo "VM $VM_NAME created and starting..."
sleep 30 # Wait for boot
done
echo "Bulk provisioning completed. VMs available at:"
for i in $(seq 1 $VM_COUNT); do
echo " homelab-worker-$(printf "%02d" $i): ${VM_BASE_IP}.$((200 + i))"
done
Example 4: Docker Service Deployment
Post-Provisioning Service Setup
After VM provisioning, deploy services using Docker Compose:
# Connect to newly provisioned VM
ssh cal@10.10.0.200
# Create service directory
mkdir -p ~/services/nginx-proxy
cd ~/services/nginx-proxy
# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./config:/etc/nginx/conf.d:ro
- ./ssl:/etc/nginx/ssl:ro
restart: unless-stopped
portainer:
image: portainer/portainer-ce:latest
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
restart: unless-stopped
volumes:
portainer_data:
EOF
# Deploy services
docker compose up -d
docker compose logs -f
Example 5: VM Template Creation
Creating Reusable VM Templates
# 1. Create and fully configure a base VM
./scripts/vm-management/vm-post-install.sh 10.10.0.199 cal
# 2. Clean up the VM for template use
ssh cal@10.10.0.199 '
# Clear bash history
history -c && history -w
# Clear logs
sudo truncate -s 0 /var/log/*log
sudo truncate -s 0 /var/log/syslog
# Clear SSH host keys (regenerated on first boot)
sudo rm -f /etc/ssh/ssh_host_*
# Clear machine ID
sudo truncate -s 0 /etc/machine-id
# Clear network configuration
sudo rm -f /etc/udev/rules.d/70-persistent-net.rules
# Shutdown
sudo shutdown -h now
'
# 3. Convert VM to template in Proxmox
pvesh create /nodes/pve/qemu/199/template
# 4. Clone template to create new VMs
pvesh create /nodes/pve/qemu/199/clone -newid 201 -name homelab-from-template
Example 6: Monitoring and Verification
Post-Deployment Health Checks
#!/bin/bash
# VM health check script
# Usage: ./vm-health-check.sh <vm-ip>
VM_IP="$1"
echo "🔍 VM Health Check: $VM_IP"
# Test SSH connectivity
if ssh -o ConnectTimeout=5 cal@$VM_IP 'echo "SSH OK"' >/dev/null 2>&1; then
echo "✅ SSH: Connected"
else
echo "❌ SSH: Failed"
exit 1
fi
# Check system info
INFO=$(ssh cal@$VM_IP '
echo "Hostname: $(hostname)"
echo "Uptime: $(uptime -p)"
echo "Memory: $(free -h | grep Mem | awk "{print \$3\"/\"\$2}")"
echo "Disk: $(df -h / | tail -1 | awk "{print \$3\"/\"\$2\" (\"\$5\" used)\"}")"
')
echo "$INFO"
# Test Docker
if ssh cal@$VM_IP 'docker --version && docker compose version' >/dev/null 2>&1; then
echo "✅ Docker: Installed and working"
else
echo "❌ Docker: Not working"
fi
# Test Docker permissions
if ssh cal@$VM_IP 'docker run --rm hello-world' >/dev/null 2>&1; then
echo "✅ Docker: User permissions OK"
else
echo "❌ Docker: User permissions issue"
fi
echo "🎉 Health check completed"
Common Workflows
1. New Development Environment
# Create VM with cloud-init
# Wait for provisioning
# Deploy development stack
ssh cal@10.10.0.201 '
mkdir -p ~/dev
cd ~/dev
# Clone your project
git clone https://github.com/your-org/project.git
cd project
# Start development environment
docker compose -f docker-compose.dev.yml up -d
'
2. Service Migration
# Provision new VM
./scripts/vm-management/vm-post-install.sh 10.10.0.202 cal
# Copy service configuration from existing server
scp -r cal@10.10.0.124:~/services/app-name cal@10.10.0.202:~/services/
# Start service on new VM
ssh cal@10.10.0.202 'cd ~/services/app-name && docker compose up -d'
3. Testing Environment
# Quick test environment with cloud-init
# Use minimal resources: 1GB RAM, 1 CPU, 10GB disk
# Deploy test configuration
# Run automated tests
# Destroy when done
Troubleshooting Examples
VM Won't Start After Cloud-Init
# Check cloud-init logs
ssh cal@<vm-ip> 'sudo cloud-init status --long'
ssh cal@<vm-ip> 'sudo cat /var/log/cloud-init-output.log'
# Manual cloud-init re-run if needed
ssh cal@<vm-ip> 'sudo cloud-init clean && sudo cloud-init init'
SSH Key Issues
# Verify keys are properly installed
ssh cal@<vm-ip> 'cat ~/.ssh/authorized_keys | wc -l' # Should show 2 keys
# Test specific key
ssh -i ~/.ssh/homelab_rsa cal@<vm-ip> 'echo "Primary key works"'
ssh -i ~/.ssh/emergency_homelab_rsa cal@<vm-ip> 'echo "Emergency key works"'
Docker Permission Problems
# Check user groups
ssh cal@<vm-ip> 'groups' # Should include 'docker'
# Re-login to apply group membership
ssh cal@<vm-ip> 'newgrp docker'
# Test Docker access
ssh cal@<vm-ip> 'docker ps'
Related Documentation
- Scripts:
scripts/vm-management/README.md- Implementation details - Patterns:
patterns/vm-management/README.md- Architectural guidance - SSH Setup:
examples/networking/ssh-homelab-setup.md- Key management - Docker:
examples/docker/- Container deployment patterns