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
412 lines
11 KiB
Markdown
412 lines
11 KiB
Markdown
# 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
|