2026-01-02 11:26:21 +01:00

Ansible Bootstrap

Automated Linux system bootstrap using the Arch Linux ISO as a universal installer. Deploys any supported distribution on virtual or physical targets via Infrastructure-as-Code.

Non-Arch targets require the appropriate package manager available from the ISO environment (e.g. dnf for RHEL-family). Set system.features.chroot.tool if arch-chroot is unavailable.

Table of Contents

  1. Supported Platforms
  2. Compatibility Notes
  3. Configuration Model
  4. Variable Reference
  5. Execution Pipeline
  6. Usage
  7. Security
  8. Safety

1. Supported Platforms

Distributions

system.os Distribution system.version
almalinux AlmaLinux 8, 9, 10
alpine Alpine Linux latest (rolling)
archlinux Arch Linux latest (rolling)
debian Debian 10-13, unstable
fedora Fedora 38-45
opensuse openSUSE Tumbleweed latest (rolling)
rhel Red Hat Enterprise Linux 8, 9, 10
rocky Rocky Linux 8, 9, 10
ubuntu Ubuntu (latest non-LTS) optional (e.g. 24.04)
ubuntu-lts Ubuntu LTS optional (e.g. 24.04)
void Void Linux latest (rolling)

Hypervisors

Hypervisor hypervisor.type
libvirt libvirt
Proxmox VE proxmox
VMware vmware
Xen xen
Bare metal none

2. Compatibility Notes

  • rhel_iso is required for system.os: rhel.
  • RHEL installs should use ext4 or xfs (not btrfs).
  • custom_iso: true skips ArchISO validation; your installer must provide required tooling.
  • On non-Arch installers, set system.features.chroot.tool explicitly.

3. Configuration Model

Two dict-based variables drive the entire configuration:

  • system -- host, network, users, disk layout, encryption, and feature toggles
  • hypervisor -- virtualization backend credentials and targeting

An optional third dict cis overrides CIS hardening parameters when system.features.cis.enabled: true.

All three are standard Ansible variables. Place them in group_vars/, host_vars/, or inline inventory. With hash_behaviour = merge, dictionaries merge across scopes, so shared values go in group vars and host-specific overrides go per-host.

Variable Placement

Location Scope Typical use
group_vars/all.yml All hosts Shared hypervisor, system.filesystem, boot_iso
group_vars/<group>.yml Group Environment-specific defaults
host_vars/<host>.yml Single host Host-specific overrides (system.network.ip, system.id, etc.)

Example Inventory

all:
  vars:
    system:
      filesystem: btrfs
    boot_iso: "local:iso/archlinux-x86_64.iso"
    hypervisor:
      type: proxmox
      url: pve01.example.com
      username: root@pam
      password: !vault |
        $ANSIBLE_VAULT...
      host: pve01
      storage: local-lvm

  children:
    bootstrap:
      hosts:
        app01.example.com:
          ansible_host: 10.0.0.10
          system:
            type: virtual
            os: debian
            version: "12"
            name: app01.example.com
            id: 101
            cpus: 2
            memory: 4096
            network:
              bridge: vmbr0
              ip: 10.0.0.10
              prefix: 24
              gateway: 10.0.0.1
              dns:
                servers: [1.1.1.1, 1.0.0.1]
                search: [example.com]
            disks:
              - size: 40
              - size: 120
                mount:
                  path: /data
                  fstype: xfs
            users:
              - name: ops
                password: !vault |
                  $ANSIBLE_VAULT...
                keys:
                  - "ssh-ed25519 AAAA..."
                sudo: true
            root:
              password: !vault |
                $ANSIBLE_VAULT...
            luks:
              enabled: true
              passphrase: !vault |
                $ANSIBLE_VAULT...
              method: tpm2
              tpm2:
                pcrs: "7"
            features:
              cis:
                enabled: true
              firewall:
                enabled: true
                backend: firewalld
                toolkit: nftables

4. Variable Reference

4.1 Core Variables

Top-level variables outside system/hypervisor/cis.

Variable Type Default Description
boot_iso string -- Boot ISO path (required for virtual installs)
rhel_iso string -- RHEL ISO path (required when system.os: rhel)
custom_iso bool false Skip ArchISO validation and pacman setup
thirdparty_tasks string dropins/preparation.yml Drop-in task file included during environment setup

4.2 system Dictionary

