All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
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>
9.1 KiB
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 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