# Multi-Distribution Linux VM Deployment Cheatsheet ## Supported Distributions ### Debian Family - Debian 11 (Bullseye) - Debian 12 (Bookworm) - Ubuntu 20.04 LTS (Focal) - Ubuntu 22.04 LTS (Jammy) - Ubuntu 24.04 LTS (Noble) ### RHEL Family - RHEL 8, 9 (requires subscription) - CentOS Stream 8, 9 - Rocky Linux 8, 9 - AlmaLinux 8, 9 ### SUSE Family - SLES 15 (requires subscription) - openSUSE Leap 15.5, 15.6 ## Quick Deployment ### Debian/Ubuntu ```bash # Debian 12 ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=debian-12" \ -e "vm_name=debian12-vm" # Ubuntu 22.04 LTS ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-22.04" \ -e "vm_name=ubuntu22-vm" # Ubuntu 24.04 LTS ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-24.04" \ -e "vm_name=ubuntu24-vm" ``` ### RHEL Family ```bash # CentOS Stream 9 ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=centos-stream-9" \ -e "vm_name=centos9-vm" # Rocky Linux 9 ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=rocky-9" \ -e "vm_name=rocky9-vm" # AlmaLinux 9 ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=almalinux-9" \ -e "vm_name=alma9-vm" ``` ### SUSE Family ```bash # openSUSE Leap 15.6 ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=opensuse-leap-15.6" \ -e "vm_name=opensuse-vm" ``` ## Custom Resource Allocation ```bash # High-performance VM ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=rocky-9" \ -e "vm_name=app-server" \ -e "vm_vcpus=8" \ -e "vm_memory_mb=16384" \ -e "vm_disk_size_gb=100" # Development VM ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-22.04" \ -e "vm_name=dev-box" \ -e "vm_vcpus=4" \ -e "vm_memory_mb=8192" \ -e "vm_disk_size_gb=50" # Minimal VM ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=debian-12" \ -e "vm_name=test-vm" \ -e "vm_vcpus=1" \ -e "vm_memory_mb=1024" \ -e "vm_disk_size_gb=10" ``` ## Custom Configuration ```bash # Custom hostname and domain ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=centos-stream-9" \ -e "vm_name=web-server" \ -e "vm_hostname=webserver01" \ -e "vm_domain=production.local" # Custom SSH key ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-24.04" \ -e "vm_name=secure-vm" \ -e "ansible_user_ssh_key='ssh-ed25519 AAAA...'" # Custom network ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=rocky-9" \ -e "vm_name=isolated-vm" \ -e "vm_network=isolated" \ -e "vm_bridge=virbr1" ``` ## Tag-Based Execution ```bash # Pre-flight checks only ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=debian-12" \ -t preflight,validate # Download and verify image only ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-22.04" \ -t download,verify # Create storage only ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=rocky-9" \ -e "vm_name=myvm" \ -t storage # Generate cloud-init config only ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=centos-stream-9" \ -e "vm_name=myvm" \ -t cloud-init # Deploy VM (assumes image downloaded) ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=almalinux-9" \ -e "vm_name=myvm" \ -t deploy # Validation only ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=debian-12" \ -e "vm_name=myvm" \ -t validate # Cleanup temporary files ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-24.04" \ -e "vm_name=myvm" \ -t cleanup ``` ## Required Variables | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `os_distribution` | **YES** | debian-12 | Distribution identifier | | `vm_name` | No | linux-guest | VM name in libvirt | | `vm_hostname` | No | linux-vm | VM hostname | | `vm_domain` | No | localdomain | Domain name | | `vm_vcpus` | No | 2 | Number of vCPUs | | `vm_memory_mb` | No | 2048 | RAM in MB | | `vm_disk_size_gb` | No | 20 | Disk size in GB | | `vm_network` | No | default | Libvirt network | | `ansible_user_ssh_key` | No | (predefined) | SSH public key | ## Distribution Identifiers ``` Debian: - debian-11 - debian-12 Ubuntu: - ubuntu-20.04 - ubuntu-22.04 - ubuntu-24.04 RHEL Family: - rhel-8 (manual download) - rhel-9 (manual download) - centos-stream-8 - centos-stream-9 - rocky-8 - rocky-9 - almalinux-8 - almalinux-9 SUSE Family: - sles-15 (manual download) - opensuse-leap-15.5 - opensuse-leap-15.6 ``` ## Distribution-Specific Features ### Debian/Ubuntu - Package Manager: `apt` - Firewall: `ufw` - Automatic Updates: `unattended-upgrades` - User Group: `sudo` ### RHEL/CentOS/Rocky/Alma - Package Manager: `dnf` - Firewall: `firewalld` - Automatic Updates: `dnf-automatic` - SELinux: Enforcing mode - User Group: `wheel` ### SUSE/openSUSE - Package Manager: `zypper` - Firewall: `firewalld` - User Group: `wheel` ## Common Use Cases ### Deploy Database Server (Rocky Linux) ```bash ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=rocky-9" \ -e "vm_name=db-server" \ -e "vm_hostname=postgres01" \ -e "vm_vcpus=4" \ -e "vm_memory_mb=8192" \ -e "vm_disk_size_gb=100" ``` ### Deploy Web Server (Ubuntu) ```bash ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=ubuntu-22.04" \ -e "vm_name=web-server" \ -e "vm_hostname=nginx01" \ -e "vm_vcpus=2" \ -e "vm_memory_mb=4096" \ -e "vm_disk_size_gb=40" ``` ### Deploy Container Host (CentOS Stream) ```bash ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=centos-stream-9" \ -e "vm_name=container-host" \ -e "vm_hostname=podman01" \ -e "vm_vcpus=6" \ -e "vm_memory_mb=12288" \ -e "vm_disk_size_gb=80" ``` ### Deploy Development VM (Debian) ```bash ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=debian-12" \ -e "vm_name=dev-vm" \ -e "vm_hostname=devbox" \ -e "vm_vcpus=4" \ -e "vm_memory_mb=8192" \ -e "vm_disk_size_gb=50" ``` ## Post-Deployment ### Access VM ```bash # Get VM IP ssh grokbox "virsh domifaddr " # SSH to VM ssh -J grokbox ansible@ # Add to ~/.ssh/config Host myvm HostName User ansible ProxyJump grokbox StrictHostKeyChecking accept-new ``` ### VM Management ```bash # Start/Stop virsh start virsh shutdown virsh destroy # Status virsh dominfo virsh list --all # Autostart virsh autostart virsh autostart --disable # Console access virsh console ``` ## Troubleshooting ### Cloud-Init Status ```bash # On VM cloud-init status cloud-init status --wait cloud-init status --long # Logs tail -f /var/log/cloud-init-output.log journalctl -u cloud-init ``` ### Network Issues ```bash # Check IP assignment virsh domifaddr # Check libvirt network virsh net-list virsh net-dhcp-leases default # Restart network (on hypervisor) virsh net-destroy default virsh net-start default ``` ### SELinux Issues (RHEL Family) ```bash # Check status getenforce # View denials ausearch -m avc -ts recent # Generate policy audit2allow -a ``` ### Firewall Issues ```bash # Debian/Ubuntu sudo ufw status verbose sudo ufw allow # RHEL/SUSE sudo firewall-cmd --list-all sudo firewall-cmd --permanent --add-service= sudo firewall-cmd --reload ``` ### Package Manager Issues ```bash # Debian/Ubuntu sudo apt update sudo apt upgrade sudo apt-cache search # RHEL/CentOS/Rocky/Alma sudo dnf check-update sudo dnf upgrade sudo dnf search # SUSE/openSUSE sudo zypper refresh sudo zypper update sudo zypper search ``` ## Image Cache Location All downloaded cloud images are cached at: ``` /var/lib/libvirt/images/--*-amd64.qcow2 ``` To update cached images: ```bash # Remove old image ssh grokbox "rm /var/lib/libvirt/images/.qcow2" # Re-run playbook to download latest ansible-playbook plays/deploy-linux-vm.yml \ -e "os_distribution=" \ -t download,verify ``` ## Manual Download (RHEL/SLES) For distributions requiring subscriptions: 1. **RHEL**: Download from Red Hat Customer Portal - Location: https://access.redhat.com/downloads/ - Product: Red Hat Enterprise Linux - Type: KVM Guest Image 2. **SLES**: Download from SUSE Customer Center - Location: https://scc.suse.com/ - Product: SUSE Linux Enterprise Server - Type: Cloud Image 3. Place downloaded image at: ``` /var/lib/libvirt/images/ ``` 4. Run deployment playbook normally ## Security Features All deployed VMs include: ✅ **User Management** - ansible user with passwordless sudo - SSH key-based authentication only - Root login disabled via SSH ✅ **Firewall** (enabled and configured) - Debian/Ubuntu: UFW - RHEL/SUSE: firewalld ✅ **Automatic Updates** - Debian/Ubuntu: unattended-upgrades - RHEL: dnf-automatic - Security updates only, no auto-reboot ✅ **Security Hardening** - RHEL: SELinux enforcing - Audit daemon enabled - Secure SSH configuration - Time synchronization (chrony) ✅ **Essential Packages** - System tools: vim, htop, tmux - Network tools: curl, wget, rsync - Development: git, python3 - Security: aide, auditd ## Validation Checklist After deployment: - [ ] VM running: `virsh list | grep ` - [ ] IP assigned: `virsh domifaddr ` - [ ] SSH accessible: `ssh -J grokbox ansible@` - [ ] Cloud-init complete: `cloud-init status` - [ ] Firewall enabled: `sudo ufw status` or `sudo firewall-cmd --state` - [ ] Updates configured: Check respective service - [ ] SELinux enforcing (RHEL): `getenforce` - [ ] Time sync: `chronyc tracking` - [ ] Audit daemon: `systemctl status auditd` ## Quick Reference ### Deployment Workflow 1. **Validate** → Check distribution and VM name 2. **Install** → Install required packages on hypervisor 3. **Download** → Download distribution cloud image 4. **Verify** → Validate image checksums 5. **Storage** → Create VM disk from cloud image 6. **Cloud-Init** → Generate configuration for OS family 7. **Deploy** → Create and start VM with virt-install 8. **Validate** → Verify SSH and system status 9. **Cleanup** → Remove temporary files ### Important Paths - Cloud Images: `/var/lib/libvirt/images/*.qcow2` - VM Disks: `/var/lib/libvirt/images/.qcow2` - Cloud-Init ISO: `/var/lib/libvirt/images/-cloud-init.iso` - VM Config: `/etc/libvirt/qemu/.xml` ### Emergency Access If SSH fails, use console: ```bash virsh console # Login as root with password: ChangeMe123! # (Change this immediately!) ``` ## Support - Documentation: `docs/linux-vm-deployment.md` - Playbook: `plays/deploy-linux-vm.yml` - Guidelines: `CLAUDE.md`