Key Type Default Description
type string virtual virtual or physical
os string -- Target distribution (see table)
version string -- Version selector for versioned distros
filesystem string -- btrfs, ext4, or xfs
name string inventory hostname Final hostname
timezone string Europe/Vienna System timezone (tz database name)
locale string en_US.UTF-8 System locale
keymap string us Console keymap
id int/string -- VMID (required for Proxmox)
cpus int 0 vCPU count (required for virtual)
memory int 0 Memory in MiB (required for virtual)
balloon int 0 Balloon memory in MiB (Proxmox)
path string -- Hypervisor folder/path
packages list [] Additional packages installed post-reboot
network dict see below Network configuration
disks list [] Disk layout (see Multi-Disk Schema)
users list [] User accounts
root dict see below Root account settings
luks dict see below Encryption settings
features dict see below Feature toggles

system.network

Key Type Default Description
bridge string -- Hypervisor network/bridge name
vlan string/int -- VLAN tag
ip string -- Static IP (omit for DHCP)
prefix int -- CIDR prefix (1-32, required with ip)
gateway string -- Default gateway
dns.servers list [] DNS resolvers (must be a YAML list)
dns.search list [] Search domains (must be a YAML list)
interfaces list [] Multi-NIC config (overrides flat fields above)

When interfaces is empty, the flat fields (bridge, ip, prefix, gateway, vlan) are auto-wrapped into a single-entry list. When interfaces is set, it takes precedence. Each entry supports: name, bridge (required), vlan, ip, prefix, gateway.

system.users

Key Type Default Description
name string -- Username (required)
password string -- User password (required for first user)
keys list [] SSH public keys
sudo bool/string -- true for NOPASSWD ALL, or custom sudoers string

The first user's credentials are prompted interactively via vars_prompt unless supplied in inventory or -e.

system.root

Key Type Default Description
password string -- Root password

system.luks

Key Type Default Description
enabled bool false Enable encrypted root
passphrase string -- Passphrase for format/open/enroll
mapper string SYSTEM_DECRYPTED Mapper name under /dev/mapper
auto bool true Auto-unlock toggle
method string tpm2 Auto-unlock backend: tpm2 or keyfile
keysize int 64 Keyfile size in bytes
options string discard,tries=3 Additional crypttab options
type string luks2 LUKS format type
cipher string aes-xts-plain64 Cipher
hash string sha512 Hash algorithm
iter int 4000 PBKDF iteration time (ms)
bits int 512 Key size (bits)
pbkdf string argon2id PBKDF algorithm
urandom bool true Use urandom during key generation
verify bool true Verify passphrase during format

system.luks.tpm2

Key Type Default Description
device string auto TPM2 device selector
pcrs string/list -- PCR binding policy (e.g. "7" or "0+7")

system.features

Key Type Default Description
cis.enabled bool false Enable CIS hardening (see 4.4)
selinux.enabled bool true SELinux management
firewall.enabled bool true Firewall setup
firewall.backend string firewalld firewalld or ufw
firewall.toolkit string nftables nftables or iptables
ssh.enabled bool true SSH service/package management
zstd.enabled bool true zstd-related tuning
swap.enabled bool true Swap setup
banner.motd bool false MOTD banner
banner.sudo bool true Sudo banner
chroot.tool string arch-chroot arch-chroot, chroot, or systemd-nspawn

4.3 hypervisor Dictionary

Key Type Default Description
type string -- libvirt, proxmox, vmware, xen, or none
url string -- API host (Proxmox/VMware)
username string -- API username
password string -- API password
host string -- Proxmox node name
storage string -- Storage identifier (Proxmox/VMware)
datacenter string -- VMware datacenter
cluster string -- VMware cluster
certs bool true TLS certificate validation (VMware)
ssh bool false Enable SSH on guest and switch connection (VMware)

4.4 cis Dictionary

When system.features.cis.enabled: true, the CIS role applies hardening. All values have sensible defaults; override specific keys via the cis dict.

Key Type Default Description
modules_blacklist list see below Kernel modules to blacklist via modprobe
sysctl dict see below Sysctl key/value pairs written to 10-cis.conf
sshd_options list see below SSHD options applied via lineinfile
pwquality_minlen int 14 Minimum password length
tmout int 900 Shell timeout (seconds)
umask string 077 Default umask in bashrc
umask_profile string 027 Default umask in /etc/profile
faillock_deny int 5 Failed login attempts before lockout
faillock_unlock_time int 900 Lockout duration (seconds)
password_remember int 5 Password history depth

Default modules blacklist: freevxfs, jffs2, hfs, hfsplus, cramfs, udf, usb-storage, dccp, sctp, rds, tipc, firewire-core, firewire-sbp2, thunderbolt. squashfs is added automatically except on Ubuntu (snap dependency).

Default sysctl settings include: kernel.yama.ptrace_scope=2, kernel.kptr_restrict=2, kernel.perf_event_paranoid=3, kernel.unprivileged_bpf_disabled=1, IPv4/IPv6 hardening, ARP protection, and IPv6 disabled by default. Override individual keys:

