Compare commits
13 Commits
0e3edb41f7
...
b72816e985
| Author | SHA1 | Date | |
|---|---|---|---|
| b72816e985 | |||
| ac0b5caf83 | |||
| 3ddc3c72ed | |||
| f1af7ccbca | |||
| 51ca969ff4 | |||
| 1221249546 | |||
| 87fd69b825 | |||
| 3deb3ea751 | |||
| cc30637f09 | |||
| 23721aac96 | |||
| 5a9b346d72 | |||
| 75267e5140 | |||
| f0fb68992d |
15
roles/bootstrap/defaults/main.yml
Normal file
15
roles/bootstrap/defaults/main.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
# OS → task file mapping for bootstrap dispatch.
|
||||||
|
# Each key matches a supported `os` value; value is the task file to include.
|
||||||
|
bootstrap_os_task_map:
|
||||||
|
almalinux: _dnf_family.yml
|
||||||
|
alpine: alpine.yml
|
||||||
|
archlinux: archlinux.yml
|
||||||
|
debian: debian.yml
|
||||||
|
fedora: _dnf_family.yml
|
||||||
|
opensuse: opensuse.yml
|
||||||
|
rocky: _dnf_family.yml
|
||||||
|
rhel: rhel.yml
|
||||||
|
ubuntu: ubuntu.yml
|
||||||
|
ubuntu-lts: ubuntu.yml
|
||||||
|
void: void.yml
|
||||||
11
roles/bootstrap/tasks/_normalize.yml
Normal file
11
roles/bootstrap/tasks/_normalize.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
# Resolve the OS-specific variable namespace and task file for the bootstrap role.
|
||||||
|
- name: Validate OS is supported for bootstrap
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- os is defined
|
||||||
|
- os in bootstrap_os_task_map
|
||||||
|
fail_msg: >-
|
||||||
|
Unsupported OS '{{ os | default("undefined") }}' for bootstrap.
|
||||||
|
Supported: {{ bootstrap_os_task_map | dict2items | map(attribute='key') | join(', ') }}
|
||||||
|
quiet: true
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
---
|
---
|
||||||
|
- name: Normalize bootstrap
|
||||||
|
ansible.builtin.import_tasks: _normalize.yml
|
||||||
|
|
||||||
- name: Create API filesystem mountpoints in installroot
|
- name: Create API filesystem mountpoints in installroot
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/mnt/{{ item }}"
|
path: "/mnt/{{ item }}"
|
||||||
state: directory
|
state: directory
|
||||||
@@ -11,7 +14,7 @@
|
|||||||
- sys
|
- sys
|
||||||
|
|
||||||
- name: Mount API filesystems into installroot
|
- name: Mount API filesystems into installroot
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
src: "{{ item.src }}"
|
src: "{{ item.src }}"
|
||||||
path: "/mnt/{{ item.path }}"
|
path: "/mnt/{{ item.path }}"
|
||||||
@@ -28,18 +31,6 @@
|
|||||||
|
|
||||||
- name: Run OS-specific bootstrap process
|
- name: Run OS-specific bootstrap process
|
||||||
vars:
|
vars:
|
||||||
bootstrap_os_task_map:
|
|
||||||
almalinux: _dnf_family.yml
|
|
||||||
alpine: alpine.yml
|
|
||||||
archlinux: archlinux.yml
|
|
||||||
debian: debian.yml
|
|
||||||
fedora: _dnf_family.yml
|
|
||||||
opensuse: opensuse.yml
|
|
||||||
rocky: _dnf_family.yml
|
|
||||||
rhel: rhel.yml
|
|
||||||
ubuntu: ubuntu.yml
|
|
||||||
ubuntu-lts: ubuntu.yml
|
|
||||||
void: void.yml
|
|
||||||
bootstrap_var_key: "{{ 'bootstrap_' + (os | replace('-lts', '') | replace('-', '_')) }}"
|
bootstrap_var_key: "{{ 'bootstrap_' + (os | replace('-lts', '') | replace('-', '_')) }}"
|
||||||
ansible.builtin.include_tasks: "{{ bootstrap_os_task_map[os] }}"
|
ansible.builtin.include_tasks: "{{ bootstrap_os_task_map[os] }}"
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
block:
|
block:
|
||||||
- name: Install base packages in chroot environment
|
- name: Install base packages in chroot environment
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
dnf --releasever={{ os_version_major }} {{ _rhel_repos }}
|
dnf --releasever={{ os_version_major }} --best {{ _rhel_repos }}
|
||||||
--installroot=/mnt
|
--installroot=/mnt
|
||||||
--setopt=install_weak_deps=False --setopt=optional_metadata_types=filelists
|
--setopt=install_weak_deps=False --setopt=optional_metadata_types=filelists
|
||||||
groupinstall -y {{ _rhel_groups }}
|
groupinstall -y {{ _rhel_groups }}
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
- name: Install additional packages in chroot
|
- name: Install additional packages in chroot
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
{{ chroot_command }} dnf --releasever={{ os_version_major }}
|
{{ chroot_command }} dnf --releasever={{ os_version_major }} --best
|
||||||
--setopt=install_weak_deps=False install -y {{ _rhel_extra }}
|
--setopt=install_weak_deps=False install -y {{ _rhel_extra }}
|
||||||
register: bootstrap_result
|
register: bootstrap_result
|
||||||
changed_when: bootstrap_result.rc == 0
|
changed_when: bootstrap_result.rc == 0
|
||||||
|
|||||||
@@ -4,15 +4,8 @@
|
|||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.proxmox.proxmox_disk:
|
community.proxmox.proxmox_disk: "{{ _proxmox_auth }}"
|
||||||
api_host: "{{ hypervisor_cfg.url }}"
|
community.proxmox.proxmox_kvm: "{{ _proxmox_auth_node }}"
|
||||||
api_user: "{{ hypervisor_cfg.username }}"
|
|
||||||
api_password: "{{ hypervisor_cfg.password }}"
|
|
||||||
community.proxmox.proxmox_kvm:
|
|
||||||
api_host: "{{ hypervisor_cfg.url }}"
|
|
||||||
api_user: "{{ hypervisor_cfg.username }}"
|
|
||||||
api_password: "{{ hypervisor_cfg.password }}"
|
|
||||||
node: "{{ hypervisor_cfg.host }}"
|
|
||||||
block:
|
block:
|
||||||
- name: Cleanup Setup Disks
|
- name: Cleanup Setup Disks
|
||||||
community.proxmox.proxmox_disk:
|
community.proxmox.proxmox_disk:
|
||||||
|
|||||||
@@ -88,11 +88,7 @@
|
|||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.proxmox.proxmox_kvm:
|
community.proxmox.proxmox_kvm: "{{ _proxmox_auth_node }}"
|
||||||
api_host: "{{ hypervisor_cfg.url }}"
|
|
||||||
api_user: "{{ hypervisor_cfg.username }}"
|
|
||||||
api_password: "{{ hypervisor_cfg.password }}"
|
|
||||||
node: "{{ hypervisor_cfg.host }}"
|
|
||||||
no_log: true
|
no_log: true
|
||||||
block:
|
block:
|
||||||
- name: Stop Proxmox VM
|
- name: Stop Proxmox VM
|
||||||
@@ -113,11 +109,7 @@
|
|||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.vmware.vmware_guest:
|
community.vmware.vmware_guest: "{{ _vmware_auth }}"
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
no_log: true
|
no_log: true
|
||||||
block:
|
block:
|
||||||
- name: Power off VMware VM
|
- name: Power off VMware VM
|
||||||
|
|||||||
@@ -4,18 +4,8 @@
|
|||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.vmware.vmware_guest:
|
community.vmware.vmware_guest: "{{ _vmware_auth }}"
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
vmware.vmware.vm_powerstate: "{{ _vmware_auth }}"
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
|
||||||
vmware.vmware.vm_powerstate:
|
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
|
||||||
no_log: true
|
no_log: true
|
||||||
block:
|
block:
|
||||||
- name: Remove CD-ROM from VM in vCenter
|
- name: Remove CD-ROM from VM in vCenter
|
||||||
|
|||||||
7
roles/configuration/defaults/main.yml
Normal file
7
roles/configuration/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
# Network configuration dispatch — maps OS name to the task file
|
||||||
|
# that writes network config. Default (NetworkManager) applies to
|
||||||
|
# all OSes not explicitly listed.
|
||||||
|
configuration_network_task_map:
|
||||||
|
alpine: network_alpine.yml
|
||||||
|
void: network_void.yml
|
||||||
19
roles/configuration/tasks/_bls_update.yml
Normal file
19
roles/configuration/tasks/_bls_update.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
# Shared task: update BLS (Boot Loader Specification) entries with kernel cmdline.
|
||||||
|
# Expects variable: _bls_cmdline (the kernel command line string)
|
||||||
|
- name: Find BLS entries
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: /mnt/boot/loader/entries
|
||||||
|
patterns: "*.conf"
|
||||||
|
register: _bls_entries
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Update BLS options
|
||||||
|
when: _bls_entries.files | length > 0
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
regexp: "^options "
|
||||||
|
line: "options {{ _bls_cmdline }}"
|
||||||
|
loop: "{{ _bls_entries.files }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.path }}"
|
||||||
16
roles/configuration/tasks/_normalize.yml
Normal file
16
roles/configuration/tasks/_normalize.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# Resolve platform-specific configuration for the target OS family.
|
||||||
|
# Sets _configuration_platform from configuration_platform_config[os_family].
|
||||||
|
- name: Resolve platform-specific configuration
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- os_family is defined
|
||||||
|
- os_family in configuration_platform_config
|
||||||
|
fail_msg: >-
|
||||||
|
Unsupported os_family '{{ os_family | default("undefined") }}'.
|
||||||
|
Extend configuration_platform_config in vars/main.yml.
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: Set platform configuration
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_configuration_platform: "{{ configuration_platform_config[os_family] }}"
|
||||||
@@ -6,11 +6,10 @@
|
|||||||
"redhat" if os == "rhel"
|
"redhat" if os == "rhel"
|
||||||
else ("ubuntu" if os in ["ubuntu", "ubuntu-lts"] else os)
|
else ("ubuntu" if os in ["ubuntu", "ubuntu-lts"] else os)
|
||||||
}}
|
}}
|
||||||
_efi_loader: >-
|
_efi_loader: "{{ _configuration_platform.efi_loader }}"
|
||||||
{{ "shimx64.efi" if is_rhel | bool else "grubx64.efi" }}
|
|
||||||
block:
|
block:
|
||||||
- name: Install GRUB EFI binary
|
- name: Install GRUB EFI binary
|
||||||
when: not (is_rhel | bool)
|
when: _configuration_platform.grub_install
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
{{ chroot_command }} /usr/sbin/grub-install --target=x86_64-efi
|
{{ chroot_command }} /usr/sbin/grub-install --target=x86_64-efi
|
||||||
--efi-directory={{ partitioning_efi_mountpoint }}
|
--efi-directory={{ partitioning_efi_mountpoint }}
|
||||||
@@ -44,20 +43,8 @@
|
|||||||
backrefs: true
|
backrefs: true
|
||||||
|
|
||||||
- name: Regenerate initramfs
|
- name: Regenerate initramfs
|
||||||
when: os not in ["alpine", "void"]
|
when: _configuration_platform.initramfs_cmd | length > 0
|
||||||
vars:
|
ansible.builtin.command: "{{ chroot_command }} {{ _configuration_platform.initramfs_cmd }}"
|
||||||
configuration_initramfs_cmd: >-
|
|
||||||
{{
|
|
||||||
'/usr/sbin/mkinitcpio -P'
|
|
||||||
if os == "archlinux"
|
|
||||||
else (
|
|
||||||
'/usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin '
|
|
||||||
+ '/usr/sbin/update-initramfs -u -k all'
|
|
||||||
if is_debian | bool
|
|
||||||
else '/usr/bin/dracut --regenerate-all --force'
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
ansible.builtin.command: "{{ chroot_command }} {{ configuration_initramfs_cmd }}"
|
|
||||||
register: configuration_initramfs_result
|
register: configuration_initramfs_result
|
||||||
changed_when: configuration_initramfs_result.rc == 0
|
changed_when: configuration_initramfs_result.rc == 0
|
||||||
|
|
||||||
@@ -65,10 +52,10 @@
|
|||||||
vars:
|
vars:
|
||||||
configuration_grub_cfg_cmd: >-
|
configuration_grub_cfg_cmd: >-
|
||||||
{{
|
{{
|
||||||
'/usr/sbin/grub2-mkconfig -o '
|
'/usr/sbin/' + _configuration_platform.grub_mkconfig_prefix + ' -o '
|
||||||
+ partitioning_efi_mountpoint
|
+ partitioning_efi_mountpoint
|
||||||
+ '/EFI/' + _efi_vendor + '/grub.cfg'
|
+ '/EFI/' + _efi_vendor + '/grub.cfg'
|
||||||
if is_rhel | bool
|
if os_family == 'RedHat'
|
||||||
else '/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg'
|
else '/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg'
|
||||||
}}
|
}}
|
||||||
ansible.builtin.command: "{{ chroot_command }} {{ configuration_grub_cfg_cmd }}"
|
ansible.builtin.command: "{{ chroot_command }} {{ configuration_grub_cfg_cmd }}"
|
||||||
|
|||||||
@@ -134,7 +134,7 @@
|
|||||||
|
|
||||||
- name: Ensure keyfile pattern for initramfs-tools
|
- name: Ensure keyfile pattern for initramfs-tools
|
||||||
when:
|
when:
|
||||||
- is_debian | bool
|
- os_family == 'Debian'
|
||||||
- configuration_luks_keyfile_in_use
|
- configuration_luks_keyfile_in_use
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /mnt/etc/cryptsetup-initramfs/conf-hook
|
path: /mnt/etc/cryptsetup-initramfs/conf-hook
|
||||||
@@ -198,14 +198,14 @@
|
|||||||
}})
|
}})
|
||||||
|
|
||||||
- name: Ensure dracut config directory exists
|
- name: Ensure dracut config directory exists
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: /mnt/etc/dracut.conf.d
|
path: /mnt/etc/dracut.conf.d
|
||||||
state: directory
|
state: directory
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
|
||||||
- name: Configure dracut for LUKS
|
- name: Configure dracut for LUKS
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/dracut.conf.d/crypt.conf
|
dest: /mnt/etc/dracut.conf.d/crypt.conf
|
||||||
content: |
|
content: |
|
||||||
@@ -216,13 +216,13 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
- name: Read kernel cmdline defaults
|
- name: Read kernel cmdline defaults
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.slurp:
|
ansible.builtin.slurp:
|
||||||
src: /mnt/etc/kernel/cmdline
|
src: /mnt/etc/kernel/cmdline
|
||||||
register: configuration_kernel_cmdline_slurp
|
register: configuration_kernel_cmdline_slurp
|
||||||
|
|
||||||
- name: Build kernel cmdline with LUKS args
|
- name: Build kernel cmdline with LUKS args
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
vars:
|
vars:
|
||||||
kernel_cmdline_current: >-
|
kernel_cmdline_current: >-
|
||||||
{{ configuration_kernel_cmdline_slurp.content | b64decode | trim }}
|
{{ configuration_kernel_cmdline_slurp.content | b64decode | trim }}
|
||||||
@@ -247,40 +247,26 @@
|
|||||||
configuration_kernel_cmdline_new: "{{ kernel_cmdline_new }}"
|
configuration_kernel_cmdline_new: "{{ kernel_cmdline_new }}"
|
||||||
|
|
||||||
- name: Write kernel cmdline with LUKS args
|
- name: Write kernel cmdline with LUKS args
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/kernel/cmdline
|
dest: /mnt/etc/kernel/cmdline
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
content: "{{ configuration_kernel_cmdline_new }}\n"
|
content: "{{ configuration_kernel_cmdline_new }}\n"
|
||||||
|
|
||||||
- name: Find BLS entries for encryption kernel cmdline
|
- name: Update BLS entries with LUKS kernel cmdline
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
ansible.builtin.find:
|
vars:
|
||||||
paths: /mnt/boot/loader/entries
|
_bls_cmdline: "{{ configuration_kernel_cmdline_new }}"
|
||||||
patterns: "*.conf"
|
ansible.builtin.include_tasks: _bls_update.yml
|
||||||
register: configuration_kernel_bls_entries
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Update BLS options with LUKS args
|
|
||||||
when:
|
|
||||||
- is_rhel | bool
|
|
||||||
- configuration_kernel_bls_entries.files | length > 0
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
regexp: "^options "
|
|
||||||
line: "options {{ configuration_kernel_cmdline_new }}"
|
|
||||||
loop: "{{ configuration_kernel_bls_entries.files }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.path }}"
|
|
||||||
|
|
||||||
- name: Read grub defaults
|
- name: Read grub defaults
|
||||||
when: not is_rhel | bool
|
when: not os_family == 'RedHat'
|
||||||
ansible.builtin.slurp:
|
ansible.builtin.slurp:
|
||||||
src: /mnt/etc/default/grub
|
src: /mnt/etc/default/grub
|
||||||
register: configuration_grub_slurp
|
register: configuration_grub_slurp
|
||||||
|
|
||||||
- name: Build grub command lines with LUKS args
|
- name: Build grub command lines with LUKS args
|
||||||
when: not is_rhel | bool
|
when: not os_family == 'RedHat'
|
||||||
vars:
|
vars:
|
||||||
grub_content: "{{ configuration_grub_slurp.content | b64decode }}"
|
grub_content: "{{ configuration_grub_slurp.content | b64decode }}"
|
||||||
grub_cmdline_linux: >-
|
grub_cmdline_linux: >-
|
||||||
@@ -344,7 +330,7 @@
|
|||||||
configuration_grub_cmdline_default_new: "{{ grub_cmdline_default_new }}"
|
configuration_grub_cmdline_default_new: "{{ grub_cmdline_default_new }}"
|
||||||
|
|
||||||
- name: Update GRUB_CMDLINE_LINUX_DEFAULT for LUKS
|
- name: Update GRUB_CMDLINE_LINUX_DEFAULT for LUKS
|
||||||
when: not is_rhel | bool
|
when: not os_family == 'RedHat'
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /mnt/etc/default/grub
|
path: /mnt/etc/default/grub
|
||||||
regexp: "^GRUB_CMDLINE_LINUX_DEFAULT="
|
regexp: "^GRUB_CMDLINE_LINUX_DEFAULT="
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
- name: Append vim configurations to vimrc
|
- name: Append vim configurations to vimrc
|
||||||
ansible.builtin.blockinfile:
|
ansible.builtin.blockinfile:
|
||||||
path: "{{ '/mnt/etc/vim/vimrc' if is_debian | bool else '/mnt/etc/vimrc' }}"
|
path: "{{ '/mnt/etc/vim/vimrc' if os_family == 'Debian' else '/mnt/etc/vimrc' }}"
|
||||||
block: |
|
block: |
|
||||||
set encoding=utf-8
|
set encoding=utf-8
|
||||||
set number
|
set number
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
- name: Configure grub defaults
|
- name: Configure grub defaults
|
||||||
when: not is_rhel | bool
|
when: os_family != 'RedHat'
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /mnt/etc/default/grub
|
dest: /mnt/etc/default/grub
|
||||||
regexp: "{{ item.regexp }}"
|
regexp: "{{ item.regexp }}"
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
label: "{{ item.line }}"
|
label: "{{ item.line }}"
|
||||||
|
|
||||||
- name: Ensure grub defaults file exists for RHEL-based systems
|
- name: Ensure grub defaults file exists for RHEL-based systems
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
block:
|
block:
|
||||||
- name: Build RHEL kernel command line defaults
|
- name: Build RHEL kernel command line defaults
|
||||||
vars:
|
vars:
|
||||||
@@ -96,22 +96,10 @@
|
|||||||
mode: "0644"
|
mode: "0644"
|
||||||
content: "{{ configuration_kernel_cmdline_base }}\n"
|
content: "{{ configuration_kernel_cmdline_base }}\n"
|
||||||
|
|
||||||
- name: Find BLS entries for GRUB configuration
|
- name: Update BLS entries with kernel cmdline defaults
|
||||||
ansible.builtin.find:
|
vars:
|
||||||
paths: /mnt/boot/loader/entries
|
_bls_cmdline: "{{ configuration_kernel_cmdline_base }}"
|
||||||
patterns: "*.conf"
|
ansible.builtin.include_tasks: _bls_update.yml
|
||||||
register: configuration_grub_bls_entries
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Update BLS options with kernel cmdline defaults
|
|
||||||
when: configuration_grub_bls_entries.files | length > 0
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
regexp: "^options "
|
|
||||||
line: "options {{ configuration_kernel_cmdline_base }}"
|
|
||||||
loop: "{{ configuration_grub_bls_entries.files }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.path }}"
|
|
||||||
|
|
||||||
- name: Enable GRUB cryptodisk for encrypted /boot
|
- name: Enable GRUB cryptodisk for encrypted /boot
|
||||||
when: partitioning_grub_enable_cryptodisk | bool
|
when: partitioning_grub_enable_cryptodisk | bool
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
- name: Setup locales
|
- name: Setup locales
|
||||||
block:
|
block:
|
||||||
- name: Configure locale.gen
|
- name: Configure locale.gen
|
||||||
when: not is_rhel | bool
|
when: _configuration_platform.locale_gen
|
||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
dest: /mnt/etc/locale.gen
|
dest: /mnt/etc/locale.gen
|
||||||
regexp: "{{ item.regex }}"
|
regexp: "{{ item.regex }}"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
label: "{{ item.line }}"
|
label: "{{ item.line }}"
|
||||||
|
|
||||||
- name: Generate locales
|
- name: Generate locales
|
||||||
when: not is_rhel | bool
|
when: _configuration_platform.locale_gen
|
||||||
ansible.builtin.command: "{{ chroot_command }} /usr/sbin/locale-gen"
|
ansible.builtin.command: "{{ chroot_command }} /usr/sbin/locale-gen"
|
||||||
register: configuration_locale_result
|
register: configuration_locale_result
|
||||||
changed_when: configuration_locale_result.rc == 0
|
changed_when: configuration_locale_result.rc == 0
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
- name: Normalize configuration
|
||||||
|
ansible.builtin.import_tasks: _normalize.yml
|
||||||
|
|
||||||
- name: Include configuration tasks
|
- name: Include configuration tasks
|
||||||
when: configuration_task.when | default(true)
|
when: configuration_task.when | default(true)
|
||||||
ansible.builtin.include_tasks: "{{ configuration_task.file }}"
|
ansible.builtin.include_tasks: "{{ configuration_task.file }}"
|
||||||
@@ -17,7 +20,7 @@
|
|||||||
- file: users.yml
|
- file: users.yml
|
||||||
- file: sudo.yml
|
- file: sudo.yml
|
||||||
- file: selinux.yml
|
- file: selinux.yml
|
||||||
when: "{{ is_rhel | bool }}"
|
when: "{{ os_family == 'RedHat' }}"
|
||||||
loop_control:
|
loop_control:
|
||||||
loop_var: configuration_task
|
loop_var: configuration_task
|
||||||
label: "{{ configuration_task.file }}"
|
label: "{{ configuration_task.file }}"
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
- configuration_detected_interfaces | length > 0
|
- configuration_detected_interfaces | length > 0
|
||||||
fail_msg: Failed to detect any network interfaces.
|
fail_msg: Failed to detect any network interfaces.
|
||||||
|
|
||||||
|
- name: Set DNS configuration facts
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
configuration_dns_list: "{{ system_cfg.network.dns.servers }}"
|
||||||
|
configuration_dns_search: "{{ system_cfg.network.dns.search }}"
|
||||||
|
|
||||||
- name: Configure networking
|
- name: Configure networking
|
||||||
vars:
|
|
||||||
configuration_network_task_map:
|
|
||||||
alpine: network_alpine.yml
|
|
||||||
void: network_void.yml
|
|
||||||
ansible.builtin.include_tasks: "{{ configuration_network_task_map[os] | default('network_nm.yml') }}"
|
ansible.builtin.include_tasks: "{{ configuration_network_task_map[os] | default('network_nm.yml') }}"
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
---
|
---
|
||||||
- name: Write Alpine network interfaces
|
- name: Write Alpine network interfaces
|
||||||
vars:
|
|
||||||
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /mnt/etc/network/interfaces
|
dest: /mnt/etc/network/interfaces
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
@@ -25,9 +23,6 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
- name: Set Alpine DNS resolvers
|
- name: Set Alpine DNS resolvers
|
||||||
vars:
|
|
||||||
configuration_dns_list: "{{ system_cfg.network.dns.servers | default([]) }}"
|
|
||||||
configuration_dns_search: "{{ system_cfg.network.dns.search | default([]) }}"
|
|
||||||
when: configuration_dns_list | length > 0 or configuration_dns_search | length > 0
|
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
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
---
|
---
|
||||||
- name: Write dhcpcd configuration
|
- name: Write dhcpcd configuration
|
||||||
vars:
|
|
||||||
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"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
- name: Fix SELinux
|
- name: Fix SELinux
|
||||||
when: is_rhel | bool
|
when: os_family == 'RedHat'
|
||||||
block:
|
block:
|
||||||
- name: Fix SELinux by pre-labeling the filesystem before first boot
|
- name: Fix SELinux by pre-labeling the filesystem before first boot
|
||||||
when: os in ['almalinux', 'rocky', 'rhel'] and system_cfg.features.selinux.enabled | bool
|
when: os in ['almalinux', 'rocky', 'rhel'] and system_cfg.features.selinux.enabled | bool
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
- name: Enable systemd services
|
- name: Enable systemd services
|
||||||
when: os not in ['alpine', 'void']
|
when: _configuration_platform.init_system == 'systemd'
|
||||||
vars:
|
vars:
|
||||||
configuration_systemd_services: >-
|
configuration_systemd_services: >-
|
||||||
{{
|
{{
|
||||||
['NetworkManager']
|
['NetworkManager']
|
||||||
+ (['firewalld'] if system_cfg.features.firewall.backend == 'firewalld' and system_cfg.features.firewall.enabled | bool else [])
|
+ (['firewalld'] if system_cfg.features.firewall.backend == 'firewalld' and system_cfg.features.firewall.enabled | bool else [])
|
||||||
+ (['ufw'] if system_cfg.features.firewall.backend == 'ufw' and system_cfg.features.firewall.enabled | bool else [])
|
+ (['ufw'] if system_cfg.features.firewall.backend == 'ufw' and system_cfg.features.firewall.enabled | bool else [])
|
||||||
+ ([('ssh' if is_debian | bool else 'sshd')] if system_cfg.features.ssh.enabled | bool else [])
|
+ ([_configuration_platform.ssh_service] if system_cfg.features.ssh.enabled | bool else [])
|
||||||
+ (['logrotate', 'systemd-timesyncd'] if os == 'archlinux' else [])
|
+ (['logrotate', 'systemd-timesyncd'] if os == 'archlinux' else [])
|
||||||
}}
|
}}
|
||||||
ansible.builtin.command: "{{ chroot_command }} systemctl enable {{ item }}"
|
ansible.builtin.command: "{{ chroot_command }} systemctl enable {{ item }}"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
changed_when: configuration_enable_service_result.rc == 0
|
changed_when: configuration_enable_service_result.rc == 0
|
||||||
|
|
||||||
- name: Enable OpenRC services
|
- name: Enable OpenRC services
|
||||||
when: os == 'alpine'
|
when: _configuration_platform.init_system == 'openrc'
|
||||||
vars:
|
vars:
|
||||||
configuration_openrc_services: >-
|
configuration_openrc_services: >-
|
||||||
{{
|
{{
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
when: item.stat.exists
|
when: item.stat.exists
|
||||||
|
|
||||||
- name: Enable runit services
|
- name: Enable runit services
|
||||||
when: os == 'void'
|
when: _configuration_platform.init_system == 'runit'
|
||||||
vars:
|
vars:
|
||||||
configuration_runit_services: >-
|
configuration_runit_services: >-
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
- name: Give sudo access to wheel group
|
- name: Give sudo access to wheel group
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
content: "{{ '%sudo ALL=(ALL) ALL\n' if is_debian | bool else '%wheel ALL=(ALL) ALL\n' }}"
|
content: "{{ _configuration_platform.sudo_group }} ALL=(ALL) ALL\n"
|
||||||
dest: /mnt/etc/sudoers.d/01-wheel
|
dest: /mnt/etc/sudoers.d/01-wheel
|
||||||
mode: "0440"
|
mode: "0440"
|
||||||
validate: /usr/sbin/visudo --check --file=%s
|
validate: /usr/sbin/visudo --check --file=%s
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
|
|
||||||
- name: Create user accounts
|
- name: Create user accounts
|
||||||
vars:
|
vars:
|
||||||
configuration_user_group: >-
|
configuration_user_group: "{{ _configuration_platform.user_group }}"
|
||||||
{{ "sudo" if is_debian | bool else "wheel" }}
|
|
||||||
# UID starts at 1000; safe for fresh installs only
|
# UID starts at 1000; safe for fresh installs only
|
||||||
configuration_useradd_cmd: >-
|
configuration_useradd_cmd: >-
|
||||||
{{ chroot_command }} /usr/sbin/useradd --create-home --user-group
|
{{ chroot_command }} /usr/sbin/useradd --create-home --user-group
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ interface-name={{ configuration_iface_name }}
|
|||||||
|
|
||||||
[ipv4]
|
[ipv4]
|
||||||
{% set iface = configuration_iface %}
|
{% set iface = configuration_iface %}
|
||||||
{% set dns_list = system_cfg.network.dns.servers | default([]) %}
|
{% set dns_list = configuration_dns_list %}
|
||||||
{% set search_list = system_cfg.network.dns.search | default([]) %}
|
{% set search_list = configuration_dns_search %}
|
||||||
{% if iface.ip | default('') | string | length %}
|
{% if iface.ip | default('') | string | length %}
|
||||||
address1={{ iface.ip }}/{{ iface.prefix }}{{ (',' ~ iface.gateway) if (iface.gateway | default('') | string | length) else '' }}
|
address1={{ iface.ip }}/{{ iface.prefix }}{{ (',' ~ iface.gateway) if (iface.gateway | default('') | string | length) else '' }}
|
||||||
method=manual
|
method=manual
|
||||||
|
|||||||
67
roles/configuration/vars/main.yml
Normal file
67
roles/configuration/vars/main.yml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
# Platform-specific configuration values keyed by os_family.
|
||||||
|
# Consumed as _configuration_platform in tasks via:
|
||||||
|
# configuration_platform_config[os_family]
|
||||||
|
configuration_platform_config:
|
||||||
|
RedHat:
|
||||||
|
user_group: wheel
|
||||||
|
sudo_group: "%wheel"
|
||||||
|
ssh_service: sshd
|
||||||
|
efi_loader: shimx64.efi
|
||||||
|
grub_install: false
|
||||||
|
initramfs_cmd: "/usr/bin/dracut --regenerate-all --force"
|
||||||
|
grub_mkconfig_prefix: grub2-mkconfig
|
||||||
|
locale_gen: false
|
||||||
|
init_system: systemd
|
||||||
|
Debian:
|
||||||
|
user_group: sudo
|
||||||
|
sudo_group: "%sudo"
|
||||||
|
ssh_service: ssh
|
||||||
|
efi_loader: grubx64.efi
|
||||||
|
grub_install: true
|
||||||
|
initramfs_cmd: >-
|
||||||
|
/usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
/usr/sbin/update-initramfs -u -k all
|
||||||
|
grub_mkconfig_prefix: grub-mkconfig
|
||||||
|
locale_gen: true
|
||||||
|
init_system: systemd
|
||||||
|
Archlinux:
|
||||||
|
user_group: wheel
|
||||||
|
sudo_group: "%wheel"
|
||||||
|
ssh_service: sshd
|
||||||
|
efi_loader: grubx64.efi
|
||||||
|
grub_install: true
|
||||||
|
initramfs_cmd: "/usr/sbin/mkinitcpio -P"
|
||||||
|
grub_mkconfig_prefix: grub-mkconfig
|
||||||
|
locale_gen: true
|
||||||
|
init_system: systemd
|
||||||
|
Suse:
|
||||||
|
user_group: wheel
|
||||||
|
sudo_group: "%wheel"
|
||||||
|
ssh_service: sshd
|
||||||
|
efi_loader: grubx64.efi
|
||||||
|
grub_install: true
|
||||||
|
initramfs_cmd: "/usr/bin/dracut --regenerate-all --force"
|
||||||
|
grub_mkconfig_prefix: grub-mkconfig
|
||||||
|
locale_gen: true
|
||||||
|
init_system: systemd
|
||||||
|
Alpine:
|
||||||
|
user_group: wheel
|
||||||
|
sudo_group: "%wheel"
|
||||||
|
ssh_service: sshd
|
||||||
|
efi_loader: grubx64.efi
|
||||||
|
grub_install: true
|
||||||
|
initramfs_cmd: ""
|
||||||
|
grub_mkconfig_prefix: grub-mkconfig
|
||||||
|
locale_gen: false
|
||||||
|
init_system: openrc
|
||||||
|
Void:
|
||||||
|
user_group: wheel
|
||||||
|
sudo_group: "%wheel"
|
||||||
|
ssh_service: sshd
|
||||||
|
efi_loader: grubx64.efi
|
||||||
|
grub_install: true
|
||||||
|
initramfs_cmd: ""
|
||||||
|
grub_mkconfig_prefix: grub-mkconfig
|
||||||
|
locale_gen: false
|
||||||
|
init_system: runit
|
||||||
10
roles/environment/defaults/main.yml
Normal file
10
roles/environment/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
# Connection and timing
|
||||||
|
environment_wait_timeout: 180
|
||||||
|
environment_wait_delay: 5
|
||||||
|
|
||||||
|
# Pacman installer settings
|
||||||
|
environment_parallel_downloads: 20
|
||||||
|
environment_pacman_lock_timeout: 120
|
||||||
|
environment_pacman_retries: 4
|
||||||
|
environment_pacman_retry_delay: 15
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
- name: Wait for connection
|
- name: Wait for connection
|
||||||
ansible.builtin.wait_for_connection:
|
ansible.builtin.wait_for_connection:
|
||||||
timeout: 180
|
timeout: "{{ environment_wait_timeout }}"
|
||||||
delay: 5
|
delay: "{{ environment_wait_delay }}"
|
||||||
|
|
||||||
- name: Gather facts
|
- name: Gather facts
|
||||||
ansible.builtin.setup:
|
ansible.builtin.setup:
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
ansible.builtin.lineinfile:
|
ansible.builtin.lineinfile:
|
||||||
path: /etc/pacman.conf
|
path: /etc/pacman.conf
|
||||||
regexp: ^#ParallelDownloads =
|
regexp: ^#ParallelDownloads =
|
||||||
line: ParallelDownloads = 20
|
line: "ParallelDownloads = {{ environment_parallel_downloads }}"
|
||||||
|
|
||||||
- name: Wait for pacman lock to be released
|
- name: Wait for pacman lock to be released
|
||||||
when: not (custom_iso | bool)
|
when: not (custom_iso | bool)
|
||||||
ansible.builtin.wait_for:
|
ansible.builtin.wait_for:
|
||||||
path: /var/lib/pacman/db.lck
|
path: /var/lib/pacman/db.lck
|
||||||
state: absent
|
state: absent
|
||||||
timeout: 120
|
timeout: "{{ environment_pacman_lock_timeout }}"
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Setup Pacman
|
- name: Setup Pacman
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
- { name: ubuntu-keyring, os: [ubuntu, ubuntu-lts] }
|
- { name: ubuntu-keyring, os: [ubuntu, ubuntu-lts] }
|
||||||
loop_control:
|
loop_control:
|
||||||
label: "{{ item.name }}"
|
label: "{{ item.name }}"
|
||||||
retries: 4
|
retries: "{{ environment_pacman_retries }}"
|
||||||
delay: 15
|
delay: "{{ environment_pacman_retry_delay }}"
|
||||||
|
|
||||||
- name: Prepare /iso mount and repository for RHEL-based systems
|
- name: Prepare /iso mount and repository for RHEL-based systems
|
||||||
when: os == "rhel"
|
when: os == "rhel"
|
||||||
|
|||||||
@@ -9,6 +9,22 @@ os_family_debian:
|
|||||||
- debian
|
- debian
|
||||||
- ubuntu
|
- ubuntu
|
||||||
- ubuntu-lts
|
- ubuntu-lts
|
||||||
|
|
||||||
|
# OS → family mapping — aligns with the main project's ansible_os_family pattern.
|
||||||
|
# Enables platform_config dict lookups per role instead of inline when: is_rhel chains.
|
||||||
|
os_family_map:
|
||||||
|
almalinux: RedHat
|
||||||
|
alpine: Alpine
|
||||||
|
archlinux: Archlinux
|
||||||
|
debian: Debian
|
||||||
|
fedora: RedHat
|
||||||
|
opensuse: Suse
|
||||||
|
rhel: RedHat
|
||||||
|
rocky: RedHat
|
||||||
|
ubuntu: Debian
|
||||||
|
ubuntu-lts: Debian
|
||||||
|
void: Void
|
||||||
|
|
||||||
os_supported:
|
os_supported:
|
||||||
- almalinux
|
- almalinux
|
||||||
- alpine
|
- alpine
|
||||||
@@ -34,9 +50,11 @@ hypervisor_defaults:
|
|||||||
storage: ""
|
storage: ""
|
||||||
datacenter: ""
|
datacenter: ""
|
||||||
cluster: ""
|
cluster: ""
|
||||||
|
folder: ""
|
||||||
certs: false
|
certs: false
|
||||||
ssh: false
|
ssh: false
|
||||||
|
|
||||||
|
physical_default_os: "archlinux"
|
||||||
custom_iso: false
|
custom_iso: false
|
||||||
thirdparty_tasks: "dropins/preparation.yml"
|
thirdparty_tasks: "dropins/preparation.yml"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
- name: Build normalized system configuration
|
- name: Build normalized system configuration
|
||||||
vars:
|
vars:
|
||||||
system_raw: "{{ system_defaults | combine(system, recursive=True) }}"
|
system_raw: "{{ system_defaults | combine(system, recursive=True) }}"
|
||||||
system_type: "{{ system_raw.type | string | lower }}"
|
system_type: "{{ 'virtual' if (system_raw.type | string | lower) in ['vm', 'virtual'] else (system_raw.type | string | lower) }}"
|
||||||
system_os_input: "{{ system_raw.os | default('') | string | lower }}"
|
system_os_input: "{{ system_raw.os | default('') | string | lower }}"
|
||||||
system_name: >-
|
system_name: >-
|
||||||
{{
|
{{
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
system_cfg:
|
system_cfg:
|
||||||
# --- Identity & platform ---
|
# --- 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 (physical_default_os 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 }}"
|
||||||
@@ -64,9 +64,9 @@
|
|||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
# --- Locale & environment ---
|
# --- Locale & environment ---
|
||||||
timezone: "{{ system_raw.timezone | default('Europe/Vienna') | string }}"
|
timezone: "{{ system_raw.timezone | string }}"
|
||||||
locale: "{{ system_raw.locale | default('en_US.UTF-8') | string }}"
|
locale: "{{ system_raw.locale | string }}"
|
||||||
keymap: "{{ system_raw.keymap | default('us') | string }}"
|
keymap: "{{ system_raw.keymap | string }}"
|
||||||
path: "{{ system_raw.path | default('') | string }}"
|
path: "{{ system_raw.path | default('') | string }}"
|
||||||
packages: >-
|
packages: >-
|
||||||
{{
|
{{
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
chroot:
|
chroot:
|
||||||
tool: "{{ system_raw.features.chroot.tool | string }}"
|
tool: "{{ system_raw.features.chroot.tool | string }}"
|
||||||
hostname: "{{ system_name }}"
|
hostname: "{{ system_name }}"
|
||||||
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 (physical_default_os if system_type == 'physical' else '') }}"
|
||||||
os_version: "{{ system_raw.version | default('') | string }}"
|
os_version: "{{ system_raw.version | default('') | string }}"
|
||||||
no_log: true
|
no_log: true
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,31 @@
|
|||||||
- name: Normalize hypervisor inputs
|
- name: Normalize hypervisor inputs
|
||||||
ansible.builtin.include_tasks: hypervisor.yml
|
ansible.builtin.include_tasks: hypervisor.yml
|
||||||
|
|
||||||
|
- name: Set VMware module auth defaults
|
||||||
|
when: hypervisor_type == 'vmware'
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_vmware_auth:
|
||||||
|
hostname: "{{ hypervisor_cfg.url }}"
|
||||||
|
username: "{{ hypervisor_cfg.username }}"
|
||||||
|
password: "{{ hypervisor_cfg.password }}"
|
||||||
|
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
||||||
|
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Set Proxmox module auth defaults
|
||||||
|
when: hypervisor_type == 'proxmox'
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_proxmox_auth:
|
||||||
|
api_host: "{{ hypervisor_cfg.url }}"
|
||||||
|
api_user: "{{ hypervisor_cfg.username }}"
|
||||||
|
api_password: "{{ hypervisor_cfg.password }}"
|
||||||
|
_proxmox_auth_node:
|
||||||
|
api_host: "{{ hypervisor_cfg.url }}"
|
||||||
|
api_user: "{{ hypervisor_cfg.username }}"
|
||||||
|
api_password: "{{ hypervisor_cfg.password }}"
|
||||||
|
node: "{{ hypervisor_cfg.host }}"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
- name: Normalize system inputs
|
- name: Normalize system inputs
|
||||||
ansible.builtin.include_tasks: system.yml
|
ansible.builtin.include_tasks: system.yml
|
||||||
|
|
||||||
@@ -20,6 +45,7 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
is_rhel: "{{ os in os_family_rhel }}"
|
is_rhel: "{{ os in os_family_rhel }}"
|
||||||
is_debian: "{{ os in os_family_debian }}"
|
is_debian: "{{ os in os_family_debian }}"
|
||||||
|
os_family: "{{ os_family_map[os] | default('Unknown') }}"
|
||||||
|
|
||||||
- name: Normalize OS version for keying
|
- name: Normalize OS version for keying
|
||||||
when:
|
when:
|
||||||
|
|||||||
@@ -347,8 +347,48 @@
|
|||||||
that:
|
that:
|
||||||
- item is mapping
|
- item is mapping
|
||||||
- item.bridge is defined and (item.bridge | string | length) > 0
|
- item.bridge is defined and (item.bridge | string | length) > 0
|
||||||
fail_msg: "Each system.network.interfaces[] entry must be a dict with at least a 'bridge' key."
|
- >-
|
||||||
|
(item.ip | default('') | string | length) == 0
|
||||||
|
or (item.prefix | default('') | string | length) > 0
|
||||||
|
fail_msg: "Each system.network.interfaces[] entry must have a 'bridge' key and 'prefix' when 'ip' is set."
|
||||||
quiet: true
|
quiet: true
|
||||||
loop: "{{ system_cfg.network.interfaces }}"
|
loop: "{{ system_cfg.network.interfaces }}"
|
||||||
loop_control:
|
loop_control:
|
||||||
label: "{{ item | to_json }}"
|
label: "{{ item | to_json }}"
|
||||||
|
|
||||||
|
- name: Validate hostname format
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- hostname is regex("^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?$")
|
||||||
|
fail_msg: "hostname '{{ hostname }}' contains invalid characters. Use only alphanumeric, hyphens, dots, and underscores."
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: Validate IP address format
|
||||||
|
when: system_cfg.network.ip is defined and (system_cfg.network.ip | string | length) > 0
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- system_cfg.network.ip is regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}$")
|
||||||
|
fail_msg: "system.network.ip '{{ system_cfg.network.ip }}' is not a valid IPv4 address."
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
- name: Validate DNS server format
|
||||||
|
when:
|
||||||
|
- system_cfg.network.dns.servers is defined
|
||||||
|
- system_cfg.network.dns.servers | length > 0
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- item is regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}$")
|
||||||
|
fail_msg: "DNS server '{{ item }}' is not a valid IPv4 address."
|
||||||
|
quiet: true
|
||||||
|
loop: "{{ system_cfg.network.dns.servers }}"
|
||||||
|
|
||||||
|
- name: Validate LUKS method
|
||||||
|
when: system_cfg.luks.enabled | bool
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- system_cfg.luks.method in ["tpm2", "keyfile"]
|
||||||
|
- >-
|
||||||
|
(system_cfg.luks.passphrase | string | length) > 0
|
||||||
|
fail_msg: "system.luks.method must be 'tpm2' or 'keyfile', and luks.passphrase must be set when LUKS is enabled."
|
||||||
|
quiet: true
|
||||||
|
no_log: true
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
---
|
---
|
||||||
partitioning_btrfs_compress_opt: "{{ 'compress=zstd:15' if system_cfg.features.zstd.enabled | bool else '' }}"
|
partitioning_btrfs_compress_opt: "{{ 'compress=zstd:15' if system_cfg.features.zstd.enabled | bool else '' }}"
|
||||||
|
# Partition separator: 'p' for NVMe/mmcblk (device path ends in digit), empty for SCSI/virtio.
|
||||||
|
# Examples: /dev/sda → /dev/sda1, /dev/nvme0n1 → /dev/nvme0n1p1
|
||||||
|
partitioning_part_sep: "{{ 'p' if (install_drive | default('') | regex_search('\\d$')) else '' }}"
|
||||||
partitioning_boot_partition_suffix: 1
|
partitioning_boot_partition_suffix: 1
|
||||||
partitioning_main_partition_suffix: 2
|
partitioning_main_partition_suffix: 2
|
||||||
partitioning_efi_size_mib: 512
|
partitioning_efi_size_mib: 512
|
||||||
@@ -113,12 +116,12 @@ partitioning_grub_enable_cryptodisk: >-
|
|||||||
and not (partitioning_separate_boot | bool)
|
and not (partitioning_separate_boot | bool)
|
||||||
and (partitioning_efi_mountpoint == '/boot/efi')
|
and (partitioning_efi_mountpoint == '/boot/efi')
|
||||||
}}
|
}}
|
||||||
partitioning_luks_device: "{{ install_drive ~ (partitioning_root_partition_suffix | string) }}"
|
partitioning_luks_device: "{{ install_drive ~ partitioning_part_sep ~ (partitioning_root_partition_suffix | string) }}"
|
||||||
partitioning_root_device: >-
|
partitioning_root_device: >-
|
||||||
{{
|
{{
|
||||||
'/dev/mapper/' + system_cfg.luks.mapper
|
'/dev/mapper/' + system_cfg.luks.mapper
|
||||||
if (system_cfg.luks.enabled | bool)
|
if (system_cfg.luks.enabled | bool)
|
||||||
else install_drive ~ (partitioning_root_partition_suffix | string)
|
else install_drive ~ partitioning_part_sep ~ (partitioning_root_partition_suffix | string)
|
||||||
}}
|
}}
|
||||||
partitioning_disk_size_gb: >-
|
partitioning_disk_size_gb: >-
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
block:
|
block:
|
||||||
- name: Create FAT32 filesystem in boot partition
|
- name: Create FAT32 filesystem in boot partition
|
||||||
community.general.filesystem:
|
community.general.filesystem:
|
||||||
dev: "{{ install_drive }}{{ partitioning_boot_partition_suffix }}"
|
dev: "{{ install_drive }}{{ partitioning_part_sep }}{{ partitioning_boot_partition_suffix }}"
|
||||||
fstype: vfat
|
fstype: vfat
|
||||||
opts: -F32 -n BOOT
|
opts: -F32 -n BOOT
|
||||||
force: true
|
force: true
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
- name: Create filesystem for /boot partition
|
- name: Create filesystem for /boot partition
|
||||||
when: partitioning_separate_boot | bool
|
when: partitioning_separate_boot | bool
|
||||||
community.general.filesystem:
|
community.general.filesystem:
|
||||||
dev: "{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}"
|
dev: "{{ install_drive }}{{ partitioning_part_sep }}{{ partitioning_boot_fs_partition_suffix }}"
|
||||||
fstype: "{{ partitioning_boot_fs_fstype }}"
|
fstype: "{{ partitioning_boot_fs_fstype }}"
|
||||||
opts: "{{ '-m bigtime=0 -i nrext64=0,exchange=0 -n parent=0' if (is_rhel | bool and partitioning_boot_fs_fstype == 'xfs') else omit }}"
|
opts: "{{ '-m bigtime=0 -i nrext64=0,exchange=0 -n parent=0' if (is_rhel | bool and partitioning_boot_fs_fstype == 'xfs') else omit }}"
|
||||||
force: true
|
force: true
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
- os in ['almalinux', 'rocky', 'rhel'] or (os == 'debian' and (os_version | string) == '11')
|
- os in ['almalinux', 'rocky', 'rhel'] or (os == 'debian' and (os_version | string) == '11')
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
tune2fs -O "^orphan_file,^metadata_csum_seed"
|
tune2fs -O "^orphan_file,^metadata_csum_seed"
|
||||||
"{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}"
|
"{{ install_drive }}{{ partitioning_part_sep }}{{ partitioning_boot_fs_partition_suffix }}"
|
||||||
register: partitioning_boot_ext4_tune_result
|
register: partitioning_boot_ext4_tune_result
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
ansible.builtin.include_tasks: "{{ system_cfg.filesystem }}.yml"
|
ansible.builtin.include_tasks: "{{ system_cfg.filesystem }}.yml"
|
||||||
|
|
||||||
- name: Get UUID for boot filesystem
|
- name: Get UUID for boot filesystem
|
||||||
ansible.builtin.command: blkid -s UUID -o value '{{ install_drive }}{{ partitioning_boot_partition_suffix }}'
|
ansible.builtin.command: blkid -s UUID -o value '{{ install_drive }}{{ partitioning_part_sep }}{{ partitioning_boot_partition_suffix }}'
|
||||||
register: partitioning_boot_uuid
|
register: partitioning_boot_uuid
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: partitioning_boot_uuid.rc != 0 or (partitioning_boot_uuid.stdout | trim | length) == 0
|
failed_when: partitioning_boot_uuid.rc != 0 or (partitioning_boot_uuid.stdout | trim | length) == 0
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
- name: Get UUID for /boot filesystem
|
- name: Get UUID for /boot filesystem
|
||||||
when: partitioning_separate_boot | bool
|
when: partitioning_separate_boot | bool
|
||||||
ansible.builtin.command: >-
|
ansible.builtin.command: >-
|
||||||
blkid -s UUID -o value '{{ install_drive }}{{ partitioning_boot_fs_partition_suffix }}'
|
blkid -s UUID -o value '{{ install_drive }}{{ partitioning_part_sep }}{{ partitioning_boot_fs_partition_suffix }}'
|
||||||
register: partitioning_boot_fs_uuid
|
register: partitioning_boot_fs_uuid
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: partitioning_boot_fs_uuid.rc != 0 or (partitioning_boot_fs_uuid.stdout | trim | length) == 0
|
failed_when: partitioning_boot_fs_uuid.rc != 0 or (partitioning_boot_fs_uuid.stdout | trim | length) == 0
|
||||||
|
|||||||
@@ -2,11 +2,7 @@
|
|||||||
- name: Deploy VM on Proxmox
|
- name: Deploy VM on Proxmox
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.proxmox.proxmox_kvm:
|
community.proxmox.proxmox_kvm: "{{ _proxmox_auth_node }}"
|
||||||
api_host: "{{ hypervisor_cfg.url }}"
|
|
||||||
api_user: "{{ hypervisor_cfg.username }}"
|
|
||||||
api_password: "{{ hypervisor_cfg.password }}"
|
|
||||||
node: "{{ hypervisor_cfg.host }}"
|
|
||||||
block:
|
block:
|
||||||
- name: Create VM on Proxmox
|
- name: Create VM on Proxmox
|
||||||
vars:
|
vars:
|
||||||
|
|||||||
@@ -14,24 +14,9 @@
|
|||||||
- name: Deploy VM in vCenter
|
- name: Deploy VM in vCenter
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
module_defaults:
|
module_defaults:
|
||||||
community.vmware.vmware_guest:
|
community.vmware.vmware_guest: "{{ _vmware_auth }}"
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
community.vmware.vmware_guest_tpm: "{{ _vmware_auth }}"
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
vmware.vmware.vm_powerstate: "{{ _vmware_auth }}"
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
|
||||||
community.vmware.vmware_guest_tpm:
|
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
|
||||||
vmware.vmware.vm_powerstate:
|
|
||||||
hostname: "{{ hypervisor_cfg.url }}"
|
|
||||||
username: "{{ hypervisor_cfg.username }}"
|
|
||||||
password: "{{ hypervisor_cfg.password }}"
|
|
||||||
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
|
|
||||||
datacenter: "{{ hypervisor_cfg.datacenter }}"
|
|
||||||
block:
|
block:
|
||||||
# community.vmware: full-featured guest management
|
# community.vmware: full-featured guest management
|
||||||
- name: Create VM in vCenter
|
- name: Create VM in vCenter
|
||||||
@@ -100,6 +85,17 @@
|
|||||||
name: "{{ hostname }}"
|
name: "{{ hostname }}"
|
||||||
state: present
|
state: present
|
||||||
no_log: true
|
no_log: true
|
||||||
|
register: virtualization_vmware_tpm2_result
|
||||||
|
|
||||||
|
- name: Validate vTPM2 was added successfully
|
||||||
|
when:
|
||||||
|
- virtualization_tpm2_enabled | bool
|
||||||
|
- virtualization_vmware_tpm2_result is defined
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- virtualization_vmware_tpm2_result is not failed
|
||||||
|
fail_msg: "Failed to add vTPM2 to VM '{{ hostname }}'. LUKS with TPM2 requires a virtual TPM device."
|
||||||
|
quiet: true
|
||||||
|
|
||||||
# vmware.vmware: modern collection for power operations
|
# vmware.vmware: modern collection for power operations
|
||||||
- name: Start VM in vCenter
|
- name: Start VM in vCenter
|
||||||
|
|||||||
Reference in New Issue
Block a user