--- - name: Detect system memory for swap sizing when: - partitioning_vm_memory is not defined - vm_memory is not defined block: - name: Read system memory ansible.builtin.command: awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo register: partitioning_memtotal_mb changed_when: false failed_when: false - name: Set partitioning vm memory default ansible.builtin.set_fact: partitioning_vm_memory: "{{ (partitioning_memtotal_mb.stdout | default('4096') | int) | float }}" - name: Set partitioning vm_size for physical installs when: - install_type == "physical" - partitioning_vm_size is not defined - vm_size is not defined - install_drive is defined block: - name: Detect install drive size ansible.builtin.command: "lsblk -b -dn -o SIZE {{ install_drive }}" register: partitioning_disk_size_bytes changed_when: false - name: Set partitioning vm_size from install drive size when: - partitioning_disk_size_bytes.stdout is defined - (partitioning_disk_size_bytes.stdout | trim | length) > 0 ansible.builtin.set_fact: partitioning_vm_size: >- {{ (partitioning_disk_size_bytes.stdout | trim | int / 1024 / 1024 / 1024) | round(2, 'floor') }} - name: Partition install drive block: - name: Prepare partitions block: - name: Disable swap ansible.builtin.command: swapoff -a changed_when: false failed_when: false - name: Find mounts under /mnt ansible.builtin.command: findmnt -R /mnt -n -o TARGET register: partitioning_mounted_paths changed_when: false failed_when: false - name: Unmount /mnt mounts when: partitioning_mounted_paths.stdout_lines | length > 0 ansible.posix.mount: path: "{{ item }}" state: unmounted loop: "{{ partitioning_mounted_paths.stdout_lines | reverse }}" loop_control: label: "{{ item }}" failed_when: false - name: Remove LVM volume group community.general.lvg: vg: sys state: absent force: true failed_when: false - name: Close LUKS mapper when: partitioning_luks_enabled | bool community.crypto.luks_device: name: "{{ partitioning_luks_mapper_name }}" state: closed failed_when: false - name: Remove LUKS mapper device when: partitioning_luks_enabled | bool ansible.builtin.command: >- dmsetup remove --force --retry {{ partitioning_luks_mapper_name }} register: partitioning_dmsetup_remove changed_when: partitioning_dmsetup_remove.rc == 0 failed_when: false - name: Remove LUKS signatures when: partitioning_luks_enabled | bool community.crypto.luks_device: device: "{{ partitioning_luks_device }}" state: absent failed_when: false - name: Wipe filesystem signatures ansible.builtin.command: >- find /dev -wholename "{{ install_drive }}*" -exec wipefs --force --all {} \; register: partitioning_wipefs_result changed_when: false failed_when: false - name: Refresh kernel partition table ansible.builtin.command: "{{ item }}" loop: - "partprobe {{ install_drive }}" - "blockdev --rereadpt {{ install_drive }}" - "udevadm settle" register: partitioning_partprobe_result changed_when: false failed_when: false - name: Define partitions block: - name: Create partition layout community.general.parted: device: "{{ install_drive }}" label: gpt number: "{{ item.number }}" part_end: "{{ item.part_end | default(omit) }}" part_start: "{{ item.part_start | default(omit) }}" name: "{{ item.name }}" flags: "{{ item.flags | default(omit) }}" state: present loop: "{{ partitioning_layout }}" rescue: - name: Refresh kernel partition table after failure ansible.builtin.command: "{{ item }}" loop: - "partprobe {{ install_drive }}" - "blockdev --rereadpt {{ install_drive }}" - "udevadm settle" register: partitioning_partprobe_retry changed_when: false failed_when: false - name: Retry partition layout community.general.parted: device: "{{ install_drive }}" label: gpt number: "{{ item.number }}" part_end: "{{ item.part_end | default(omit) }}" part_start: "{{ item.part_start | default(omit) }}" name: "{{ item.name }}" flags: "{{ item.flags | default(omit) }}" state: present loop: "{{ partitioning_layout }}" - name: Settle partition table ansible.builtin.command: "{{ item }}" loop: - "partprobe {{ install_drive }}" - "udevadm settle" register: partitioning_partprobe_settle changed_when: false failed_when: false - name: Configure LUKS encryption when: partitioning_luks_enabled | bool vars: partitioning_luks_passphrase_effective: >- {{ (partitioning_luks_passphrase | default(luks_passphrase | default(''))) | string }} block: - name: Validate LUKS passphrase ansible.builtin.assert: that: - partitioning_luks_passphrase_effective | length > 0 fail_msg: luks_passphrase (or partitioning_luks_passphrase) must be set when LUKS is enabled. no_log: true - name: Ensure LUKS container exists community.crypto.luks_device: device: "{{ partitioning_luks_device }}" state: present type: "{{ partitioning_luks_type }}" cipher: "{{ partitioning_luks_cipher }}" hash: "{{ partitioning_luks_hash }}" keysize: "{{ partitioning_luks_key_size }}" pbkdf: algorithm: "{{ partitioning_luks_pbkdf }}" iteration_time: "{{ (partitioning_luks_iter_time | float) / 1000 }}" passphrase: "{{ partitioning_luks_passphrase_effective }}" register: partitioning_luks_format_result no_log: true - name: Force-close LUKS mapper community.crypto.luks_device: name: "{{ partitioning_luks_mapper_name }}" state: closed failed_when: false - name: Force-remove LUKS mapper device ansible.builtin.command: >- dmsetup remove --force --retry {{ partitioning_luks_mapper_name }} register: partitioning_dmsetup_remove_after_format changed_when: partitioning_dmsetup_remove_after_format.rc == 0 failed_when: false - name: Settle udev after removing LUKS mapper ansible.builtin.command: udevadm settle changed_when: false failed_when: false - name: Ensure LUKS mapper is opened block: - name: Open LUKS device community.crypto.luks_device: device: "{{ partitioning_luks_device }}" state: opened name: "{{ partitioning_luks_mapper_name }}" passphrase: "{{ partitioning_luks_passphrase_effective }}" allow_discards: "{{ 'discard' in (partitioning_luks_options | default('') | lower) }}" register: partitioning_luks_open_result no_log: true rescue: - name: Force-close stale LUKS mapper community.crypto.luks_device: name: "{{ partitioning_luks_mapper_name }}" state: closed failed_when: false - name: Force-remove stale LUKS mapper device ansible.builtin.command: >- dmsetup remove --force --retry {{ partitioning_luks_mapper_name }} register: partitioning_dmsetup_remove_retry changed_when: partitioning_dmsetup_remove_retry.rc == 0 failed_when: false - name: Settle udev after removing stale LUKS mapper ansible.builtin.command: udevadm settle changed_when: false failed_when: false - name: Retry opening LUKS device community.crypto.luks_device: device: "{{ partitioning_luks_device }}" state: opened name: "{{ partitioning_luks_mapper_name }}" passphrase: "{{ partitioning_luks_passphrase_effective }}" allow_discards: "{{ 'discard' in (partitioning_luks_options | default('') | lower) }}" register: partitioning_luks_open_retry no_log: true - name: Get LUKS UUID ansible.builtin.command: "cryptsetup luksUUID {{ partitioning_luks_device }}" register: partitioning_luks_uuid_result changed_when: false - name: Store LUKS UUID ansible.builtin.set_fact: partitioning_luks_uuid: "{{ partitioning_luks_uuid_result.stdout | trim }}" - name: Create LVM logical volumes when: filesystem != 'btrfs' block: - name: Create LVM volume group community.general.lvg: vg: sys pvs: "{{ partitioning_root_device }}" - name: Create LVM logical volumes when: cis | bool or item.lv not in ['home', 'var', 'var_log', 'var_log_audit'] community.general.lvol: vg: sys lv: "{{ item.lv }}" size: "{{ item.size }}" state: present loop: - lv: root size: >- {{ [(((((partitioning_vm_size_effective | float) - (partitioning_reserved_gb | float) - ((cis | bool) | ternary(7.5, 0)) - (((partitioning_vm_memory_effective | float / 1024) > 16.0) | ternary(((partitioning_vm_memory_effective | float / 2048) | int), (partitioning_vm_memory_effective | float / 1024)))) < 4) | ternary(4,((((partitioning_vm_size_effective | float) - (partitioning_reserved_gb | float) - ((cis | bool) | ternary(7.5, 0)) - (((partitioning_vm_memory_effective | float / 1024) > 16.0) | ternary( ((partitioning_vm_memory_effective | float / 2048) | int), (partitioning_vm_memory_effective | float / 1024) ))) > 12) | ternary(((partitioning_vm_size_effective | float) * 0.4) | round(0, 'ceil'),((partitioning_vm_size_effective | float) - (partitioning_reserved_gb | float) - ((cis | bool) | ternary(7.5, 0)) - (((partitioning_vm_memory_effective | float / 1024) > 16.0) | ternary(((partitioning_vm_memory_effective | float / 2048) | int), (partitioning_vm_memory_effective | float / 1024))))))))), 4 ] | max | string + 'G' }} - lv: swap size: >- {{ ((((partitioning_vm_size_effective | float) - (partitioning_reserved_gb | float) - ((cis | bool) | ternary(7.5, 0))) - (((partitioning_vm_memory_effective | float / 1024) > 16.0) | ternary(((partitioning_vm_memory_effective | float / 2048) | int), (partitioning_vm_memory_effective | float / 1024)))) < 4) | ternary((((partitioning_vm_size_effective | float) - (partitioning_reserved_gb | float) - ((cis | bool) | ternary(7.5, 0))) - 4), (((partitioning_vm_memory_effective | float / 1024) > 16.0) | ternary(((partitioning_vm_memory_effective | float / 2048) | int), (partitioning_vm_memory_effective | float / 1024)))) | string + 'G' }} - lv: home size: "{{ ([([(((partitioning_vm_size_effective | float) - 20) * 0.1), 2] | max), 20] | min) | string + 'G' }}" - {lv: var, size: "2G"} - {lv: var_log, size: "2G"} - {lv: var_log_audit, size: "1.5G"} - name: Create filesystems block: - name: Create FAT32 filesystem in boot partition community.general.filesystem: dev: "{{ install_drive }}{{ partitioning_boot_partition_suffix }}" fstype: vfat opts: -F32 -n BOOT force: true - name: Create filesystem for /boot partition when: partitioning_separate_boot | bool community.general.filesystem: dev: "{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}" fstype: "{{ partitioning_boot_fs_fstype }}" force: true - name: Remove unsupported ext4 features from /boot when: - partitioning_separate_boot | bool - partitioning_boot_fs_fstype == 'ext4' - os | lower in ['almalinux', 'debian11', 'rhel8', 'rhel9', 'rocky'] ansible.builtin.command: >- tune2fs -O "^orphan_file,^metadata_csum_seed" "{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}" register: partitioning_boot_ext4_tune_result changed_when: partitioning_boot_ext4_tune_result.rc == 0 - name: Create swap filesystem when: filesystem != 'btrfs' community.general.filesystem: fstype: swap dev: /dev/sys/swap - name: Create filesystem ansible.builtin.include_tasks: "{{ filesystem }}.yml" - name: Get UUID for boot filesystem ansible.builtin.command: blkid -s UUID -o value '{{ install_drive }}{{ partitioning_boot_partition_suffix }}' register: partitioning_boot_uuid changed_when: false - name: Get UUID for /boot filesystem when: partitioning_separate_boot | bool ansible.builtin.command: >- blkid -s UUID -o value '{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}' register: partitioning_boot_fs_uuid changed_when: false - name: Get UUID for main filesystem ansible.builtin.command: blkid -s UUID -o value '{{ partitioning_root_device }}' register: partitioning_main_uuid changed_when: false - name: Get UUIDs for LVM filesystems when: filesystem != 'btrfs' and (cis | bool or item not in ['home', 'var', 'var_log', 'var_log_audit']) ansible.builtin.command: blkid -s UUID -o value /dev/sys/{{ item }} loop: - root - swap - home - var - var_log - var_log_audit register: partitioning_uuid_result changed_when: false - name: Assign UUIDs to Variables when: filesystem != 'btrfs' ansible.builtin.set_fact: partitioning_uuid_root: "{{ partitioning_uuid_result.results[0].stdout_lines }}" partitioning_uuid_swap: "{{ partitioning_uuid_result.results[1].stdout_lines }}" partitioning_uuid_home: "{{ partitioning_uuid_result.results[2].stdout_lines if cis | bool else '' }}" partitioning_uuid_var: "{{ partitioning_uuid_result.results[3].stdout_lines if cis | bool else '' }}" partitioning_uuid_var_log: "{{ partitioning_uuid_result.results[4].stdout_lines if cis | bool else '' }}" partitioning_uuid_var_log_audit: "{{ partitioning_uuid_result.results[5].stdout_lines if cis | bool else '' }}" - name: Mount filesystems block: - name: Mount filesystems and subvolumes when: - >- cis | bool or ( not cis and ( (filesystem == 'btrfs' and item.path in ['/home', '/var/log', '/var/cache/pacman/pkg']) or (item.path not in ['/home', '/var', '/var/log', '/var/log/audit', '/var/cache/pacman/pkg']) ) ) - >- not (item.path in ['/swap', '/var/cache/pacman/pkg'] and filesystem != 'btrfs') ansible.posix.mount: path: /mnt{{ item.path }} src: "{{ 'UUID=' + (partitioning_main_uuid.stdout if filesystem == 'btrfs' else item.uuid) }}" fstype: "{{ filesystem }}" opts: "{{ item.opts }}" state: mounted loop: - path: "" uuid: "{{ partitioning_uuid_root[0] | default(omit) }}" opts: >- {{ 'defaults' if filesystem != 'btrfs' else [ 'rw', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@' ] | join(',') }} - path: /swap opts: >- {{ [ 'rw', 'nosuid', 'nodev', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@swap' ] | join(',') }} - path: /home uuid: "{{ partitioning_uuid_home[0] | default(omit) }}" opts: >- {{ 'defaults,nosuid,nodev' if filesystem != 'btrfs' else [ 'rw', 'nosuid', 'nodev', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@home' ] | join(',') }} - path: /var uuid: "{{ partitioning_uuid_var[0] | default(omit) }}" opts: >- {{ 'defaults,nosuid,nodev' if filesystem != 'btrfs' else [ 'rw', 'nosuid', 'nodev', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@var' ] | join(',') }} - path: /var/log uuid: "{{ partitioning_uuid_var_log[0] | default(omit) }}" opts: >- {{ 'defaults,nosuid,nodev,noexec' if filesystem != 'btrfs' else [ 'rw', 'nosuid', 'nodev', 'noexec', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@var_log' ] | join(',') }} - path: /var/cache/pacman/pkg uuid: "{{ partitioning_uuid_root | default([]) | first | default(omit) }}" opts: >- {{ 'defaults,nosuid,nodev,noexec' if filesystem != 'btrfs' else [ 'rw', 'nosuid', 'nodev', 'noexec', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@pkg' ] | join(',') }} - path: /var/log/audit uuid: "{{ partitioning_uuid_var_log_audit[0] | default(omit) }}" opts: >- {{ 'defaults,nosuid,nodev,noexec' if filesystem != 'btrfs' else [ 'rw', 'nosuid', 'nodev', 'noexec', 'relatime', 'compress=zstd:15', 'ssd', 'space_cache=v2', 'discard=async', 'subvol=@var_log_audit' ] | join(',') }} - name: Mount /boot filesystem when: partitioning_separate_boot | bool ansible.posix.mount: path: /mnt/boot src: "UUID={{ partitioning_boot_fs_uuid.stdout }}" fstype: "{{ partitioning_boot_fs_fstype }}" opts: defaults state: mounted - name: Mount boot filesystem ansible.posix.mount: path: "/mnt{{ partitioning_efi_mountpoint }}" src: UUID={{ partitioning_boot_uuid.stdout }} fstype: vfat state: mounted - name: Activate swap vars: partitioning_swap_cmd: >- {{ 'swapon /mnt/swap/swapfile' if filesystem == 'btrfs' else 'swapon -U ' + partitioning_uuid_swap[0] }} ansible.builtin.command: "{{ partitioning_swap_cmd }}" register: partitioning_swap_activate_result changed_when: partitioning_swap_activate_result.rc == 0