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
This commit is contained in:
Infrastructure Team
2025-11-10 22:52:11 +01:00
parent 04a381e0d5
commit 5ba666dfbf
7 changed files with 2491 additions and 0 deletions

View File

@@ -0,0 +1,380 @@
# Deploy Debian with LVM Network Installer - Quick Reference
## Playbook
`plays/deploy-debian-lvm-netinst.yml`
## Description
Advanced Debian deployment using network installer (netinst) with full LVM configuration. This playbook creates a VM with proper LVM partitioning per CLAUDE.md requirements using preseed for unattended installation.
## Quick Deployment
### Basic Usage
```bash
ansible-playbook plays/deploy-debian-lvm-netinst.yml
```
### Custom Configuration
```bash
ansible-playbook plays/deploy-debian-lvm-netinst.yml \
-e "vm_name=debian-lvm-server" \
-e "vm_hostname=db-server" \
-e "vm_vcpus=4" \
-e "vm_memory_mb=8192" \
-e "vm_disk_size_gb=100"
```
## Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `vm_name` | debian-lvm-guest | VM name in libvirt |
| `vm_hostname` | debian-lvm | VM hostname |
| `vm_domain` | localdomain | Domain name |
| `vm_vcpus` | 2 | Number of vCPUs |
| `vm_memory_mb` | 4096 | RAM in MB (needs 4GB for installer) |
| `vm_disk_size_gb` | 50 | Disk size in GB |
| `vm_network` | default | Libvirt network |
| `debian_version` | 12 | Debian version (11 or 12) |
| `debian_mirror` | deb.debian.org | Debian mirror URL |
## LVM Configuration (CLAUDE.md Compliant)
This playbook creates the following LVM layout:
```
Physical Volume: /dev/vda2
Volume Group: vg_system
Logical Volumes:
├── lv_root 8G /
├── lv_opt 3G /opt
├── lv_tmp 1G /tmp (noexec,nosuid,nodev)
├── lv_home 2G /home
├── lv_var 5G /var
├── lv_var_log 2G /var/log
├── lv_var_tmp 5G /var/tmp (noexec,nosuid,nodev)
├── lv_var_audit 1G /var/log/audit
└── lv_swap 2G swap
Separate partition:
└── /dev/vda1 2G /boot (ext4)
```
## Tag-Based Execution
```bash
# Pre-flight checks only
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags preflight
# Download netinst ISO only
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags download
# Generate preseed configuration only
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags preseed
# Deploy VM (assumes ISO downloaded)
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags deploy
# Validation only
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags validate
```
### Available Tags
- `preflight` - Pre-flight validation
- `install` - Install required packages
- `download` - Download Debian netinst ISO
- `preseed` - Generate preseed configuration
- `storage` - Create VM disk
- `deploy` - Deploy and start VM
- `validate` - Post-installation validation
- `cleanup` - Remove temporary files
## Installation Process
### Timeline
1. **Download ISO**: ~5 minutes (depending on connection)
2. **VM Creation**: ~1 minute
3. **OS Installation**: ~15-20 minutes (unattended)
4. **Total Time**: ~20-25 minutes
### Monitoring Installation
```bash
# Watch VM console during installation
ssh grokbox "virsh console debian-lvm-guest"
# Check VM status
ssh grokbox "virsh list --all"
# Monitor from VNC (if available)
ssh grokbox "virsh vncdisplay debian-lvm-guest"
```
## Post-Installation
### Wait for Completion
The installation is fully unattended. Wait for:
- Playbook to complete (deployment task will wait 20 minutes)
- VM to reboot automatically
- SSH service to become available
### Get VM Information
```bash
# Get VM IP
ssh grokbox "virsh domifaddr debian-lvm-guest"
# VM details
ssh grokbox "virsh dominfo debian-lvm-guest"
```
### Access VM
```bash
# SSH via ProxyJump
ssh -J grokbox ansible@<VM_IP>
# Add to ~/.ssh/config
Host debian-lvm
HostName <VM_IP>
User ansible
ProxyJump grokbox
StrictHostKeyChecking accept-new
```
### Verify LVM Configuration
```bash
# SSH to VM
ssh -J grokbox ansible@<VM_IP>
# Check physical volumes
sudo pvs
# Check volume groups
sudo vgs
# Check logical volumes
sudo lvs
# Check mounts
df -h
lsblk
# Verify fstab
cat /etc/fstab
```
Expected output:
```
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 2G 0 part /boot
└─vda2 252:2 0 48G 0 part
├─vg_system-lv_root 254:0 0 8G 0 lvm /
├─vg_system-lv_opt 254:1 0 3G 0 lvm /opt
├─vg_system-lv_tmp 254:2 0 1G 0 lvm /tmp
├─vg_system-lv_home 254:3 0 2G 0 lvm /home
├─vg_system-lv_var 254:4 0 5G 0 lvm /var
├─vg_system-lv_var_log 254:5 0 2G 0 lvm /var/log
├─vg_system-lv_var_tmp 254:6 0 5G 0 lvm /var/tmp
├─vg_system-lv_var_audit 254:7 0 1G 0 lvm /var/log/audit
└─vg_system-lv_swap 254:8 0 2G 0 lvm [SWAP]
```
## Security Features
### Preseed Configuration Includes
- Minimal installation (no desktop environment)
- Automatic partitioning with LVM
- Security hardening:
- SSH server installed
- Root password set (change after deployment!)
- ansible user with sudo access
- SSH key authentication configured
- UFW firewall enabled
- Automatic security updates
### Post-Installation Security Tasks
```bash
# Change root password
ssh -J grokbox ansible@<VM_IP>
sudo passwd root
# Verify SSH configuration
sudo cat /etc/ssh/sshd_config | grep -E 'PermitRoot|PasswordAuth'
# Check firewall
sudo ufw status verbose
# Verify automatic updates
sudo dpkg -l | grep unattended-upgrades
```
## LVM Management
### Extend Logical Volumes
```bash
# Extend lv_var by 5GB
sudo lvextend -L +5G /dev/vg_system/lv_var
sudo resize2fs /dev/vg_system/lv_var
# Extend lv_var to use all free space
sudo lvextend -l +100%FREE /dev/vg_system/lv_var
sudo resize2fs /dev/vg_system/lv_var
```
### Create New Logical Volumes
```bash
# Create new LV for application data
sudo lvcreate -L 10G -n lv_app_data vg_system
sudo mkfs.ext4 /dev/vg_system/lv_app_data
sudo mkdir -p /opt/appdata
sudo mount /dev/vg_system/lv_app_data /opt/appdata
# Add to fstab
echo "/dev/vg_system/lv_app_data /opt/appdata ext4 defaults 0 2" | sudo tee -a /etc/fstab
```
### LVM Snapshots
```bash
# Create snapshot of lv_root
sudo lvcreate -L 2G -s -n lv_root_snapshot /dev/vg_system/lv_root
# Mount snapshot
sudo mkdir -p /mnt/snapshot
sudo mount /dev/vg_system/lv_root_snapshot /mnt/snapshot
# Remove snapshot
sudo umount /mnt/snapshot
sudo lvremove /dev/vg_system/lv_root_snapshot
```
## Troubleshooting
### Installation Hangs
```bash
# Connect to console
ssh grokbox "virsh console debian-lvm-guest"
# Check VM is running
ssh grokbox "virsh list"
# Restart VM if needed
ssh grokbox "virsh reboot debian-lvm-guest"
```
### No IP After Installation
```bash
# Check DHCP
ssh grokbox "virsh net-dhcp-leases default"
# Restart network on VM (via console)
ssh grokbox "virsh console debian-lvm-guest"
# Login and run:
sudo systemctl restart networking
```
### Preseed Issues
```bash
# Check preseed file syntax
ssh grokbox "debconf-set-selections -c /tmp/preseed.cfg"
# Re-generate preseed
ansible-playbook plays/deploy-debian-lvm-netinst.yml --tags preseed
# View generated preseed
ssh grokbox "cat /tmp/preseed-debian-lvm-guest.cfg"
```
### LVM Not Configured
If LVM is not properly configured after installation:
```bash
# Check if LVM packages are installed
ssh ansible@<VM_IP> "dpkg -l | grep lvm2"
# Check if VG exists
ssh ansible@<VM_IP> "sudo vgs"
# Manual LVM setup (if needed)
ssh ansible@<VM_IP> "sudo pvcreate /dev/vda2"
ssh ansible@<VM_IP> "sudo vgcreate vg_system /dev/vda2"
```
## Advantages Over Cloud Images
### Why Use Network Installer?
1. **Full LVM Support**: Proper LVM partitioning from installation
2. **CLAUDE.md Compliance**: Meets all partitioning requirements
3. **Flexibility**: Complete control over partitioning
4. **Production Ready**: Standard Debian installation process
5. **Latest Packages**: Always installs latest packages during install
### Disadvantages
1. **Longer Deployment**: 15-20 minutes vs 2-3 minutes for cloud images
2. **More Complex**: Requires preseed configuration
3. **Network Dependent**: Requires network access during installation
## VM Management
### Start/Stop/Restart
```bash
ssh grokbox "virsh start debian-lvm-guest"
ssh grokbox "virsh shutdown debian-lvm-guest"
ssh grokbox "virsh reboot debian-lvm-guest"
ssh grokbox "virsh destroy debian-lvm-guest" # Force stop
```
### Delete VM
```bash
ssh grokbox "virsh destroy debian-lvm-guest"
ssh grokbox "virsh undefine debian-lvm-guest --remove-all-storage"
```
## Validation Checklist
After deployment:
- [ ] VM running: `virsh list | grep debian-lvm`
- [ ] IP assigned: `virsh domifaddr debian-lvm-guest`
- [ ] SSH accessible: `ssh -J grokbox ansible@<VM_IP>`
- [ ] LVM configured: `sudo vgs && sudo lvs`
- [ ] All partitions mounted: `df -h`
- [ ] Firewall enabled: `sudo ufw status`
- [ ] Security updates configured: `sudo unattended-upgrades --dry-run`
- [ ] Swap active: `free -h | grep Swap`
## Important Files
### On Hypervisor (grokbox)
- Netinst ISO: `/var/lib/libvirt/images/debian-12.0.0-amd64-netinst.iso`
- VM disk: `/var/lib/libvirt/images/debian-lvm-guest.qcow2`
- Preseed config: `/tmp/preseed-debian-lvm-guest.cfg`
- VM config: `/etc/libvirt/qemu/debian-lvm-guest.xml`
### On Guest VM
- LVM config: `/etc/lvm/lvm.conf`
- Fstab: `/etc/fstab`
- Installed packages: `/var/log/installer/`
## Comparison with Other Playbooks
| Feature | deploy-debian12-vm.yml | deploy-debian-lvm-netinst.yml | deploy-linux-vm-role |
|---------|------------------------|-------------------------------|---------------------|
| LVM Support | ❌ No | ✅ Yes (native) | ✅ Yes (post-config) |
| Deployment Time | 2-3 min | 15-20 min | 2-3 min + LVM setup |
| Multi-distro | ❌ No | ❌ No | ✅ Yes |
| CLAUDE.md LVM | ❌ No | ✅ Yes | ✅ Yes |
| Complexity | Low | Medium | High |
## Related Documentation
- Playbook: `plays/deploy-debian-lvm-netinst.yml`
- CLAUDE.md: LVM requirements and specifications
- Debian Preseed: https://wiki.debian.org/DebianInstaller/Preseed
- LVM Guide: https://wiki.debian.org/LVM
## Support
For issues:
- Check installation logs: `/var/log/installer/` on VM
- Review preseed: `/tmp/preseed-debian-lvm-guest.cfg` on hypervisor
- Monitor console: `virsh console debian-lvm-guest`
- Consult CLAUDE.md for LVM specifications

