Files
infra-automation/cheatsheets/deploy-linux-vm.md
Infrastructure Team 5ba666dfbf Add quick reference cheatsheets for all playbooks
Cheatsheets created:
- deploy-debian12-vm.md - Basic Debian 12 deployment reference
- deploy-debian-lvm-netinst.md - Network installer with native LVM
- deploy-linux-vm.md - Multi-distribution quick reference
- deploy-linux-vm-lvm.md - Multi-distro with post-config LVM
- deploy-linux-vm-role.md - Role-based deployment guide
- test-deploy-linux-vm-role.md - Testing and validation procedures

Each cheatsheet includes:
- Quick deployment commands
- Variable reference tables
- Tag-based execution examples
- Post-deployment verification steps
- LVM management commands (where applicable)
- Troubleshooting procedures
- Security validation steps
- VM management commands
2025-11-10 22:52:11 +01:00

11 KiB

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

# 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

# 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

# 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

# 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

# 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

# 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)

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)

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)

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)

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

# Get VM IP
ssh grokbox "virsh domifaddr <vm_name>"

# SSH to VM
ssh -J grokbox ansible@<VM_IP>

# Add to ~/.ssh/config
Host myvm
    HostName <VM_IP>
    User ansible
    ProxyJump grokbox
    StrictHostKeyChecking accept-new

VM Management

# Start/Stop
virsh start <vm_name>
virsh shutdown <vm_name>
virsh destroy <vm_name>

# Status
virsh dominfo <vm_name>
virsh list --all

# Autostart
virsh autostart <vm_name>
virsh autostart <vm_name> --disable

# Console access
virsh console <vm_name>

Troubleshooting

Cloud-Init Status

# 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

# Check IP assignment
virsh domifaddr <vm_name>

# 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)

# Check status
getenforce

# View denials
ausearch -m avc -ts recent

# Generate policy
audit2allow -a

Firewall Issues

# Debian/Ubuntu
sudo ufw status verbose
sudo ufw allow <port>

# RHEL/SUSE
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=<service>
sudo firewall-cmd --reload

Package Manager Issues

# Debian/Ubuntu
sudo apt update
sudo apt upgrade
sudo apt-cache search <package>

# RHEL/CentOS/Rocky/Alma
sudo dnf check-update
sudo dnf upgrade
sudo dnf search <package>

# SUSE/openSUSE
sudo zypper refresh
sudo zypper update
sudo zypper search <package>

Image Cache Location

All downloaded cloud images are cached at:

/var/lib/libvirt/images/<distribution>-<version>-*-amd64.qcow2

To update cached images:

# Remove old image
ssh grokbox "rm /var/lib/libvirt/images/<image-name>.qcow2"

# Re-run playbook to download latest
ansible-playbook plays/deploy-linux-vm.yml \
  -e "os_distribution=<distro>" \
  -t download,verify

Manual Download (RHEL/SLES)

For distributions requiring subscriptions:

  1. RHEL: Download from Red Hat Customer Portal

  2. SLES: Download from SUSE Customer Center

  3. Place downloaded image at:

    /var/lib/libvirt/images/<cache_name>
    
  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 <vm_name>
  • IP assigned: virsh domifaddr <vm_name>
  • SSH accessible: ssh -J grokbox ansible@<IP>
  • 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/<vm_name>.qcow2
  • Cloud-Init ISO: /var/lib/libvirt/images/<vm_name>-cloud-init.iso
  • VM Config: /etc/libvirt/qemu/<vm_name>.xml

Emergency Access

If SSH fails, use console:

virsh console <vm_name>

# 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