claude-home/vm-management/examples/proxmox-automation.md
Cal Corum 4b7eca8a46
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
docs: add YAML frontmatter to all 151 markdown files
Adds title, description, type, domain, and tags frontmatter to every
doc for improved KB semantic search. The description field is prepended
to every search chunk, and domain/type/tags enable filtered queries.

Type values: context, guide, runbook, reference, troubleshooting
Domain values match directory structure (networking, docker, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:00:44 -05:00

9.1 KiB

title description type domain tags
Proxmox Automation Examples Working examples for Proxmox VM automation: cloud-init deployment, post-install scripting, bulk provisioning, Docker service deployment, VM template creation, and health check scripts. reference vm-management
proxmox
automation
cloud-init
docker
templates
examples

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

  1. Create VM with cloud-init drive attached
  2. Paste cloud-init config into User Data field
  3. Set network configuration (IP: 10.10.0.200/24, Gateway: 10.10.0.1)
  4. Start VM - automatic provisioning begins
  5. Wait 3-5 minutes for first boot provisioning
  6. 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'
  • 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