View File

@@ -0,0 +1,286 @@
# Debian 12 VM Deployment Cheatsheet
## Quick Deployment
### Basic Deployment
```bash
# Deploy VM with default settings
ansible-playbook plays/deploy-debian12-vm.yml
# Deploy with custom VM name
ansible-playbook plays/deploy-debian12-vm.yml -e "vm_name=myvm"
```
### Custom Configuration
```bash
# Deploy with custom resources
ansible-playbook plays/deploy-debian12-vm.yml \
-e "vm_name=custom-vm" \
-e "vm_vcpus=4" \
-e "vm_memory_mb=4096" \
-e "vm_disk_size_gb=50"
# Deploy with custom network
ansible-playbook plays/deploy-debian12-vm.yml \
-e "vm_name=web-server" \
-e "vm_network=default" \
-e "vm_hostname=webserver" \
-e "vm_domain=example.com"
```
## Tag-Based Execution
### Selective Deployment Steps
```bash
# Pre-flight checks only
ansible-playbook plays/deploy-debian12-vm.yml -t preflight,validate
# Download image only
ansible-playbook plays/deploy-debian12-vm.yml -t download
# Verify image checksum
ansible-playbook plays/deploy-debian12-vm.yml -t verify
# Create storage only
ansible-playbook plays/deploy-debian12-vm.yml -t storage
# Generate cloud-init config only
ansible-playbook plays/deploy-debian12-vm.yml -t cloud-init
# Deploy VM (skip download if image exists)
ansible-playbook plays/deploy-debian12-vm.yml -t deploy
# Validation only
ansible-playbook plays/deploy-debian12-vm.yml -t validate
# Cleanup temporary files
ansible-playbook plays/deploy-debian12-vm.yml -t cleanup
```
### Debug Mode
```bash
# Show console output (use with caution)
ansible-playbook plays/deploy-debian12-vm.yml -t debug
```
## Common Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `vm_name` | debian12-guest | VM name in libvirt |
| `vm_hostname` | debian12 | VM hostname |
| `vm_domain` | localdomain | Domain name |
| `vm_vcpus` | 2 | Number of vCPUs |
| `vm_memory_mb` | 2048 | RAM in MB |
| `vm_disk_size_gb` | 20 | Disk size in GB |
| `vm_network` | default | Libvirt network |
| `vm_bridge` | virbr0 | Bridge interface |
| `ansible_user_ssh_key` | (predefined) | SSH public key for ansible user |
## Post-Deployment
### Access the VM
```bash
# Get VM IP address
virsh domifaddr debian12-guest
# SSH to VM via ProxyJump
ssh -J grokbox ansible@<VM_IP>
# Direct SSH (from grokbox)
ssh ansible@<VM_IP>
```
### VM Management
```bash
# Start VM
virsh start debian12-guest
# Stop VM
virsh shutdown debian12-guest
# Force stop VM
virsh destroy debian12-guest
# Remove VM
virsh undefine debian12-guest --remove-all-storage
# VM status
virsh dominfo debian12-guest
# List all VMs
virsh list --all
# VM console access
virsh console debian12-guest
```
### Add to Inventory
Add the deployed VM to your Ansible inventory:
```yaml
# inventories/development/hosts.yml
kvm_guests:
children:
development:
hosts:
debian12-guest:
ansible_host: 192.168.122.XX
ansible_user: ansible
ansible_ssh_common_args: '-o ProxyJump=grokbox -o StrictHostKeyChecking=accept-new'
host_description: "Debian 12 Development VM"
host_role: development
vm_vcpus: 2
vm_memory_mb: 2048
```
## Troubleshooting
### Check Cloud-Init Status
```bash
# On the VM
cloud-init status
cloud-init status --wait
cloud-init status --long
# View cloud-init logs
cat /var/log/cloud-init.log
cat /var/log/cloud-init-output.log
```
### Network Issues
```bash
# Check VM network interface
virsh domiflist debian12-guest
# Check VM IP
virsh domifaddr debian12-guest
# Check network connectivity from grokbox
ping <VM_IP>
```
### VM Console Access
```bash
# Connect to serial console
virsh console debian12-guest
# Disconnect: Ctrl + ]
```
### Storage Issues
```bash
# Check VM disk
virsh domblklist debian12-guest
# Check disk usage on hypervisor
qemu-img info /var/lib/libvirt/images/debian12-guest.qcow2
# Resize disk (if needed, after deployment)
qemu-img resize /var/lib/libvirt/images/debian12-guest.qcow2 +10G
```
### VM Won't Start
```bash
# Check libvirt logs
journalctl -u libvirtd -f
# Check VM XML configuration
virsh dumpxml debian12-guest
# Validate VM configuration
virt-xml-validate /etc/libvirt/qemu/debian12-guest.xml
```
### SSH Connection Issues
```bash
# Test SSH connectivity
ssh -vvv -J grokbox ansible@<VM_IP>
# Check SSH service on VM (via console)
virsh console debian12-guest
# Then: systemctl status ssh
```
## Security Features
The deployed VM includes:
- ✅ Ansible user with passwordless sudo
- ✅ SSH key-based authentication only
- ✅ Root login disabled via SSH
- ✅ UFW firewall enabled (SSH allowed)
- ✅ Automatic security updates configured
- ✅ Audit daemon (auditd) enabled
- ✅ Time synchronization (chrony)
- ✅ Essential security packages installed
- ✅ AIDE for file integrity monitoring
- ✅ Secure SSH configuration
## Package List
### Essential Packages
- sudo, vim, htop, tmux
- curl, wget, rsync, git
- python3, python3-pip
- jq, bc
### Security Packages
- aide (file integrity)
- auditd (system auditing)
- ufw (firewall)
- unattended-upgrades
### System Packages
- chrony (time sync)
- lvm2 (storage management)
- cloud-guest-utils
- parted
## Validation Checklist
After deployment, verify:
- [ ] VM is running: `virsh list`
- [ ] VM has IP address: `virsh domifaddr debian12-guest`
- [ ] SSH accessible: `ssh -J grokbox ansible@<VM_IP>`
- [ ] Cloud-init completed: `cloud-init status`
- [ ] Security updates enabled: `systemctl status unattended-upgrades`
- [ ] Firewall enabled: `sudo ufw status`
- [ ] Time sync working: `chronyc tracking`
- [ ] Audit daemon running: `systemctl status auditd`
## Next Steps
1. Add VM to Ansible inventory
2. Run configuration management roles
3. Configure application-specific settings
4. Set up monitoring and logging
5. Configure backups
6. Document VM purpose and services
## Quick Reference
### Deployment Flow
1. **Preflight** → Check if VM exists, validate virtualization
2. **Install** → Install required packages on hypervisor
3. **Download** → Download Debian 12 cloud image
4. **Storage** → Create VM disk from cloud image
5. **Cloud-Init** → Generate cloud-init configuration
6. **Deploy** → Create and start VM
7. **Validate** → Verify SSH connectivity and system status
8. **Cleanup** → Remove temporary files
### Important Paths
- VM Disk: `/var/lib/libvirt/images/debian12-guest.qcow2`
- Cloud-Init ISO: `/var/lib/libvirt/images/debian12-guest-cloud-init.iso`
- Base Image: `/var/lib/libvirt/images/debian-12-generic-amd64.qcow2`
- VM Config: `/etc/libvirt/qemu/debian12-guest.xml`
### Support
For issues or questions:
- Check `/var/log/cloud-init.log` on VM
- Check `journalctl -u libvirtd` on hypervisor
- Review playbook documentation: `plays/deploy-debian12-vm.yml`
- Consult CLAUDE.md for infrastructure guidelines

