Ansible Bootstrap Playbook

Automate Linux system bootstrap across multiple distributions and hypervisors in an Infrastructure-as-Code workflow.

Supported Distributions

Distribution Versions
AlmaLinux 8.x, 9.x, 10.x
Alpine Linux latest
Arch Linux latest
Debian 10, 11, 12, 13, unstable
Fedora 40, 41, 42, 43
openSUSE Tumbleweed latest
RHEL 8.x, 9.x, 10.x
Rocky Linux 8.x, 9.x, 10.x
Ubuntu latest
Ubuntu LTS latest
Void Linux latest

Supported Hypervisors

Hypervisor Value
libvirt libvirt
Proxmox proxmox
VMware vmware
Xen xen
Bare metal none

Compatibility Notes

  • rhel_iso is required for system.os: rhel.
  • RHEL installs should use system.filesystem: ext4 or system.filesystem: xfs (not btrfs).
  • For RHEL 8 specifically, prefer ext4 over xfs if you hit installer/filesystem edge cases.
  • custom_iso: true skips ArchISO validation and pacman preparation; your installer image must already provide required tooling.
  • On non-Arch installers, set system.features.chroot.tool (arch-chroot, chroot, or systemd-nspawn) explicitly as needed.

Configuration Model

The project uses only dict-based variables:

  • system for host/runtime/install configuration
  • hypervisor for virtualization backend configuration