cis:
  sysctl:
    net.ipv6.conf.all.disable_ipv6: 0    # re-enable IPv6
    net.ipv4.ip_forward: 1               # enable for routers/containers

Default SSHD options enforce: PermitRootLogin no, PasswordAuthentication no, X11Forwarding no, AllowTcpForwarding no, MaxAuthTries 4, and post-quantum KEX (mlkem768x25519-sha256 on OpenSSH 9.9+). Override per-option:

cis:
  sshd_options:
    - { option: X11Forwarding, value: "yes" }
    - { option: AllowTcpForwarding, value: "yes" }

Note: providing sshd_options replaces the entire list. Copy the defaults from roles/cis/defaults/main.yml and modify as needed.

4.5 VMware Guest Operations

When hypervisor.type: vmware uses the vmware_tools connection:

Variable Description
ansible_vmware_tools_user Guest OS username
ansible_vmware_tools_password Guest OS password
ansible_vmware_guest_path VM inventory path
ansible_vmware_host vCenter/ESXi hostname
ansible_vmware_user vCenter/ESXi API username
ansible_vmware_password vCenter/ESXi API password
ansible_vmware_validate_certs TLS certificate validation

4.6 Multi-Disk Schema

system.disks[0] is the OS disk (no mount.path). Additional entries define data disks.

Key Type Description
size number Disk size in GB (required for virtual)
device string Block device path (required for physical data disks)
partition string Partition device path (required for physical data disks)
mount.path string Mount point (additional disks only)
mount.fstype string btrfs, ext4, or xfs
mount.label string Filesystem label
mount.opts string Mount options (default: defaults)
system:
  disks:
    - size: 80                    # OS disk
    - size: 200                   # Data disk
      mount:
        path: /data
        fstype: xfs
        label: DATA

4.7 Advanced Partitioning Overrides

Variable Default Description
partitioning_efi_size_mib 512 EFI system partition size in MiB
partitioning_boot_size_mib 1024 Separate /boot size in MiB
partitioning_separate_boot auto-derived Force a separate /boot partition
partitioning_boot_fs_fstype auto-derived Filesystem for /boot
partitioning_use_full_disk true Use remaining VG space for root LV

Swap sizing: RAM >= 16GB gets swap = RAM/2. RAM < 16GB gets swap = max(RAM_GB, 2GB). Further capped to prevent over-allocation on small disks.

LVM layout (when not using btrfs): root, swap, and when CIS is enabled: /home (2-20GB, 10% of disk), /var (2GB), /var/log (2GB), /var/log/audit (1.5GB).

4.8 Cleanup Defaults

Post-install verification and recovery settings.

Variable Default Description
cleanup_verify_boot true Check VM accessibility after reboot
cleanup_boot_timeout 300 Timeout in seconds for boot verification
cleanup_remove_on_failure true Auto-remove VMs that fail to boot (created this run only)

5. Execution Pipeline

Roles execute in this order:

  1. global_defaults -- normalize inputs, validate, set OS flags
  2. system_check -- detect installer environment, verify live/non-prod target
  3. virtualization -- create VM (if virtual), attach disks, cloud-init
  4. environment -- prepare installer: mount ISO, configure repos, setup pacman
  5. partitioning -- create partitions, LVM, LUKS, mount filesystems
  6. bootstrap -- install base system and packages (OS-specific)
  7. configuration -- users, fstab, locales, bootloader, encryption enrollment, networking
  8. cis -- CIS hardening (when system.features.cis.enabled: true)
  9. cleanup -- unmount, shutdown installer, remove media, verify boot

6. Usage

ansible-playbook -i inventory.yml main.yml
ansible-playbook -i inventory.yml main.yml -e @vars.yml

Credentials for the first user and root are prompted interactively via vars_prompt unless already set in inventory or passed via -e.

Example inventory files are included:

  • inventory_example.yml -- Proxmox virtual setup
  • inventory_libvirt_example.yml -- libvirt virtual setup
  • inventory_baremetal_example.yml -- bare-metal physical setup

7. Security

Use Ansible Vault for all sensitive values (hypervisor.password, system.luks.passphrase, system.users[].password, system.root.password).

8. Safety

The playbook aborts on non-live/production targets. It refuses to touch pre-existing VMs and only cleans up VMs created in the current run.

Description
An Ansible playbook for automating system bootstrap processes in an Infrastructure-as-Code manner, utilizing ArchISO as the foundational tool.
Readme 2.2 MiB
Languages
Jinja 97.8%
Shell 2.2%