View File

@@ -0,0 +1,411 @@
# Deploy Linux VM with Post-Config LVM - Quick Reference
## Playbook
`plays/deploy-linux-vm-lvm.yml`
## Description
Multi-distribution Linux VM deployment with post-installation LVM configuration. This playbook deploys a VM using cloud images and then configures LVM on a second disk to meet CLAUDE.md requirements.
## Quick Deployment
### Debian 12 with LVM
```bash
ansible-playbook plays/deploy-linux-vm-lvm.yml \
-e "os_distribution=debian-12" \
-e "vm_name=debian-lvm"
```
### Ubuntu 22.04 with LVM
```bash
ansible-playbook plays/deploy-linux-vm-lvm.yml \
-e "os_distribution=ubuntu-22.04" \
-e "vm_name=ubuntu-lvm"
```
### AlmaLinux 9 with LVM
```bash
ansible-playbook plays/deploy-linux-vm-lvm.yml \
-e "os_distribution=almalinux-9" \
-e "vm_name=alma-lvm"
```
### Custom Resources
```bash
ansible-playbook plays/deploy-linux-vm-lvm.yml \
-e "os_distribution=rocky-9" \
-e "vm_name=prod-server" \
-e "vm_vcpus=8" \
-e "vm_memory_mb=16384" \
-e "vm_disk_size_gb=100"
```
## Supported Distributions
### Debian Family
- `debian-11`, `debian-12`
- `ubuntu-20.04`, `ubuntu-22.04`, `ubuntu-24.04`
### RHEL Family
- `rhel-8`, `rhel-9` (manual download required)
- `centos-stream-8`, `centos-stream-9`
- `rocky-8`, `rocky-9`
- `almalinux-8`, `almalinux-9`
### SUSE Family
- `sles-15` (manual download required)
- `opensuse-leap-15.5`, `opensuse-leap-15.6`
## LVM Configuration
This playbook creates a **30GB secondary disk** (`/dev/vdb`) with LVM:
```
Physical Volume: /dev/vdb (30GB)
Volume Group: vg_system
Logical Volumes (CLAUDE.md compliant):
├── lv_opt 3G /opt
├── lv_tmp 1G /tmp (noexec,nosuid,nodev)
├── lv_home 2G /home
├── lv_var 5G /var
├── lv_var_log 2G /var/log
├── lv_var_tmp 5G /var/tmp (noexec,nosuid,nodev)
├── lv_var_audit 1G /var/log/audit
└── lv_swap 2G swap
Primary disk (/dev/vda): OS installation (unchanged)
```
## Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `os_distribution` | **REQUIRED** | Distribution identifier |
| `vm_name` | linux-guest | VM name |
| `vm_hostname` | linux-vm | VM hostname |
| `vm_vcpus` | 2 | Number of vCPUs |
| `vm_memory_mb` | 2048 | RAM in MB |
| `vm_disk_size_gb` | 20 | Primary disk size |
| `lvm_disk_size_gb` | 30 | LVM disk size |
| `lvm_vg_name` | vg_system | Volume group name |
| `lvm_pv_device` | /dev/vdb | Physical volume device |
## Tag-Based Execution
```bash
# Pre-flight checks
ansible-playbook plays/deploy-linux-vm-lvm.yml --tags preflight
# Deploy VM only (no LVM)
ansible-playbook plays/deploy-linux-vm-lvm.yml --skip-tags lvm
# Configure LVM only (existing VM)
ansible-playbook plays/deploy-linux-vm-lvm.yml \
-e "vm_ip=192.168.122.50" \
--tags lvm
# Full deployment
ansible-playbook plays/deploy-linux-vm-lvm.yml
```
### Available Tags
- `preflight`, `validate` - Pre-flight validation
- `install` - Install hypervisor packages
- `download`, `verify` - Download and verify cloud images
- `storage` - Create VM disks (including LVM disk)
- `cloud-init` - Generate cloud-init configuration
- `deploy` - Deploy and start VM
- `lvm` - Configure LVM on deployed VM
- `post-deploy` - Post-deployment tasks
- `cleanup` - Remove temporary files
## Deployment Process
### Stage 1: VM Deployment (~2-3 minutes)
1. Download cloud image (if not cached)
2. Create primary disk from cloud image
3. Create secondary 30GB disk for LVM
4. Generate cloud-init configuration
5. Deploy VM with both disks attached
6. Wait for VM to boot
### Stage 2: LVM Configuration (~3-5 minutes)
1. Install LVM packages on VM
2. Create physical volume on /dev/vdb
3. Create volume group vg_system
4. Create logical volumes
5. Format filesystems
6. Copy existing data to LVM volumes
7. Update /etc/fstab
8. **Reboot required to activate**
### Total Time: ~5-8 minutes
## Post-Deployment
### Get VM IP
```bash
ssh grokbox "virsh domifaddr <vm_name>"
```
### Access VM
```bash
ssh -J grokbox ansible@<VM_IP>
```
### Verify LVM Configuration
```bash
# Check LVM status
ssh -J grokbox ansible@<VM_IP> "sudo pvs && sudo vgs && sudo lvs"
# Check disk layout
ssh -J grokbox ansible@<VM_IP> "lsblk"
# View fstab
ssh -J grokbox ansible@<VM_IP> "cat /etc/fstab"
```
Expected lsblk output:
```
NAME SIZE TYPE MOUNTPOINTS
vda 20G disk
├─vda1 19.9G part /
└─vda14 4M part
vdb 30G disk
├─vg_system-lv_opt 3G lvm /opt
├─vg_system-lv_tmp 1G lvm /tmp
├─vg_system-lv_home 2G lvm /home
├─vg_system-lv_var 5G lvm /var
├─vg_system-lv_var_log 2G lvm /var/log
├─vg_system-lv_var_tmp 5G lvm /var/tmp
├─vg_system-lv_var_audit 1G lvm /var/log/audit
└─vg_system-lv_swap 2G lvm [SWAP]
```
### Reboot to Activate LVM Mounts
```bash
# IMPORTANT: Reboot required!
ssh -J grokbox ansible@<VM_IP> "sudo reboot"
# Wait ~1 minute, then verify mounts
ssh -J grokbox ansible@<VM_IP> "df -h"
```
After reboot, verify all LVM volumes are mounted:
```bash
ssh -J grokbox ansible@<VM_IP> "df -h | grep vg_system"
```
## Distribution-Specific Features
### Debian/Ubuntu
- Package manager: `apt`
- Firewall: `ufw` (enabled with SSH allowed)
- Security: AppArmor enabled
- Auto-updates: `unattended-upgrades`
- User group: `sudo`
### RHEL/AlmaLinux/Rocky
- Package manager: `dnf`
- Firewall: `firewalld` (enabled with SSH allowed)
- Security: SELinux enforcing
- Auto-updates: `dnf-automatic`
- User group: `wheel`
### SUSE/openSUSE
- Package manager: `zypper`
- Firewall: `firewalld`
- User group: `wheel`
## LVM Management
### Extend Logical Volumes
```bash
# Extend lv_var by 5GB
ssh ansible@<VM_IP> "sudo lvextend -L +5G /dev/vg_system/lv_var"
ssh ansible@<VM_IP> "sudo resize2fs /dev/vg_system/lv_var"
# Use all remaining free space
ssh ansible@<VM_IP> "sudo lvextend -l +100%FREE /dev/vg_system/lv_var"
ssh ansible@<VM_IP> "sudo resize2fs /dev/vg_system/lv_var"
```
### Create New Logical Volume
```bash
ssh ansible@<VM_IP> "sudo lvcreate -L 5G -n lv_app vg_system"
ssh ansible@<VM_IP> "sudo mkfs.ext4 /dev/vg_system/lv_app"
ssh ansible@<VM_IP> "sudo mkdir -p /opt/app"
ssh ansible@<VM_IP> "sudo mount /dev/vg_system/lv_app /opt/app"
# Add to fstab
ssh ansible@<VM_IP> "echo '/dev/vg_system/lv_app /opt/app ext4 defaults 0 2' | sudo tee -a /etc/fstab"
```
### LVM Snapshots
```bash
# Create snapshot
ssh ansible@<VM_IP> "sudo lvcreate -L 2G -s -n lv_var_snapshot /dev/vg_system/lv_var"
# Mount snapshot
ssh ansible@<VM_IP> "sudo mkdir -p /mnt/snapshot"
ssh ansible@<VM_IP> "sudo mount /dev/vg_system/lv_var_snapshot /mnt/snapshot"
# Remove snapshot
ssh ansible@<VM_IP> "sudo umount /mnt/snapshot"
ssh ansible@<VM_IP> "sudo lvremove /dev/vg_system/lv_var_snapshot"
```
## Troubleshooting
### LVM Configuration Failed
```bash
# Check if second disk is attached
ssh grokbox "virsh domblklist <vm_name>"
# Check disk visibility on VM
ssh ansible@<VM_IP> "lsblk"
# Manually run LVM setup
ssh ansible@<VM_IP> "sudo pvcreate /dev/vdb"
ssh ansible@<VM_IP> "sudo vgcreate vg_system /dev/vdb"
```
### Mounts Not Active After Reboot
```bash
# Check fstab entries
ssh ansible@<VM_IP> "cat /etc/fstab | grep vg_system"
# Manually mount all
ssh ansible@<VM_IP> "sudo mount -a"
# Check for errors
ssh ansible@<VM_IP> "dmesg | tail -30"
```
### Data Migration Issues
```bash
# Check data was copied
ssh ansible@<VM_IP> "sudo du -sh /var"
ssh ansible@<VM_IP> "sudo du -sh /opt"
# If data missing, restore from rsync backup
# (Data should be preserved on original locations until reboot)
```
### SELinux Issues (RHEL Family)
```bash
# Check SELinux status
ssh ansible@<VM_IP> "getenforce"
# View denials
ssh ansible@<VM_IP> "sudo ausearch -m avc -ts recent"
# Relabel filesystem
ssh ansible@<VM_IP> "sudo restorecon -R /opt /tmp /home /var"
```
## Security Features
All deployed VMs include:
**Authentication**
- 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
- Debian: AppArmor enabled
- Audit daemon enabled
- Time synchronization (chrony)
**Essential Packages**
- System tools: vim, htop, tmux
- Network: curl, wget, rsync
- Development: git, python3
- Security: aide, auditd
- Storage: lvm2, parted
## VM Management
```bash
# Start/Stop
ssh grokbox "virsh start <vm_name>"
ssh grokbox "virsh shutdown <vm_name>"
ssh grokbox "virsh destroy <vm_name>"
# Status
ssh grokbox "virsh dominfo <vm_name>"
ssh grokbox "virsh list --all"
# Console
ssh grokbox "virsh console <vm_name>"
# Delete
ssh grokbox "virsh destroy <vm_name>"
ssh grokbox "virsh undefine <vm_name> --remove-all-storage"
```
## Validation Checklist
After deployment and reboot:
- [ ] VM running: `virsh list | grep <vm_name>`
- [ ] IP assigned: `virsh domifaddr <vm_name>`
- [ ] SSH accessible: `ssh -J grokbox ansible@<VM_IP>`
- [ ] Cloud-init complete: `cloud-init status`
- [ ] LVM configured: `sudo vgs && sudo lvs`
- [ ] All volumes mounted: `df -h | grep vg_system`
- [ ] Firewall enabled: `sudo ufw status` or `sudo firewall-cmd --state`
- [ ] SELinux enforcing (RHEL): `getenforce`
- [ ] Swap active: `free -h | grep Swap`
## Comparison with Other Playbooks
| Feature | deploy-debian12-vm | deploy-debian-lvm-netinst | deploy-linux-vm-lvm | deploy_linux_vm role |
|---------|-------------------|---------------------------|---------------------|---------------------|
| Multi-distro | ❌ No | ❌ No | ✅ Yes | ✅ Yes |
| LVM Support | ❌ No | ✅ Yes (native) | ✅ Yes (post-config) | ✅ Yes (post-config) |
| Deploy Time | 2-3 min | 15-20 min | 5-8 min | 5-8 min |
| CLAUDE.md LVM | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes |
| Reboot Required | No | No | Yes | Yes |
| Modular | No | No | No | Yes |
## Important Files
### On Hypervisor (grokbox)
- Cloud images: `/var/lib/libvirt/images/*.qcow2`
- VM primary disk: `/var/lib/libvirt/images/<vm_name>.qcow2`
- VM LVM disk: `/var/lib/libvirt/images/<vm_name>-lvm.qcow2`
- Cloud-init ISO: `/var/lib/libvirt/images/<vm_name>-cloud-init.iso`
### On Guest VM
- SSH config: `/etc/ssh/sshd_config.d/99-security.conf`
- Sudoers: `/etc/sudoers.d/ansible`
- Fstab: `/etc/fstab` (LVM mounts)
- LVM config: `/etc/lvm/lvm.conf`
## Related Documentation
- Playbook: `plays/deploy-linux-vm-lvm.yml`
- Role (recommended): `roles/deploy_linux_vm/`
- Multi-distro without LVM: `plays/deploy-linux-vm.yml`
- Debian native LVM: `plays/deploy-debian-lvm-netinst.yml`
- CLAUDE.md: LVM specifications
## Support
For issues or questions:
- Check playbook output during LVM configuration
- View `/var/log/cloud-init-output.log` on VM
- Consult CLAUDE.md for LVM requirements
- Use role version for advanced features

