Files
infra-automation/roles/deploy_linux_vm/tasks/lvm.yml
Infrastructure Team eec15a1cc2 Add deploy_linux_vm role with LVM and SSH hardening
Features:
- Multi-distribution support (Debian, Ubuntu, RHEL, AlmaLinux, Rocky, SUSE)
- LVM configuration with meaningful volume groups and logical volumes
- 8 LVs: lv_opt, lv_tmp, lv_home, lv_var, lv_var_log, lv_var_tmp, lv_var_audit, lv_swap
- Security mount options on sensitive directories

SSH Hardening:
- GSSAPI authentication disabled
- GSSAPI cleanup credentials disabled
- Root login disabled via SSH
- Password authentication disabled
- Key-based authentication only
- MaxAuthTries: 3, ClientAliveInterval: 300s

Security Features:
- SELinux enforcing (RHEL family)
- AppArmor enabled (Debian family)
- Firewall configuration (UFW/firewalld)
- Automatic security updates
- Audit daemon (auditd) enabled
- Time synchronization (chrony)
- Essential security packages (aide, auditd)

Role Structure:
- Modular task organization (validate, install, download, storage, deploy, lvm)
- Tag-based execution for selective deployment
- OS-family specific cloud-init templates
- Comprehensive variable defaults (100+ configurable options)
- Post-deployment validation tasks
2025-11-10 22:51:51 +01:00

186 lines
7.1 KiB
YAML

---
# =============================================================================
# LVM Configuration Tasks - Configure LVM on Deployed VM
# =============================================================================
# This task file configures LVM on the deployed VM per CLAUDE.md requirements
- name: Wait for cloud-init to complete on VM
delegate_to: "{{ deploy_linux_vm_ip }}"
command: cloud-init status --wait
changed_when: false
failed_when: false
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Install LVM packages on VM (Debian/Ubuntu)
delegate_to: "{{ deploy_linux_vm_ip }}"
apt:
name:
- lvm2
- parted
state: present
update_cache: yes
when: deploy_linux_vm_distro_config.family == "debian"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Install LVM packages on VM (RHEL)
delegate_to: "{{ deploy_linux_vm_ip }}"
dnf:
name:
- lvm2
- parted
state: present
when: deploy_linux_vm_distro_config.family == "rhel"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create Physical Volume on {{ deploy_linux_vm_lvm_pv_device }}
delegate_to: "{{ deploy_linux_vm_ip }}"
command: pvcreate {{ deploy_linux_vm_lvm_pv_device }}
register: deploy_linux_vm_pvcreate_result
failed_when: false
changed_when: deploy_linux_vm_pvcreate_result.rc == 0
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create Volume Group {{ deploy_linux_vm_lvm_vg_name }}
delegate_to: "{{ deploy_linux_vm_ip }}"
lvg:
vg: "{{ deploy_linux_vm_lvm_vg_name }}"
pvs: "{{ deploy_linux_vm_lvm_pv_device }}"
state: present
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create Logical Volumes
delegate_to: "{{ deploy_linux_vm_ip }}"
lvol:
vg: "{{ deploy_linux_vm_lvm_vg_name }}"
lv: "{{ item.name }}"
size: "{{ item.size }}"
state: present
loop: "{{ deploy_linux_vm_lvm_volumes }}"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create filesystems on logical volumes (non-swap)
delegate_to: "{{ deploy_linux_vm_ip }}"
filesystem:
fstype: "{{ item.fstype }}"
dev: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}"
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when: item.fstype != "swap"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create swap filesystem
delegate_to: "{{ deploy_linux_vm_ip }}"
command: mkswap /dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when: item.fstype == "swap"
register: deploy_linux_vm_mkswap_result
failed_when: false
changed_when: deploy_linux_vm_mkswap_result.rc == 0
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Create temporary mount points
delegate_to: "{{ deploy_linux_vm_ip }}"
file:
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
state: directory
mode: '0755'
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when: item.fstype != "swap"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Mount logical volumes temporarily for data copy
delegate_to: "{{ deploy_linux_vm_ip }}"
mount:
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
src: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }}"
fstype: "{{ item.fstype }}"
state: mounted
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when: item.fstype != "swap"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Copy existing data to LVM volumes
delegate_to: "{{ deploy_linux_vm_ip }}"
shell: |
if [ -d "{{ item.mount }}" ] && [ "$(ls -A {{ item.mount }})" ]; then
rsync -av {{ item.mount }}/ /mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}/
fi
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when:
- item.fstype != "swap"
- item.mount != "none"
register: deploy_linux_vm_rsync_result
failed_when: false
changed_when: deploy_linux_vm_rsync_result.rc == 0
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Unmount temporary mount points
delegate_to: "{{ deploy_linux_vm_ip }}"
mount:
path: "/mnt/{{ item.name | regex_replace('^lv_', '') | regex_replace('_', '-') }}"
state: unmounted
loop: "{{ deploy_linux_vm_lvm_volumes }}"
when: item.fstype != "swap"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Update /etc/fstab with LVM mounts
delegate_to: "{{ deploy_linux_vm_ip }}"
lineinfile:
path: /etc/fstab
line: "/dev/{{ deploy_linux_vm_lvm_vg_name }}/{{ item.name }} {{ item.mount }} {{ item.fstype }} {{ item.mount_options }} 0 {{ '0' if item.fstype == 'swap' else '2' }}"
state: present
loop: "{{ deploy_linux_vm_lvm_volumes }}"
vars:
ansible_user: "{{ deploy_linux_vm_ansible_user }}"
ansible_ssh_common_args: '-o ProxyJump={{ inventory_hostname }} -o StrictHostKeyChecking=accept-new'
tags: [lvm, post-deploy]
- name: Display LVM configuration summary
debug:
msg:
- "=== LVM Configuration Complete ==="
- "Volume Group: {{ deploy_linux_vm_lvm_vg_name }}"
- "Physical Volume: {{ deploy_linux_vm_lvm_pv_device }} (30GB)"
- "Logical Volumes: {{ deploy_linux_vm_lvm_volumes | length }}"
- ""
- "⚠️ IMPORTANT: VM needs reboot to use new mounts"
- "After reboot, LVM volumes will be mounted automatically"
- ""
- "To reboot: ssh {{ deploy_linux_vm_ansible_user }}@{{ deploy_linux_vm_ip }} 'sudo reboot'"
tags: [lvm, post-deploy]