This dracut module is created for the ansible bare-metal-install collection tuxifier.
It features the following:
- It depends on the dracut-sshd module, and on the dracut modules
network,mdraidandcrypt. - It includes a
pythonconda environment with support for linux-system-roles.storage and some other basic tools in the initial ramdisk. By packaging a conda environment. (See: python-nest) - It pauses the boot process just before the root filesystem gets mounted (dracut
pre-mounthook)
This combination makes it possible to use ansible to:
- partition (a) disk(s)
- install an OS
- poweroff the machine
or - continue the boot to the freshly installed OS and continue your ansible playbook from there.
This repository is one of four that make up the tuxifier installer:
| Repository | Role |
|---|---|
dracut-incubator (this one) |
The dracut module that puts the packed python-nest environment in an initramfs and holds the boot until the install is done |
| python-nest | The conda recipes and the environment that make up the python-nest environment |
| tuxifier | The ansible collection that runs inside that initramfs and installs the OS |
| tuxifier-playbook | An example playbook and inventory |
- The
dracut-incubatormodule depends on and installs thepython-nest.squashfsconda environment. The build system supplies the ssh host keys and theauthorized_keysof the initramfs, see SSH access. - The machine boots the initramfs with its kernel. The network is brought up (
rd.neednet=1) andsshdstarts. - The
initqueuehooks run.defer-root-wait.shcancels the wait for the root device, which, possibly, does not exist yet.mount-conda-squashfs.shmounts the squashfs read-only on/local/conda/envs/python-nest. - The
pre-mounthookwait_for_ansible_finished.shstops the boot. Every 5 seconds it writes a line to/dev/consolewith the uptime and the contents of/tmp/message, if that file exists. - Ansible connects over ssh as root and uses the python interpreter of the mounted environment to partition the disks and install the OS. tuxifier writes its progress to
/tmp/message. - When the playbook is done it creates the file
/tmp/ansible-finished. The boot continues. Withansible_tuxifier__continue_install: falsetuxifier has installed apre-pivothook that powers the machine off. Withansible_tuxifier__continue_install: truethe boot goes on into the installed system. See theansible_tuxifier__continue_installvariable of tuxifier. - The
cleanuphookumount-python-nest.shunmounts the squashfs, and dracut mounts the root filesystem (root=) and switches to it.
The module is not enabled by default: it has to be requested with -a incubator.
-
Clone this repository and copy or link the
dracut-incubator/94incubatordirectory to the/usr/lib/dracut/modules.d/directory. The module is calledincubator: dracut drops the number in front of the directory name. -
Download the pre-packaged python-nest.squashfs
and place it in/usr/lib/dracut/modules.d/94incubator/
Or
- build and modify the
python-nest.squashfsas described here: python-nest
and place it in/usr/lib/dracut/modules.d/94incubator/
Without the squashfs dracut stops with Missing …/94incubator/python-nest.squashfs.
The initramfs image can be built using the following command:
sudo dracut -NM -a "incubator" incubator-initramfs-$(uname -r).img $(uname -r)
The build is not meant for a host-only initramfs, hence -N. Prebuilt images are listed in the tuxifier-playbook repository.
The incubator module pulls in the dracut modules below. They are needed to support the storage layouts of linux-system-roles.storage:
| dracut module | adds | enables |
|---|---|---|
sshd |
sshd, the ssh host keys and authorized_keys |
Logging in from the Ansible controller |
network |
The network configuration | rd.neednet=1 and the ip= arguments |
crypt |
The kernel modules and libraries for LUKS | LUKS encrypted volumes |
mdraid |
mdadm, the md udev rules (63-md-raid-arrays.rules, 64-md-raid-assembly.rules) and the raid* and dm-raid kernel modules |
md RAID (type: raid, or raid_level on an lvm pool) and LVM RAID volumes |
The module itself also installs chroot (the dracut of Fedora does not, the tuxifier role needs it), chmod, date, dirname and ldconfig.
On Fedora the dracut module network needs the packages dracut-network and dhcp-client on the system the initramfs is built on, else dracut stops with Module 'incubator' depends on module 'network', which can't be installed. On Rocky Linux, AlmaLinux and RHEL dracut-network brings them.
mdadm has to be installed on the system the initramfs is built on. Without it dracut stops with dracut module 'incubator' depends on 'mdraid', which can't be installed. Without the md udev rules the storage role fails with mdadm: /dev/vdX is busy - skipping.
Note
These modules only provide the tools in the initramfs used for the install. For the installed system the tuxifier role installs cryptsetup and mdadm, writes /etc/crypttab and /etc/mdadm.conf from the devices it created, and the kernel package builds the initramfs of the installed system, which selects the crypt and mdraid modules itself.
The sshd module copies the keys that give access to the initramfs from the system on which dracut runs. Without them nobody can log in, and dracut stops with No authorized_keys for root user found! or Didn't find any SSH host key!.
authorized_keys. The public keys that are allowed to log in as root. The first of these files that exists on the build system is used:
| Priority | File | Remarks |
|---|---|---|
| 1 | /root/.ssh/dracut_authorized_keys |
Use this file to give the initramfs other keys than the root user of the build system. |
| 2 | /etc/dracut-sshd/authorized_keys |
|
| 3 | /root/.ssh/authorized_keys |
The default: the keys of the root user of the build system. |
This is the behavior of dracut-sshd, see its documentation (the Install section and the FAQ) for the details. To change the keys, edit the file that is used, or create a file of higher priority, and build the initramfs again: the keys are copied into the image while it is built.
For example, to give the initramfs the key of an Ansible controller without touching the authorized_keys of root on the build system:
sudo sh -c 'umask 077; echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyOfTheController ansible@controller" >> /root/.ssh/dracut_authorized_keys'
sudo dracut -NM -a "incubator" incubator-initramfs-$(uname -r).img $(uname -r)
sudo lsinitrd incubator-initramfs-$(uname -r).img | grep authorized_keys
The lsinitrd line shows that root/.ssh/authorized_keys is in the image. A key can be in the image and still be refused when the root account is locked (!) in /etc/shadow; see the FAQ of dracut-sshd.
The authorized_keys of the initramfs are also added to the root user of the installed system by tuxifier, together with the keys from its ansible_tuxifier__root_authorized_keys variable.
Host keys. The ssh host keys of the build system are copied into the image: /etc/ssh/dracut_ssh_host_*_key if they exist, otherwise /etc/ssh/ssh_host_*_key. Every machine booted from the image has that identity. Anyone who can read the image can read the private keys, and an ssh client that connected to another image from the same build system sees the same host key.
sftp. If the sshd_config of the initramfs has no internal-sftp subsystem, the module adds Subsystem sftp internal-sftp before the first AcceptEnv line, so that file transfers work without an sftp-server binary.
The initramfs file together with its kernel need to be fed to the server by any way possible. For instance: PXE, virt-manager Direct kernel boot, customized grub.
The image is large, about 240 MB, because it contains the squashfs with the python-nest environment. Give the machine enough memory: the test installs use 2 GiB.
| kernel argument | description |
|---|---|
rd.neednet=1 |
The initial ramdisk execution requires network accessibility. The network is configured by dracut, so the standard dracut ip= arguments apply. |
root=LABEL=root |
The root argument should be set to the device that contains the root filesystem after the install is finished. Use LABEL=… or a device path such as /dev/vda2. Other forms, such as UUID=…, are not supported: the wait for the device is only cancelled for these two. |
enforcing=0 |
selinux should be disabled during the install. |
The progress messages of the wait loop are written to /dev/console. The kernel connects /dev/console to the device of the last console= argument of the kernel command line, when the arguments are of different device types. Kernel messages appear on all of them. Put the console you watch last, for instance console=tty0 console=ttyS0 to receive the messages on the serial console. Without a console= argument there may be no output.
| Symptom | Cause | Solution |
|---|---|---|
dracut stops with Missing …/94incubator/python-nest.squashfs |
The squashfs is not in the module directory. | See Installing the dracut-incubator module. |
dracut stops with module 'incubator' depends on 'mdraid', which can't be installed |
mdadm is not installed on the build system. |
Install mdadm there. |
dracut stops with No authorized_keys for root user found! or Didn't find any SSH host key! |
The build system has no ssh keys for the initramfs. | See SSH access. |
The machine boots, but ssh is refused with Permission denied (publickey) |
The key you use is not in the authorized_keys that were copied into the image when it was built. |
Add the key as described in SSH access and build the initramfs again. |
| Ansible cannot connect | The network did not come up: rd.neednet=1 is missing, or there is no dhcp or ip= configuration. |
Check the boot arguments and the console. |
The console shows Missing Conda squashfs image or Could not mount … on /local/conda/envs/python-nest |
The squashfs is not in the image, or the kernel modules loop and squashfs are missing, for instance in a host-only image. |
Build the initramfs as described above, without host-only. |
| No progress messages on the console | The messages go to the last console= argument, or there is none. |
Put the console you watch last, see Console output. |
The storage role fails with mdadm: /dev/vdX is busy - skipping |
The md udev rules are missing. | Build with the mdraid module, which the incubator module pulls in. |
This module is licensed under the EUPL 1.2.