View File

@@ -0,0 +1,287 @@
# Deploy Linux VM Role - Quick Reference
## Quick Deployment
### Basic Usage
```bash
# Deploy Debian 12 VM
ansible-playbook -i inventories/production site.yml \
-e "deploy_linux_vm_name=test-vm" \
-e "deploy_linux_vm_os_distribution=debian-12"
# Deploy Ubuntu 22.04 VM with LVM
ansible-playbook -i inventories/production site.yml \
-e "deploy_linux_vm_name=ubuntu-vm" \
-e "deploy_linux_vm_os_distribution=ubuntu-22.04" \
-e "deploy_linux_vm_use_lvm=true"
# Deploy AlmaLinux 9 with custom resources
ansible-playbook -i inventories/production site.yml \
-e "deploy_linux_vm_name=alma-vm" \
-e "deploy_linux_vm_os_distribution=almalinux-9" \
-e "deploy_linux_vm_vcpus=4" \
-e "deploy_linux_vm_memory_mb=8192" \
-e "deploy_linux_vm_disk_size_gb=50"
```
### Distribution Identifiers
```
Debian: debian-11, debian-12
Ubuntu: ubuntu-20.04, ubuntu-22.04, ubuntu-24.04
RHEL: rhel-8, rhel-9 (manual download)
CentOS: centos-stream-8, centos-stream-9
Rocky: rocky-8, rocky-9
AlmaLinux: almalinux-8, almalinux-9
SLES: sles-15 (manual download)
openSUSE: opensuse-leap-15.5, opensuse-leap-15.6
```
## Tag-Based Execution
```bash
# Pre-flight checks only
ansible-playbook site.yml --tags validate,preflight
# Download images only
ansible-playbook site.yml --tags download,verify
# Deploy without LVM
ansible-playbook site.yml --skip-tags lvm
# Configure LVM only (existing VM)
ansible-playbook site.yml --tags lvm,post-deploy
# Full deployment
ansible-playbook site.yml
```
## Common Variables
### VM Configuration
```yaml
deploy_linux_vm_name: "myvm" # VM name
deploy_linux_vm_hostname: "myhost" # Hostname
deploy_linux_vm_vcpus: 2 # CPU cores
deploy_linux_vm_memory_mb: 2048 # RAM in MB
deploy_linux_vm_disk_size_gb: 30 # Disk size
```
### LVM Configuration
```yaml
deploy_linux_vm_use_lvm: true # Enable LVM
deploy_linux_vm_lvm_vg_name: "vg_system" # VG name
deploy_linux_vm_lvm_pv_device: "/dev/vdb" # PV device
```
### Security Settings
```yaml
deploy_linux_vm_ssh_gssapi_authentication: "no" # GSSAPI disabled
deploy_linux_vm_enable_firewall: true # Firewall on
deploy_linux_vm_enable_selinux: true # SELinux (RHEL)
deploy_linux_vm_enable_automatic_updates: true # Auto updates
```
## Example Playbooks
### Minimal Playbook
```yaml
---
- hosts: grokbox
become: yes
roles:
- deploy_linux_vm
vars:
deploy_linux_vm_name: "test-vm"
deploy_linux_vm_os_distribution: "debian-12"
```
### Production Playbook with LVM
```yaml
---
- hosts: grokbox
become: yes
roles:
- deploy_linux_vm
vars:
deploy_linux_vm_name: "prod-db"
deploy_linux_vm_hostname: "postgres01"
deploy_linux_vm_domain: "prod.local"
deploy_linux_vm_os_distribution: "almalinux-9"
deploy_linux_vm_vcpus: 8
deploy_linux_vm_memory_mb: 16384
deploy_linux_vm_disk_size_gb: 100
deploy_linux_vm_use_lvm: true
```
## Post-Deployment
### Access VM
```bash
# Get VM IP
ssh grokbox "virsh domifaddr <vm_name>"
# SSH to VM
ssh -J grokbox ansible@<VM_IP>
# Or add to ~/.ssh/config
Host myvm
HostName <VM_IP>
User ansible
ProxyJump grokbox
```
### Verify LVM
```bash
# Check LVM status
ssh -J grokbox ansible@<VM_IP> "sudo vgs && sudo lvs"
# Check mounts (after reboot)
ssh -J grokbox ansible@<VM_IP> "df -h && lsblk"
# Reboot VM to activate LVM mounts
ssh -J grokbox ansible@<VM_IP> "sudo reboot"
```
### Verify SSH Hardening
```bash
# Check GSSAPI disabled
ssh -J grokbox ansible@<VM_IP> "sudo sshd -T | grep -i gssapi"
# Should show:
# gssapiauthentication no
# gssapicleanupcredentials no
```
### Check Security Features
```bash
# Debian/Ubuntu - UFW status
ssh -J grokbox ansible@<VM_IP> "sudo ufw status"
# RHEL/Alma - Firewall and SELinux
ssh -J grokbox ansible@<VM_IP> "sudo firewall-cmd --list-all && getenforce"
# Check automatic updates
ssh -J grokbox ansible@<VM_IP> "systemctl status unattended-upgrades" # Debian
ssh -J grokbox ansible@<VM_IP> "systemctl status dnf-automatic.timer" # RHEL
```
## VM Management
```bash
# Start/Stop/Status
virsh start <vm_name>
virsh shutdown <vm_name>
virsh destroy <vm_name>
virsh dominfo <vm_name>
# List VMs
virsh list --all
# Console access
virsh console <vm_name>
# Delete VM
virsh destroy <vm_name>
virsh undefine <vm_name> --remove-all-storage
```
## Troubleshooting
### Cloud-Init
```bash
# Check status
ssh -J grokbox ansible@<VM_IP> "cloud-init status --wait"
# View logs
ssh -J grokbox ansible@<VM_IP> "tail -f /var/log/cloud-init-output.log"
```
### Network
```bash
# Get VM IP
virsh domifaddr <vm_name>
# Check network
virsh net-list
virsh net-dhcp-leases default
```
### LVM Issues
```bash
# Check LVM configuration
ssh -J grokbox ansible@<VM_IP> "sudo pvs && sudo vgs && sudo lvs"
# Check fstab
ssh -J grokbox ansible@<VM_IP> "cat /etc/fstab"
# Manually mount if needed
ssh -J grokbox ansible@<VM_IP> "sudo mount -a"
```
## LVM Volume Layout (CLAUDE.md)
```
Volume Group: vg_system (30GB on /dev/vdb)
├── lv_opt 3G /opt
├── lv_tmp 1G /tmp (noexec,nosuid,nodev)
├── lv_home 2G /home
├── lv_var 5G /var
├── lv_var_log 2G /var/log
├── lv_var_tmp 5G /var/tmp (noexec,nosuid,nodev)
├── lv_var_audit 1G /var/log/audit
└── lv_swap 2G swap
```
## SSH Security Settings
```
PermitRootLogin: no
PasswordAuthentication: no
GSSAPIAuthentication: no ← DISABLED per requirements
GSSAPICleanupCredentials: no ← DISABLED per requirements
MaxAuthTries: 3
ClientAliveInterval: 300
Key-based authentication only
```
## Essential Packages Installed
- System: vim, htop, tmux, jq, bc
- Network: curl, wget, rsync
- Dev: git, python3, python3-pip
- Security: aide, auditd, chrony
- Storage: lvm2, parted
## Important Files
### On Hypervisor
- Cloud images: `/var/lib/libvirt/images/*.qcow2`
- VM disk: `/var/lib/libvirt/images/<vm_name>.qcow2`
- LVM disk: `/var/lib/libvirt/images/<vm_name>-lvm.qcow2`
### On Guest VM
- SSH config: `/etc/ssh/sshd_config.d/99-security.conf`
- Sudoers: `/etc/sudoers.d/ansible`
- Fstab: `/etc/fstab`
- Cloud-init log: `/var/log/cloud-init-output.log`
## Quick Validation Checklist
After deployment:
- [ ] VM running: `virsh list | grep <vm_name>`
- [ ] IP assigned: `virsh domifaddr <vm_name>`
- [ ] SSH accessible: `ssh -J grokbox ansible@<VM_IP>`
- [ ] Cloud-init done: `cloud-init status`
- [ ] Firewall active: `sudo ufw status` or `sudo firewall-cmd --state`
- [ ] LVM configured: `sudo vgs` (if LVM enabled)
- [ ] GSSAPI disabled: `sudo sshd -T | grep gssapi`
- [ ] Reboot for LVM: `sudo reboot` (then verify mounts)
## Support
- Role README: `roles/deploy_linux_vm/README.md`
- Documentation: `docs/linux-vm-deployment.md`
- Guidelines: `CLAUDE.md`

