Compare commits
6 Commits
5b8438ac3b
...
0e3edb41f7
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e3edb41f7 | |||
| 2bf0cb901e | |||
| 1216c79619 | |||
| 4efd64664d | |||
| dc5aa5077e | |||
| c65934c290 |
10
main.yml
10
main.yml
@@ -1,4 +1,14 @@
|
|||||||
---
|
---
|
||||||
|
# Bootstrap pipeline — role execution order:
|
||||||
|
# 1. global_defaults — normalize + validate system/hypervisor/disk input
|
||||||
|
# 2. system_check — pre-flight hardware/environment safety checks
|
||||||
|
# 3. virtualization — create VM on hypervisor (libvirt/proxmox/vmware/xen)
|
||||||
|
# 4. environment — detect live ISO, configure installer network, install tools
|
||||||
|
# 5. partitioning — partition disk, create FS, LUKS, LVM, mount everything
|
||||||
|
# 6. bootstrap — debootstrap/pacstrap/dnf install the target OS into /mnt
|
||||||
|
# 7. configuration — users, network, encryption, fstab, bootloader, services
|
||||||
|
# 8. cis — CIS hardening (optional, per system.features.cis.enabled)
|
||||||
|
# 9. cleanup — unmount, remove cloud-init artifacts, reboot/shutdown
|
||||||
- name: Create and configure VMs
|
- name: Create and configure VMs
|
||||||
hosts: "{{ bootstrap_target | default('all') }}"
|
hosts: "{{ bootstrap_target | default('all') }}"
|
||||||
strategy: free # noqa: run-once[play]
|
strategy: free # noqa: run-once[play]
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
cleanup_xen_disks: "{{ cleanup_xen_disks | default([]) + [cleanup_xen_disk_cfg] }}"
|
cleanup_xen_disks: "{{ cleanup_xen_disks | default([]) + [cleanup_xen_disk_cfg] }}"
|
||||||
vars:
|
vars:
|
||||||
device_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
device_letter_map: "{{ disk_letter_map }}"
|
||||||
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
||||||
cleanup_xen_disk_cfg: >-
|
cleanup_xen_disk_cfg: >-
|
||||||
{{
|
{{
|
||||||
@@ -58,3 +58,8 @@
|
|||||||
- /tmp/xen-{{ hostname }}.cfg
|
- /tmp/xen-{{ hostname }}.cfg
|
||||||
register: cleanup_xen_start_result
|
register: cleanup_xen_start_result
|
||||||
changed_when: cleanup_xen_start_result.rc == 0
|
changed_when: cleanup_xen_start_result.rc == 0
|
||||||
|
|
||||||
|
- name: Remove temporary Xen configuration file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /tmp/xen-{{ hostname }}.cfg
|
||||||
|
state: absent
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Configure disk encryption
|
- name: Configure disk encryption
|
||||||
when: system_cfg.luks.enabled | bool
|
when: system_cfg.luks.enabled | bool
|
||||||
|
no_log: true
|
||||||
vars:
|
vars:
|
||||||
configuration_luks_passphrase: >-
|
configuration_luks_passphrase: >-
|
||||||
{{ system_cfg.luks.passphrase | string }}
|
{{ system_cfg.luks.passphrase | string }}
|
||||||
|
|||||||
@@ -80,10 +80,11 @@
|
|||||||
host stderr={{ configuration_luks_tpm2_enroll_host.stderr | default('') }}
|
host stderr={{ configuration_luks_tpm2_enroll_host.stderr | default('') }}
|
||||||
rescue:
|
rescue:
|
||||||
- name: Warn about TPM2 enrollment failure
|
- name: Warn about TPM2 enrollment failure
|
||||||
ansible.builtin.debug:
|
ansible.builtin.fail:
|
||||||
msg: >-
|
msg: >-
|
||||||
TPM2 enrollment failed — falling back to keyfile auto-decrypt.
|
WARNING: TPM2 enrollment failed — falling back to keyfile auto-decrypt.
|
||||||
The system will use a keyfile instead of TPM2 for automatic LUKS unlock.
|
The system will use a keyfile instead of TPM2 for automatic LUKS unlock.
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
- name: Fallback to keyfile auto-decrypt
|
- name: Fallback to keyfile auto-decrypt
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
marker: "# {mark} CUSTOM VIM CONFIG"
|
marker: "# {mark} CUSTOM VIM CONFIG"
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|
||||||
|
# Tuned for VM workloads: low swappiness, aggressive writeback, large page-cluster
|
||||||
|
# for zram. Override post-bootstrap via the linux role or sysctl if needed.
|
||||||
- name: Add memory tuning parameters
|
- name: Add memory tuning parameters
|
||||||
ansible.builtin.blockinfile:
|
ansible.builtin.blockinfile:
|
||||||
path: /mnt/etc/sysctl.d/90-memory.conf
|
path: /mnt/etc/sysctl.d/90-memory.conf
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: Copy Custom Shell config
|
- name: Copy Custom Shell config
|
||||||
ansible.builtin.template:
|
ansible.builtin.copy:
|
||||||
src: custom.sh.j2
|
src: custom.sh
|
||||||
dest: /mnt/etc/profile.d/custom.sh
|
dest: /mnt/etc/profile.d/custom.sh
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|||||||
@@ -27,11 +27,15 @@
|
|||||||
- name: Set Alpine DNS resolvers
|
- name: Set Alpine DNS resolvers
|
||||||
vars:
|
vars:
|
||||||
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
||||||
when: configuration_dns_list | length > 0
|
configuration_dns_search: "{{ system_cfg.network.dns.search | default([]) }}"
|
||||||
|
when: configuration_dns_list | length > 0 or configuration_dns_search | length > 0
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/resolv.conf
|
dest: /mnt/etc/resolv.conf
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
content: |
|
content: |
|
||||||
|
{% if configuration_dns_search | length > 0 %}
|
||||||
|
search {{ configuration_dns_search | join(' ') }}
|
||||||
|
{% endif %}
|
||||||
{% for resolver in configuration_dns_list %}
|
{% for resolver in configuration_dns_list %}
|
||||||
nameserver {{ resolver }}
|
nameserver {{ resolver }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
- name: Write dhcpcd configuration
|
- name: Write dhcpcd configuration
|
||||||
vars:
|
vars:
|
||||||
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
||||||
|
configuration_dns_search: "{{ system_cfg.network.dns.search | default([]) }}"
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/dhcpcd.conf
|
dest: /mnt/etc/dhcpcd.conf
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
@@ -20,6 +21,9 @@
|
|||||||
{% if loop.index0 == 0 and configuration_dns_list | length > 0 %}
|
{% if loop.index0 == 0 and configuration_dns_list | length > 0 %}
|
||||||
static domain_name_servers={{ configuration_dns_list | join(' ') }}
|
static domain_name_servers={{ configuration_dns_list | join(' ') }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if loop.index0 == 0 and configuration_dns_search | length > 0 %}
|
||||||
|
static domain_search={{ configuration_dns_search | join(' ') }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
register: configuration_setfiles_result
|
register: configuration_setfiles_result
|
||||||
changed_when: configuration_setfiles_result.rc == 0
|
changed_when: configuration_setfiles_result.rc == 0
|
||||||
|
|
||||||
|
# Fedora: setfiles segfaults during bootstrap chroot relabeling, so SELinux
|
||||||
|
# is left permissive and expected to relabel on first boot.
|
||||||
- name: Disable SELinux
|
- name: Disable SELinux
|
||||||
when: os == "fedora" or not system_cfg.features.selinux.enabled | bool
|
when: os == "fedora" or not system_cfg.features.selinux.enabled | bool
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# Bootstrap-only: permissive SSH for initial Ansible access.
|
||||||
|
# Post-bootstrap hardening (key-only, no root login) is handled by the linux role.
|
||||||
- name: Ensure SSH password authentication is enabled
|
- name: Ensure SSH password authentication is enabled
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /mnt/etc/ssh/sshd_config
|
path: /mnt/etc/ssh/sshd_config
|
||||||
|
|||||||
@@ -112,6 +112,42 @@ system_defaults:
|
|||||||
chroot:
|
chroot:
|
||||||
tool: "arch-chroot" # arch-chroot|chroot|systemd-nspawn
|
tool: "arch-chroot" # arch-chroot|chroot|systemd-nspawn
|
||||||
|
|
||||||
|
# Per-hypervisor required fields — drives data-driven validation.
|
||||||
|
# All virtual types additionally require network bridge or interfaces.
|
||||||
|
hypervisor_required_fields:
|
||||||
|
proxmox:
|
||||||
|
hypervisor: [url, username, password, host, storage]
|
||||||
|
system: [id]
|
||||||
|
vmware:
|
||||||
|
hypervisor: [url, username, password, datacenter, cluster, storage]
|
||||||
|
system: []
|
||||||
|
xen:
|
||||||
|
hypervisor: []
|
||||||
|
system: []
|
||||||
|
libvirt:
|
||||||
|
hypervisor: []
|
||||||
|
system: []
|
||||||
|
|
||||||
|
# Hypervisor-to-disk device prefix mapping for virtual machines.
|
||||||
|
# Physical installs must set system.disks[].device explicitly.
|
||||||
|
hypervisor_disk_device_map:
|
||||||
|
libvirt: "/dev/vd"
|
||||||
|
xen: "/dev/xvd"
|
||||||
|
proxmox: "/dev/sd"
|
||||||
|
vmware: "/dev/sd"
|
||||||
|
|
||||||
|
# Mountpoints managed by the partitioning role — forbidden for extra disks.
|
||||||
|
reserved_mounts:
|
||||||
|
- /boot
|
||||||
|
- /boot/efi
|
||||||
|
- /home
|
||||||
|
- /var
|
||||||
|
- /var/log
|
||||||
|
- /var/log/audit
|
||||||
|
|
||||||
|
# Drive letter sequence for disk device naming (max 26 disks).
|
||||||
|
disk_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
system_disk_defaults:
|
system_disk_defaults:
|
||||||
size: 0
|
size: 0
|
||||||
device: ""
|
device: ""
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
- name: Normalize system disks input
|
- name: Normalize system disks input
|
||||||
vars:
|
vars:
|
||||||
system_disks: "{{ system_cfg.disks | default([]) }}"
|
system_disks: "{{ system_cfg.disks | default([]) }}"
|
||||||
system_disk_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
system_disk_letter_map: "{{ disk_letter_map }}"
|
||||||
system_disk_device_prefix: >-
|
system_disk_device_prefix: >-
|
||||||
{{
|
{{
|
||||||
{'libvirt': '/dev/vd', 'xen': '/dev/xvd', 'proxmox': '/dev/sd', 'vmware': '/dev/sd'}.get(hypervisor_type, '')
|
hypervisor_disk_device_map.get(hypervisor_type, '')
|
||||||
if system_cfg.type == 'virtual'
|
if system_cfg.type == 'virtual'
|
||||||
else ''
|
else ''
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -12,15 +12,22 @@
|
|||||||
}}
|
}}
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
system_cfg:
|
system_cfg:
|
||||||
|
# --- Identity & platform ---
|
||||||
type: "{{ system_type }}"
|
type: "{{ system_type }}"
|
||||||
os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}"
|
os: "{{ system_os_input if system_os_input | length > 0 else ('archlinux' if system_type == 'physical' else '') }}"
|
||||||
version: "{{ system_raw.version | default('') | string }}"
|
version: "{{ system_raw.version | default('') | string }}"
|
||||||
filesystem: "{{ system_raw.filesystem | default('') | string | lower }}"
|
filesystem: "{{ system_raw.filesystem | default('') | string | lower }}"
|
||||||
name: "{{ system_name }}"
|
name: "{{ system_name }}"
|
||||||
id: "{{ system_raw.id | default('') | string }}"
|
id: "{{ system_raw.id | default('') | string }}"
|
||||||
|
# --- VM sizing (ignored for physical) ---
|
||||||
cpus: "{{ [system_raw.cpus | default(0) | int, 0] | max }}"
|
cpus: "{{ [system_raw.cpus | default(0) | int, 0] | max }}"
|
||||||
memory: "{{ [system_raw.memory | default(0) | int, 0] | max }}"
|
memory: "{{ [system_raw.memory | default(0) | int, 0] | max }}"
|
||||||
balloon: "{{ [system_raw.balloon | default(0) | int, 0] | max }}"
|
balloon: "{{ [system_raw.balloon | default(0) | int, 0] | max }}"
|
||||||
|
# --- Network ---
|
||||||
|
# Flat fields (bridge, ip, etc.) and interfaces[] are mutually exclusive.
|
||||||
|
# When interfaces[] is set, flat fields are populated from the first
|
||||||
|
# interface in the "Populate primary network fields" task below.
|
||||||
|
# When only flat fields are set, a synthetic interfaces[] entry is built.
|
||||||
network:
|
network:
|
||||||
bridge: "{{ system_raw.network.bridge | default('') | string }}"
|
bridge: "{{ system_raw.network.bridge | default('') | string }}"
|
||||||
vlan: "{{ system_raw.network.vlan | default('') | string }}"
|
vlan: "{{ system_raw.network.vlan | default('') | string }}"
|
||||||
@@ -56,6 +63,7 @@
|
|||||||
else []
|
else []
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
# --- Locale & environment ---
|
||||||
timezone: "{{ system_raw.timezone | default('Europe/Vienna') | string }}"
|
timezone: "{{ system_raw.timezone | default('Europe/Vienna') | string }}"
|
||||||
locale: "{{ system_raw.locale | default('en_US.UTF-8') | string }}"
|
locale: "{{ system_raw.locale | default('en_US.UTF-8') | string }}"
|
||||||
keymap: "{{ system_raw.keymap | default('us') | string }}"
|
keymap: "{{ system_raw.keymap | default('us') | string }}"
|
||||||
@@ -71,10 +79,12 @@
|
|||||||
| reject('equalto', '')
|
| reject('equalto', '')
|
||||||
| list
|
| list
|
||||||
}}
|
}}
|
||||||
|
# --- Storage & accounts ---
|
||||||
disks: "{{ system_raw.disks | default([]) }}"
|
disks: "{{ system_raw.disks | default([]) }}"
|
||||||
users: "{{ system_raw.users | default([]) }}"
|
users: "{{ system_raw.users | default([]) }}"
|
||||||
root:
|
root:
|
||||||
password: "{{ system_raw.root.password | string }}"
|
password: "{{ system_raw.root.password | string }}"
|
||||||
|
# --- LUKS disk encryption ---
|
||||||
luks:
|
luks:
|
||||||
enabled: "{{ system_raw.luks.enabled | bool }}"
|
enabled: "{{ system_raw.luks.enabled | bool }}"
|
||||||
passphrase: "{{ system_raw.luks.passphrase | string }}"
|
passphrase: "{{ system_raw.luks.passphrase | string }}"
|
||||||
@@ -94,6 +104,7 @@
|
|||||||
pbkdf: "{{ system_raw.luks.pbkdf | string }}"
|
pbkdf: "{{ system_raw.luks.pbkdf | string }}"
|
||||||
urandom: "{{ system_raw.luks.urandom | bool }}"
|
urandom: "{{ system_raw.luks.urandom | bool }}"
|
||||||
verify: "{{ system_raw.luks.verify | bool }}"
|
verify: "{{ system_raw.luks.verify | bool }}"
|
||||||
|
# --- Feature flags ---
|
||||||
features:
|
features:
|
||||||
cis:
|
cis:
|
||||||
enabled: "{{ system_raw.features.cis.enabled | bool }}"
|
enabled: "{{ system_raw.features.cis.enabled | bool }}"
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
---
|
---
|
||||||
|
# Centralized normalization — all input dicts (system, hypervisor, disks)
|
||||||
|
# are normalized here into system_cfg, hypervisor_cfg, etc.
|
||||||
|
# Downstream roles consume these computed facts directly and do NOT need
|
||||||
|
# per-role _normalize.yml (except CIS, which has its own input dict).
|
||||||
- name: Global defaults loaded
|
- name: Global defaults loaded
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: Global defaults loaded.
|
msg: Global defaults loaded.
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
---
|
---
|
||||||
|
# Two code paths:
|
||||||
|
# 1. Fresh run (system_cfg undefined): normalize from raw `system` input.
|
||||||
|
# 2. Pre-computed (system_cfg already set, e.g. from main project's deploy_iac):
|
||||||
|
# merge with bootstrap system_defaults to fill missing fields (luks, features,
|
||||||
|
# etc.) that bootstrap expects but the main project doesn't set, then derive
|
||||||
|
# convenience facts (hostname, os, os_version).
|
||||||
- name: Normalize system and disk configuration
|
- name: Normalize system and disk configuration
|
||||||
when: system_cfg is not defined
|
when: system_cfg is not defined
|
||||||
block:
|
block:
|
||||||
|
|||||||
@@ -152,70 +152,43 @@
|
|||||||
fail_msg: "rhel_iso is required when os=rhel."
|
fail_msg: "rhel_iso is required when os=rhel."
|
||||||
quiet: true
|
quiet: true
|
||||||
|
|
||||||
- name: Validate Proxmox hypervisor inputs
|
- name: Validate hypervisor-specific required fields
|
||||||
when:
|
when:
|
||||||
- system_cfg.type == "virtual"
|
- system_cfg.type == "virtual"
|
||||||
- hypervisor_type == "proxmox"
|
- hypervisor_type in hypervisor_required_fields
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- (hypervisor_cfg[item] | default('') | string | length) > 0
|
||||||
|
fail_msg: "Missing required {{ hypervisor_type }} field: hypervisor.{{ item }}"
|
||||||
|
quiet: true
|
||||||
|
loop: "{{ hypervisor_required_fields[hypervisor_type].hypervisor | default([]) }}"
|
||||||
|
loop_control:
|
||||||
|
label: "hypervisor.{{ item }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Validate hypervisor-specific required system fields
|
||||||
|
when:
|
||||||
|
- system_cfg.type == "virtual"
|
||||||
|
- hypervisor_type in hypervisor_required_fields
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- (system_cfg[item] | default('') | string | length) > 0
|
||||||
|
fail_msg: "Missing required {{ hypervisor_type }} field: system.{{ item }}"
|
||||||
|
quiet: true
|
||||||
|
loop: "{{ hypervisor_required_fields[hypervisor_type].system | default([]) }}"
|
||||||
|
loop_control:
|
||||||
|
label: "system.{{ item }}"
|
||||||
|
|
||||||
|
- name: Validate virtual machine network requirement
|
||||||
|
when: system_cfg.type == "virtual"
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- hypervisor_cfg.url | string | length > 0
|
|
||||||
- hypervisor_cfg.username | string | length > 0
|
|
||||||
- hypervisor_cfg.password | string | length > 0
|
|
||||||
- hypervisor_cfg.host | string | length > 0
|
|
||||||
- hypervisor_cfg.storage | string | length > 0
|
|
||||||
- system_cfg.id | string | length > 0
|
|
||||||
- >-
|
- >-
|
||||||
(system_cfg.network.bridge | default('') | string | length > 0)
|
(system_cfg.network.bridge | default('') | string | length > 0)
|
||||||
or (system_cfg.network.interfaces | default([]) | length > 0)
|
or (system_cfg.network.interfaces | default([]) | length > 0)
|
||||||
fail_msg: >-
|
fail_msg: >-
|
||||||
Missing required Proxmox inputs. Define hypervisor.(url,username,password,host,storage),
|
Missing required {{ hypervisor_type }} network configuration.
|
||||||
system.id, and system.network.bridge (or system.network.interfaces[]).
|
Define system.network.bridge (or system.network.interfaces[]).
|
||||||
quiet: true
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Validate VMware hypervisor inputs
|
|
||||||
when:
|
|
||||||
- system_cfg.type == "virtual"
|
|
||||||
- hypervisor_type == "vmware"
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- hypervisor_cfg.url | string | length > 0
|
|
||||||
- hypervisor_cfg.username | string | length > 0
|
|
||||||
- hypervisor_cfg.password | string | length > 0
|
|
||||||
- hypervisor_cfg.datacenter | string | length > 0
|
|
||||||
- hypervisor_cfg.cluster | string | length > 0
|
|
||||||
- hypervisor_cfg.storage | string | length > 0
|
|
||||||
- >-
|
|
||||||
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
||||||
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
||||||
fail_msg: >-
|
|
||||||
Missing required VMware inputs. Define hypervisor.(url,username,password,datacenter,cluster,storage)
|
|
||||||
and system.network.bridge (or system.network.interfaces[]).
|
|
||||||
quiet: true
|
|
||||||
no_log: true
|
|
||||||
|
|
||||||
- name: Validate Xen hypervisor inputs
|
|
||||||
when:
|
|
||||||
- system_cfg.type == "virtual"
|
|
||||||
- hypervisor_type == "xen"
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- >-
|
|
||||||
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
||||||
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
||||||
fail_msg: "Missing required Xen inputs. Define system.network.bridge (or system.network.interfaces[])."
|
|
||||||
quiet: true
|
|
||||||
|
|
||||||
- name: Validate libvirt hypervisor inputs
|
|
||||||
when:
|
|
||||||
- system_cfg.type == "virtual"
|
|
||||||
- hypervisor_type == "libvirt"
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- >-
|
|
||||||
(system_cfg.network.bridge | default('') | string | length > 0)
|
|
||||||
or (system_cfg.network.interfaces | default([]) | length > 0)
|
|
||||||
fail_msg: "Missing required libvirt inputs. Define system.network.bridge (or system.network.interfaces[])."
|
|
||||||
quiet: true
|
quiet: true
|
||||||
|
|
||||||
- name: Validate virtual installer ISO requirement
|
- name: Validate virtual installer ISO requirement
|
||||||
@@ -250,6 +223,8 @@
|
|||||||
- system_cfg.disks is defined and (system_cfg.disks | length) > 0
|
- system_cfg.disks is defined and (system_cfg.disks | length) > 0
|
||||||
- (system_cfg.disks[0].size | float) > 0
|
- (system_cfg.disks[0].size | float) > 0
|
||||||
- (system_cfg.disks[0].size | float) >= 20
|
- (system_cfg.disks[0].size | float) >= 20
|
||||||
|
# Btrfs minimum disk: swap_size + 5.5 GiB overhead (subvolumes + metadata).
|
||||||
|
# Swap sizing: memory < 16 GiB → max(memory_GiB, 2); memory >= 16 GiB → memory/2.
|
||||||
- >-
|
- >-
|
||||||
system_cfg.filesystem != "btrfs"
|
system_cfg.filesystem != "btrfs"
|
||||||
or (
|
or (
|
||||||
@@ -333,9 +308,9 @@
|
|||||||
- name: Validate disk mount definitions
|
- name: Validate disk mount definitions
|
||||||
when: system_cfg.disks is defined
|
when: system_cfg.disks is defined
|
||||||
vars:
|
vars:
|
||||||
reserved_mounts: >-
|
all_reserved_mounts: >-
|
||||||
{{
|
{{
|
||||||
['/boot', '/boot/efi', '/home', '/var', '/var/log', '/var/log/audit']
|
reserved_mounts
|
||||||
+ (['/var/cache/pacman/pkg'] if os == 'archlinux' else [])
|
+ (['/var/cache/pacman/pkg'] if os == 'archlinux' else [])
|
||||||
}}
|
}}
|
||||||
disk_mount: "{{ (item.mount.path | default('') | string) | trim }}"
|
disk_mount: "{{ (item.mount.path | default('') | string) | trim }}"
|
||||||
@@ -346,7 +321,7 @@
|
|||||||
that:
|
that:
|
||||||
- disk_mount == "" or disk_mount.startswith("/")
|
- disk_mount == "" or disk_mount.startswith("/")
|
||||||
- disk_mount == "" or disk_mount != "/"
|
- disk_mount == "" or disk_mount != "/"
|
||||||
- disk_mount == "" or disk_mount not in reserved_mounts
|
- disk_mount == "" or disk_mount not in all_reserved_mounts
|
||||||
- disk_mount == "" or disk_fstype in ["btrfs", "ext4", "xfs"]
|
- disk_mount == "" or disk_fstype in ["btrfs", "ext4", "xfs"]
|
||||||
- disk_mount == "" or system_cfg.type == "virtual" or (disk_device | length) > 0
|
- disk_mount == "" or system_cfg.type == "virtual" or (disk_device | length) > 0
|
||||||
- disk_mount == "" or system_cfg.type != "virtual" or (disk_size | float) > 0
|
- disk_mount == "" or system_cfg.type != "virtual" or (disk_size | float) > 0
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
tune2fs -O "^orphan_file,^metadata_csum_seed"
|
tune2fs -O "^orphan_file,^metadata_csum_seed"
|
||||||
"{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}"
|
"{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}"
|
||||||
register: partitioning_boot_ext4_tune_result
|
register: partitioning_boot_ext4_tune_result
|
||||||
changed_when: partitioning_boot_ext4_tune_result.rc == 0
|
changed_when: false
|
||||||
|
|
||||||
- name: Create swap filesystem
|
- name: Create swap filesystem
|
||||||
when:
|
when:
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
---
|
---
|
||||||
- name: Mount filesystems
|
- name: Mount filesystems
|
||||||
block:
|
block:
|
||||||
|
# CIS mode: mount all paths (separate partitions for /home, /var, etc.)
|
||||||
|
# Non-CIS btrfs: only mount subvolume paths (/home, /var/log, /var/cache/pacman/pkg)
|
||||||
|
# Non-CIS LVM: skip CIS-only paths (/home, /var, /var/log, /var/log/audit, /var/cache/pacman/pkg)
|
||||||
- name: Mount filesystems and subvolumes
|
- name: Mount filesystems and subvolumes
|
||||||
when:
|
when:
|
||||||
- >-
|
- >-
|
||||||
@@ -121,4 +124,6 @@
|
|||||||
{{ 'swapon /mnt/swap/swapfile' if system_cfg.filesystem == 'btrfs' else 'swapon -U ' + partitioning_uuid_swap[0] }}
|
{{ 'swapon /mnt/swap/swapfile' if system_cfg.filesystem == 'btrfs' else 'swapon -U ' + partitioning_uuid_swap[0] }}
|
||||||
ansible.builtin.command: "{{ partitioning_swap_cmd }}"
|
ansible.builtin.command: "{{ partitioning_swap_cmd }}"
|
||||||
register: partitioning_swap_activate_result
|
register: partitioning_swap_activate_result
|
||||||
|
# swapon returns 255 if swap is already active
|
||||||
|
failed_when: partitioning_swap_activate_result.rc not in [0, 255]
|
||||||
changed_when: partitioning_swap_activate_result.rc == 0
|
changed_when: partitioning_swap_activate_result.rc == 0
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
---
|
---
|
||||||
|
# Cloud-init support matrix:
|
||||||
|
# libvirt — cloud-init ISO attached as CDROM (user-data + network-config)
|
||||||
|
# proxmox — cloud-init via Proxmox API (cicustom, ciuser, cipassword, etc.)
|
||||||
|
# vmware — no cloud-init; configuration is applied post-install via chroot
|
||||||
|
# xen — no cloud-init; configuration is applied post-install via chroot
|
||||||
virtualization_libvirt_image_dir: >-
|
virtualization_libvirt_image_dir: >-
|
||||||
{{
|
{{
|
||||||
system_cfg.path
|
system_cfg.path
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
virtualization_libvirt_disks: "{{ virtualization_libvirt_disks | default([]) + [virtualization_libvirt_disk_cfg] }}"
|
virtualization_libvirt_disks: "{{ virtualization_libvirt_disks | default([]) + [virtualization_libvirt_disk_cfg] }}"
|
||||||
vars:
|
vars:
|
||||||
device_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
device_letter_map: "{{ disk_letter_map }}"
|
||||||
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
||||||
virtualization_libvirt_disk_cfg: >-
|
virtualization_libvirt_disk_cfg: >-
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
virtualization_xen_disks: "{{ virtualization_xen_disks | default([]) + [virtualization_xen_disk_cfg] }}"
|
virtualization_xen_disks: "{{ virtualization_xen_disks | default([]) + [virtualization_xen_disk_cfg] }}"
|
||||||
vars:
|
vars:
|
||||||
device_letter_map: "abcdefghijklmnopqrstuvwxyz"
|
device_letter_map: "{{ disk_letter_map }}"
|
||||||
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
device_letter: "{{ device_letter_map[ansible_loop.index0] }}"
|
||||||
virtualization_xen_disk_cfg: >-
|
virtualization_xen_disk_cfg: >-
|
||||||
{{
|
{{
|
||||||
|
|||||||
Reference in New Issue
Block a user