These dictionaries are normal Ansible variables and belong in host/group vars. You can define them in inventory host entries, group_vars/*, or host_vars/*. Dictionary variables are merged across scopes (group_vars -> host_vars) by project config. Set shared values like system.filesystem once in group vars, then override only host-specific keys per host.

Variable Placement

Location Scope Typical use
group_vars/all.yml All hosts Shared defaults like hypervisor, system.filesystem, boot_iso
group_vars/<group>.yml Group Environment or role-specific defaults
host_vars/<host>.yml Single host Host-specific overrides
Inventory host vars Single host Inline definitions for quick setup

Example Host Definition

all:
  vars:
    system:
      filesystem: btrfs
    boot_iso: "local:iso/archlinux-x86_64.iso"
    hypervisor:
      type: proxmox
      url: pve01.example.com
      username: root@pam
      password: CHANGE_ME
      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
            balloon: 0
            network: 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
            user:
              name: ops
              password: CHANGE_ME
              key: "ssh-ed25519 AAAA..."
            root:
              password: CHANGE_ME
            luks:
              enabled: true
              passphrase: CHANGE_ME
              auto: true
              method: tpm2
              tpm2:
                pcrs: "7"
            features:
              firewall:
                enabled: true
                backend: firewalld
                toolkit: nftables

Core Variables

Variable Type Description
boot_iso string Required when system.type=virtual
rhel_iso string Required when system.os=rhel
custom_iso bool Skip Arch ISO-specific preparation checks

system Dictionary

Top-level host install/runtime settings. Use these keys under system.

Key Type Default Description
type string virtual virtual or physical
os string empty (archlinux if omitted on physical) Target distribution
version string empty Version selector for distro families
filesystem string empty btrfs, ext4, or xfs
name string inventory hostname Final hostname
id int/string empty VMID for Proxmox
cpus int 0 vCPU count
memory int 0 Memory in MiB
balloon int 0 Balloon memory in MiB
network string empty Hypervisor network/bridge
vlan string/int empty VLAN tag
ip string empty Static IP (optional)
prefix int empty Prefix for static IP
gateway string empty Static gateway
path string empty Hypervisor folder/path (libvirt/vmware)
packages list/string empty Post-reboot packages
dns dict {servers: [], search: []} DNS nested dictionary
disks list [] Disk layout list
user dict {name:'', password:'', key:''} User account dictionary
root dict {password:''} Root account dictionary
luks dict see below Encryption dictionary
features dict see below Feature flags dictionary

system.dns

DNS options used by network configuration tasks. Use these keys under system.dns.

Key Type Default Description
servers list/string [] DNS resolvers; comma-separated string is normalized
search list/string [] Search domains; comma-separated string is normalized

system.user

Target user account settings. Use these keys under system.user.

Key Type Default Description
name string empty Username created on target
password string empty User password (also used for sudo/become)
key string empty SSH public key for authorized_keys

system.root

Use these keys under system.root.

Key Type Default Description
password string empty Root password

system.luks

LUKS container, unlock, and initramfs-related settings. Use these keys under system.luks.

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

system.luks.tpm2

TPM2-specific policy settings used when system.luks.method=tpm2. Use these keys under system.luks.tpm2.

Key Type Default Allowed Description
device string auto auto or device path TPM2 device selector
pcrs string/list empty PCR expression PCR binding policy (for example "7" or "0+7")

system.features

Feature toggles for optional system configuration. Use these keys under system.features.

Key Type Default Allowed Description
cis.enabled bool false true/false Enable CIS hardening role
selinux.enabled bool true true/false SELinux management
firewall.enabled bool true true/false Enable firewall role actions
firewall.backend string firewalld firewalld,ufw Firewall service backend
firewall.toolkit string nftables nftables,iptables Packet filtering toolkit selection
ssh.enabled bool true true/false SSH service/package management
zstd.enabled bool true true/false zstd related tuning
swap.enabled bool true true/false Swap setup toggle
banner.motd bool true true/false MOTD banner management
banner.sudo bool true true/false Sudo banner management
chroot.tool string arch-chroot arch-chroot,chroot,systemd-nspawn Chroot wrapper command

Multi-Disk Schema

system.disks[0] is always the OS disk. Additional entries can define data disks.

Key Type Description
size number Disk size in GB (required for virtual)
device string Explicit disk device (required for physical data disks)
mount.path string Mount target (for additional disks)
mount.fstype string btrfs, ext4, or xfs
mount.label string Optional filesystem label
mount.opts string Mount options (defaults by default)

Example:

system:
  disks:
    - size: 80
    - size: 200
      mount:
        path: /data
        fstype: xfs
        label: DATA
        opts: defaults,noatime
    - size: 300
      mount:
        path: /backup
        fstype: ext4

For physical installs, include device paths:

system:
  type: physical
  disks:
    - device: /dev/sda
      size: 120
    - device: /dev/sdb
      size: 500
      mount:
        path: /data
        fstype: ext4

Advanced Partitioning Overrides

Use these only when you need to override default layout behavior.

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

hypervisor Dictionary

Use these keys under hypervisor.

Key Type Description
type string libvirt, proxmox, vmware, xen, none
url string Proxmox/VMware API host
username string API username
password string API password
host string Proxmox node name
storage string Proxmox/VMware storage
datacenter string VMware datacenter
cluster string VMware cluster
certs bool TLS cert validation for VMware
ssh bool VMware installer SSH bootstrap helper

VMware Guest Operations Variables

When hypervisor.type: vmware and connection uses vmware_tools, ensure these variables are set in inventory/group/host vars as needed by your vCenter/ESXi environment.

Variable Description
ansible_vmware_tools_user Guest OS username for guest operations
ansible_vmware_tools_password Guest OS password for guest operations
ansible_vmware_guest_path VM inventory path (/datacenter/vm/folder/name)
ansible_vmware_host vCenter/ESXi host
ansible_vmware_user vCenter/ESXi API username
ansible_vmware_password vCenter/ESXi API password
ansible_vmware_validate_certs Enable/disable TLS certificate validation

Prerequisites

  • Ansible installed on the control machine.
  • Inventory and variables prepared for your target hosts.
  • Disposable/non-production targets (the playbook enforces production-safety checks).

Usage

ansible-playbook -i inventory_example.yml main.yml
ansible-playbook -i inventory_libvirt_example.yml main.yml
ansible-playbook -i inventory.yml main.yml -e @vars_example.yml

Security

Store sensitive data (passwords, API tokens, private keys) with Ansible Vault instead of plaintext inventory files.

Operational Notes

  • For virtual installs, system.cpus, system.memory, and system.disks[0].size are required and validated.
  • For physical installs, sizing is derived from the detected install drive; set installer access (ansible_user/ansible_password) when needed.
  • system.dns.servers and system.dns.search accept either YAML lists or comma-separated strings.
  • hypervisor.type selects backend-specific provisioning/cleanup behavior.
  • Guest tools are selected automatically by hypervisor: qemu-guest-agent (libvirt/proxmox) and open-vm-tools (vmware).
  • With system.luks.method: tpm2 on virtual installs, the virtualization role enables a TPM2 device where supported.
  • With LUKS on non-Arch targets, provisioning may use a separate /boot; tune with partitioning_efi_size_mib and partitioning_boot_size_mib.
  • For VMware, hypervisor.ssh: true enables SSH on the guest and switches the connection to SSH for remaining tasks.
  • Molecule scenario is lint-focused (delegated driver with non-destructive placeholder converge).

Safety

This playbook intentionally aborts if it detects a non-live/production target. It also refuses to touch pre-existing VMs and only cleans up VMs created in the current run.

Validation

Always run lint after changes:

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