View File

@@ -0,0 +1,502 @@
# 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 <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
```bash
# 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
```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 <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)
```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 <port>
# RHEL/SUSE
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=<service>
sudo firewall-cmd --reload
```
### Package Manager Issues
```bash
# 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:
```bash
# 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
- 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/<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:
```bash
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`

212
cheatsheets/inventory.md Normal file
View File

@@ -0,0 +1,212 @@
# Inventory Cheatsheet
Quick reference for Ansible inventory management.
## Quick Commands
### List Hosts
```bash
# Static inventory
ansible all -i inventories/development/hosts.yml --list-hosts
# SSH config dynamic
ansible all -i plugins/inventory/ssh_config_inventory.py --list-hosts
# Libvirt dynamic
ansible all -i plugins/inventory/libvirt_kvm.py --list-hosts
```
### View Inventory Structure
```bash
# List all groups and hosts
ansible-inventory -i <inventory> --list
# Show as graph
ansible-inventory -i <inventory> --graph
# Specific host details
ansible-inventory -i <inventory> --host <hostname>
```
### Test Connectivity
```bash
# Ping all hosts
ansible all -i <inventory> -m ping
# Ping specific group
ansible kvm_guests -i <inventory> -m ping
# Verbose output
ansible all -i <inventory> -m ping -vvv
```
## Inventory Locations
| Inventory | Path | Type |
|-----------|------|------|
| Static Dev | `inventories/development/hosts.yml` | Static YAML |
| SSH Parser | `plugins/inventory/ssh_config_inventory.py` | Dynamic Script |
| Libvirt | `plugins/inventory/libvirt_kvm.py` | Dynamic Script |
## Common Groups
| Group | Description | Inventory |
|-------|-------------|-----------|
| `all` | All hosts | All |
| `external_hosts` | Public-facing hosts | All |
| `hypervisors` | KVM hypervisors | All |
| `kvm_guests` | All VMs | All |
| `running_vms` | Running VMs only | Libvirt |
| `dns_servers` | DNS/DHCP servers | All |
| `mail_servers` | Mail servers | All |
| `development` | Dev/test hosts | All |
## Dynamic Inventory Usage
### SSH Config Parser
```bash
# List inventory
python3 plugins/inventory/ssh_config_inventory.py --list
# Host details
python3 plugins/inventory/ssh_config_inventory.py --host pihole
# Use with ansible
ansible all -i plugins/inventory/ssh_config_inventory.py -m ping
```
### Libvirt Dynamic
```bash
# Set environment
export LIBVIRT_DEFAULT_URI="qemu+ssh://grok@grok.home.serneels.xyz/system"
export LIBVIRT_HYPERVISOR_NAME="grokbox"
# List VMs
python3 plugins/inventory/libvirt_kvm.py --list
# Use with ansible
ansible running_vms -i plugins/inventory/libvirt_kvm.py -m setup
```
## Playbook Execution
### Single Inventory
```bash
ansible-playbook -i inventories/development/hosts.yml site.yml
```
### Multiple Inventories
```bash
ansible-playbook \
-i inventories/development/hosts.yml \
-i plugins/inventory/libvirt_kvm.py \
site.yml
```
### With Limits
```bash
# Limit to specific group
ansible-playbook -i <inventory> --limit kvm_guests site.yml
# Limit to specific host
ansible-playbook -i <inventory> --limit pihole site.yml
# Multiple limits
ansible-playbook -i <inventory> --limit "dns_servers:mail_servers" site.yml
```
## Variable Precedence
From lowest to highest:
1. `group_vars/all.yml`
2. `group_vars/<group_name>.yml`
3. `host_vars/<hostname>.yml`
4. Playbook vars
5. Extra vars (`-e`)
## Debugging
### Validate Inventory
```bash
# Syntax check
ansible-inventory -i <inventory> --list > /dev/null
# YAML validation
yamllint inventories/development/hosts.yml
```
### Connection Test
```bash
# Test SSH connectivity
ansible all -i <inventory> -m ping -vvv
# Check Python interpreter
ansible all -i <inventory> -m setup -a "filter=ansible_python_version"
# Verify become/sudo
ansible all -i <inventory> -m shell -a "whoami" --become
```
### View Effective Variables
```bash
# All variables for a host
ansible-inventory -i <inventory> --host <hostname> --yaml
# Specific variable
ansible <hostname> -i <inventory> -m debug -a "var=ansible_user"
```
## Common Issues
### SSH Config Parser
**Issue:** Hosts missing
**Fix:** Check `~/.ssh/config` syntax and permissions
### Libvirt Dynamic
**Issue:** `python3-libvirt` not found
**Fix:** `apt-get install python3-libvirt` (Debian) or `dnf install python3-libvirt` (RHEL)
**Issue:** Connection failed
**Fix:** Test SSH: `ssh grok@grok.home.serneels.xyz`
### Static Inventory
**Issue:** YAML errors
**Fix:** Check indentation, validate with `yamllint`
**Issue:** Variables not applied
**Fix:** Check file naming in `group_vars/` matches group name
## Performance Tips
```ini
# ansible.cfg
[defaults]
forks = 20
gathering = smart
fact_caching = jsonfile
fact_caching_timeout = 86400
```
```bash
# SSH connection reuse (~/.ssh/config)
Host *
ControlMaster auto
ControlPersist 600s
```
## Quick Setup
```bash
# Create inventory structure
mkdir -p inventories/{production,staging,development}/{group_vars,host_vars}
# Test connectivity
ansible all -i <inventory> -m ping
# Gather facts
ansible all -i <inventory> -m setup --tree /tmp/facts
```
---
**See also:** `/opt/ansible/docs/inventory.md` for complete documentation

View File

@@ -0,0 +1,413 @@
# Test Deploy Linux VM Role - Quick Reference
## Playbook
`plays/test-deploy-linux-vm-role.yml`
## Description
Test playbook for the `deploy_linux_vm` role. Deploys a Debian 12 test VM with full LVM configuration and SSH hardening (GSSAPI disabled) to validate role functionality.
## Quick Test
### Run Full Test
```bash
ansible-playbook plays/test-deploy-linux-vm-role.yml
```
### Test with Different Distribution
```bash
# Test with Ubuntu
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=ubuntu-22.04"
# Test with AlmaLinux
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=almalinux-9"
```
### Test with Custom Resources
```bash
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_vcpus=4" \
-e "deploy_linux_vm_memory_mb=4096"
```
## Test Configuration
### Default Test Settings
```yaml
VM Name: test-lvm-vm
Hostname: test-lvm
Distribution: debian-12
vCPUs: 2
Memory: 2048 MB
Disk: 20 GB
LVM: Enabled (30GB on /dev/vdb)
```
### Features Being Tested
✅ LVM configuration (CLAUDE.md compliant)
✅ SSH hardening (GSSAPI disabled)
✅ Multi-distribution support
✅ Security features (Firewall, SELinux/AppArmor, Audit)
✅ Automatic updates
✅ Cloud-init provisioning
## Test Execution Flow
### 1. Pre-flight Validation
- Checks if test VM already exists
- Validates distribution support
- Verifies virtualization capabilities
### 2. VM Deployment (~2-3 minutes)
- Downloads cloud image (if not cached)
- Creates primary disk (20GB)
- Creates LVM disk (30GB on /dev/vdb)
- Generates cloud-init with security hardening
- Deploys VM with both disks
### 3. LVM Configuration (~3-5 minutes)
- Installs LVM packages
- Creates vg_system volume group
- Creates 8 logical volumes
- Formats filesystems
- Migrates existing data
- Updates /etc/fstab
### 4. Validation
- Verifies VM is running
- Checks SSH connectivity
- Validates LVM configuration
- Confirms security features
### Total Test Time: ~5-8 minutes
## Post-Test Verification
### Get Test VM Information
```bash
# Get IP address
ssh grokbox "virsh domifaddr test-lvm-vm"
# SSH to test VM
ssh -J grokbox ansible@<VM_IP>
```
### Verify LVM Configuration
```bash
# Check LVM status
ssh -J grokbox ansible@<VM_IP> "sudo pvs && sudo vgs && sudo lvs"
# Expected output:
# VG: vg_system
# PV: /dev/vdb (30.00g)
# LVs: lv_opt, lv_tmp, lv_home, lv_var, lv_var_log, lv_var_tmp, lv_var_audit, lv_swap
```
### Verify SSH Hardening
```bash
# Check GSSAPI is disabled
ssh -J grokbox ansible@<VM_IP> "sudo sshd -T | grep -i gssapi"
# Expected output:
# gssapiauthentication no
# gssapicleanupcredentials no
```
### Verify Security Features
```bash
# Check firewall (Debian)
ssh -J grokbox ansible@<VM_IP> "sudo ufw status"
# Check SELinux (RHEL - if testing RHEL family)
ssh -J grokbox ansible@<VM_IP> "getenforce"
# Expected: Enforcing
```
### Reboot and Verify LVM Mounts
```bash
# Reboot test VM
ssh -J grokbox ansible@<VM_IP> "sudo reboot"
# Wait ~1 minute, then verify all mounts
ssh -J grokbox ansible@<VM_IP> "df -h && lsblk"
# Check all LVM volumes are mounted
ssh -J grokbox ansible@<VM_IP> "mount | grep vg_system"
```
## Tag-Based Testing
### Test Specific Components
```bash
# Test pre-flight validation only
ansible-playbook plays/test-deploy-linux-vm-role.yml --tags validate,preflight
# Test VM deployment only (skip LVM)
ansible-playbook plays/test-deploy-linux-vm-role.yml --skip-tags lvm
# Test LVM configuration only (if VM exists)
ansible-playbook plays/test-deploy-linux-vm-role.yml --tags lvm,post-deploy
# Test cloud-init generation only
ansible-playbook plays/test-deploy-linux-vm-role.yml --tags cloud-init
```
## Test Validation Checklist
Complete this checklist to validate test success:
### Basic Functionality
- [ ] Playbook completes without errors
- [ ] VM created: `virsh list | grep test-lvm-vm`
- [ ] IP assigned: `virsh domifaddr test-lvm-vm`
- [ ] SSH accessible: `ssh -J grokbox ansible@<VM_IP>`
### LVM Configuration
- [ ] Physical volume exists: `sudo pvs` shows /dev/vdb
- [ ] Volume group created: `sudo vgs` shows vg_system
- [ ] All 8 LVs created: `sudo lvs` shows all volumes
- [ ] Filesystems formatted: `lsblk -f` shows ext4/swap
- [ ] Fstab updated: `cat /etc/fstab | grep vg_system`
- [ ] After reboot, all mounted: `df -h | grep vg_system`
### SSH Security
- [ ] GSSAPI disabled: `sudo sshd -T | grep gssapiauthentication` shows "no"
- [ ] GSSAPI cleanup disabled: `sudo sshd -T | grep gssapicleanupcredentials` shows "no"
- [ ] Root login disabled: `sudo sshd -T | grep permitrootlogin` shows "no"
- [ ] Password auth disabled: `sudo sshd -T | grep passwordauthentication` shows "no"
- [ ] Key-based auth works: SSH connection successful
### Security Features
- [ ] Firewall enabled: `sudo ufw status` (Debian) or `sudo firewall-cmd --state` (RHEL)
- [ ] Audit daemon running: `systemctl status auditd`
- [ ] Time sync active: `chronyc tracking`
- [ ] SELinux enforcing (RHEL): `getenforce` shows "Enforcing"
### System Health
- [ ] Cloud-init complete: `cloud-init status` shows "done"
- [ ] System updated: Package updates applied during cloud-init
- [ ] No errors in logs: Check `/var/log/cloud-init-output.log`
- [ ] Swap active: `free -h | grep Swap` shows non-zero
## Cleanup After Testing
### Delete Test VM
```bash
# Stop and remove test VM
ssh grokbox "virsh destroy test-lvm-vm"
ssh grokbox "virsh undefine test-lvm-vm --remove-all-storage"
# Verify removal
ssh grokbox "virsh list --all | grep test-lvm-vm"
# Should return nothing
```
### Clean Test Files
```bash
# On hypervisor, remove any temporary files
ssh grokbox "rm -f /tmp/cloud-init-test-lvm-vm/*"
ssh grokbox "rm -f /tmp/*-CHECKSUM"
```
## Testing Different Distributions
### Test Debian Family
```bash
# Debian 12
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=debian-12" \
-e "deploy_linux_vm_name=test-debian12"
# Ubuntu 22.04
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=ubuntu-22.04" \
-e "deploy_linux_vm_name=test-ubuntu22"
```
### Test RHEL Family
```bash
# AlmaLinux 9
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=almalinux-9" \
-e "deploy_linux_vm_name=test-alma9"
# Rocky Linux 9
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=rocky-9" \
-e "deploy_linux_vm_name=test-rocky9"
```
## Troubleshooting Tests
### Test Fails at Pre-flight
```bash
# Check if test VM already exists
ssh grokbox "virsh list --all | grep test-lvm-vm"
# If exists, delete it
ssh grokbox "virsh destroy test-lvm-vm"
ssh grokbox "virsh undefine test-lvm-vm --remove-all-storage"
# Re-run test
ansible-playbook plays/test-deploy-linux-vm-role.yml
```
### LVM Configuration Fails
```bash
# Check if second disk is attached
ssh grokbox "virsh domblklist test-lvm-vm"
# Should show both:
# - test-lvm-vm.qcow2 (primary)
# - test-lvm-vm-lvm.qcow2 (LVM disk)
# Verify disk visibility on VM
ssh -J grokbox ansible@<VM_IP> "lsblk"
# Should show vda (20G) and vdb (30G)
```
### SSH Connection Issues
```bash
# Check VM is running
ssh grokbox "virsh list | grep test-lvm-vm"
# Get IP again
ssh grokbox "virsh domifaddr test-lvm-vm"
# Test with verbose SSH
ssh -vvv -J grokbox ansible@<VM_IP>
# Check SSH service on VM (via console)
ssh grokbox "virsh console test-lvm-vm"
```
### GSSAPI Still Enabled
```bash
# Check SSH config file was created
ssh -J grokbox ansible@<VM_IP> "ls -la /etc/ssh/sshd_config.d/"
# View security config
ssh -J grokbox ansible@<VM_IP> "cat /etc/ssh/sshd_config.d/99-security.conf"
# Restart SSH service
ssh -J grokbox ansible@<VM_IP> "sudo systemctl restart sshd"
# Test again
ssh -J grokbox ansible@<VM_IP> "sudo sshd -T | grep gssapi"
```
## Continuous Testing
### Automated Test Suite
Create a test script for continuous validation:
```bash
#!/bin/bash
# test-role.sh
DISTRIBUTIONS=(
"debian-12"
"ubuntu-22.04"
"almalinux-9"
"rocky-9"
)
for distro in "${DISTRIBUTIONS[@]}"; do
echo "Testing $distro..."
ansible-playbook plays/test-deploy-linux-vm-role.yml \
-e "deploy_linux_vm_os_distribution=$distro" \
-e "deploy_linux_vm_name=test-$distro"
if [ $? -eq 0 ]; then
echo "$distro test PASSED"
# Cleanup
ssh grokbox "virsh destroy test-$distro && virsh undefine test-$distro --remove-all-storage"
else
echo "$distro test FAILED"
exit 1
fi
done
echo "All tests completed successfully!"
```
## Expected Test Output
Successful test execution should show:
```
PLAY [Test Deploy Linux VM Role] ***********************************
TASK [Gathering Facts] *********************************************
ok: [grokbox]
...
TASK [deploy_linux_vm : Display LVM configuration summary] ********
ok: [grokbox] => {
"msg": [
"=== LVM Configuration Complete ===",
"Volume Group: vg_system",
"Physical Volume: /dev/vdb (30GB)",
"Logical Volumes: 8",
"",
"⚠️ IMPORTANT: VM needs reboot to use new mounts",
"After reboot, LVM volumes will be mounted automatically"
]
}
TASK [Display test completion message] *****************************
ok: [grokbox] => {
"msg": [
"╔════════════════════════════════════════════════════════════════╗",
"║ Role Test Completed Successfully ║",
"╚════════════════════════════════════════════════════════════════╝",
"",
"VM deployed with:",
" ✓ LVM Configuration (CLAUDE.md compliant)",
" ✓ SSH Hardening (GSSAPI disabled)",
" ✓ Security Features (Firewall, Audit, Auto-updates)",
" ✓ Multi-distribution support",
"",
"Next steps:",
" 1. SSH to VM: ssh -J grokbox ansible@192.168.122.X",
" 2. Verify GSSAPI: sudo sshd -T | grep -i gssapi",
" 3. Check LVM: sudo vgs && sudo lvs",
" 4. Reboot for LVM: sudo reboot",
" 5. After reboot verify: df -h && lsblk"
]
}
PLAY RECAP *********************************************************
grokbox: ok=X changed=Y unreachable=0 failed=0 skipped=Z
```
## Test Documentation
This test validates:
1. **Role Structure**: Proper task organization and variable handling
2. **Multi-Distribution**: Works across Debian, Ubuntu, RHEL families
3. **LVM Implementation**: Creates CLAUDE.md compliant LVM layout
4. **SSH Security**: GSSAPI disabled, key-only authentication
5. **Security Hardening**: Firewall, SELinux/AppArmor, audit daemon
6. **Cloud-Init**: Proper provisioning and package installation
7. **Idempotency**: Can be re-run without errors
## Related Documentation
- Role README: `roles/deploy_linux_vm/README.md`
- Role cheatsheet: `cheatsheets/deploy-linux-vm-role.md`
- CLAUDE.md: Infrastructure requirements
- Test playbook: `plays/test-deploy-linux-vm-role.yml`
## Support
For test failures:
- Check playbook output for specific error messages
- Review role tasks: `roles/deploy_linux_vm/tasks/`
- Check VM logs: `/var/log/cloud-init-output.log`
- Verify hypervisor resources: disk space, memory
- Consult role README for detailed troubleshooting