Ansible Role linuxfabrik.lfops.bootloader¶
This role manages the kernel command line of a host, for parameters that only take effect at boot time.
On the Red Hat family the boot entries are written with grubby. Debian and Ubuntu do not package grubby, so there the role deploys a GRUB drop-in of its own and regenerates the boot loader configuration.
Available in the next LFOps release.
How the Role Behaves¶
- Red Hat family: options are applied to every boot entry of the host (
grubby --update-kernel=ALL), so the running kernel and every kernel still installed alongside it carry the same command line.grubbykeepsGRUB_CMDLINE_LINUXin/etc/default/grubin sync while doing so, appending only the managed options and leaving the rest of the file alone. Nothing else in/etc/default/gruband nothing ingrub.cfgis touched. - Debian family: the options are written to
/etc/default/grub.d/z00-lfops.cfgandupdate-grubregenerates/boot/grub/grub.cfgfrom it.grub-mkconfigsources/etc/default/grubfirst and every/etc/default/grub.d/*.cfgafter it, so the drop-in wins without the packaged configuration file ever being edited, and it appends to whateverGRUB_CMDLINE_LINUXalready holds instead of replacing it (the sourcing order was read from thegrub-mkconfigof grub-common 2.12-9+deb13u2 on Debian 13, 2.12-1ubuntu7.3 on Ubuntu 24.04 and 2.14-2ubuntu2.1 on Ubuntu 26.04). Once no option is left to set, the drop-in is removed instead of being left behind empty. - A configured option counts as present only when every boot entry carries it, and it is compared as a whole word with the option escaped, so an option containing a dot matches a dot.
- A run against a host that already carries the configured command line changes nothing and reports no change, and it neither requests a reboot nor touches any file. Changing the value of an option that is already set replaces it rather than adding a second one.
--checkchanges nothing. The dry run reads the current boot entries and reports what it would add or remove.- The change only takes effect on the next boot. When the schedule_reboot mechanism is deployed, a changed command line requests a reboot at the next maintenance window (spool entry
bootloader). Without it, the role only prints a message and leaves the reboot to the operator. lfops__reboot_nowmakes the role apply the change in the same run instead of waiting for the window. The reboot still goes through the same mechanism, so the notification mail, the Icinga downtime and the grace period all apply, and a reboot another role requested earlier in the run is carried out together with this one. The role then waits for the host to come back before the play continues. Set it as--extra-varsfor a single change, or in the inventory for a host group whose reboots need no window. Have a look at the README. With the variable set on a host where theschedule_rebootmechanism is missing, the run aborts rather than reporting a reboot it cannot perform.- On the Red Hat family a kernel installed later inherits the command line from the running kernel.
kernel-installbuilds the boot entry of a new kernel from/etc/kernel/cmdline, from/usr/lib/kernel/cmdline, or, when neither exists, from/proc/cmdlineof the running kernel (verified against/usr/lib/kernel/install.d/20-grub.installon Rocky 9). A kernel installed between the change and the reboot therefore still comes up without the new options; run the role again afterwards. On the Debian family this cannot happen, because installing a kernel regenerates/boot/grub/grub.cfgfrom the drop-in. - The role manages the kernel command line only. It does not add, remove or reorder boot entries, does not change the boot loader timeout, and does not manage the GRUB password.
Known Limitations¶
- GRUB 2 only. Hosts booted by zipl or systemd-boot are not supported.
- Debian family:
state: 'absent'only drops an option from the command line this role writes. An option that comes from/etc/default/grubor from another drop-in stays, because the role never edits files it does not own. On the Red Hat family the same option is removed withgrubby --remove-args. - the
rootoption cannot be managed.grubbyreports it on a line of its own rather than as part of the kernel command line, so the role would never see it as applied and would set it again on every run. It is rejected with an error instead. This does not apply toinitrd, which stays on the command line. - Red Hat family 8: a host that boots in BIOS mode and has
/boot/grub2/grubenvas a symlink into the EFI System Partition is rejected with an error. Boot entries there reference the command line asoptions $kerneloptsand keep the value in that environment block; from a BIOS boot GRUB reads it on/bootand cannot follow the symlink into the ESP, so it falls back to the command line compiled intogrub.cfgand the option never reaches the kernel.grubbyreports the option as applied either way, so the role would otherwise report a converged run that does nothing. The combination comes from images built to boot both ways. An installed host does not have it: booted BIOS it has a regular file there, booted UEFI it reads the copy in the ESP directly. Red Hat family 9 and later put the options in the boot entry itself and are unaffected.
Dependent Roles¶
Any LFOps playbook that installs this role runs these for you. Optional ones can be disabled via the playbook's skip variables.
- Optional: the reboot mechanism should be in place (role: linuxfabrik.lfops.schedule_reboot), so a changed kernel command line reboots the host at the maintenance window instead of waiting for a manual reboot.
Requirements¶
- The host is booted by GRUB 2.
- Red Hat family:
grubbyis installed. It is part of every GRUB installation there, sincekernel-installrelies on it. - Debian family:
grub2-commonis installed. It providesupdate-grub, which the role calls.
Tags¶
bootloader
- Configures the kernel command line.
- Requests a reboot when the kernel command line changed, or performs it in the same run when
lfops__reboot_nowis set. - Triggers: none.
Optional Role Variables¶
These variables are intended to be used in a host / group variable file in the Ansible inventory. Note that the group variable can only be used in one group at a time.
bootloader__cmdline_options__host_var / bootloader__cmdline_options__group_var
- Kernel command line options. An option that is already present with a different value is overwritten. On the Debian family the options end up in
GRUB_CMDLINE_LINUX, so they apply to the recovery entries as well. - Type: List of dictionaries.
- Default:
[] -
Subkeys:
-
name:- Mandatory. Name of the option, for example
psi. - Type: String.
- Mandatory. Name of the option, for example
-
value:- Optional. Value of the option. Omit it for options that stand on their own, for example
quiet. Quote a value YAML reads as a boolean,'on'and'off'among them, otherwise it reaches the command line asTrueorFalse. - Type: String or Number.
- Optional. Value of the option. Omit it for options that stand on their own, for example
-
state:- Optional. Whether the option is added to or removed from the kernel command line. One of
presentorabsent. On the Debian family see "Known Limitations". - Type: String.
- Default:
'present'
- Optional. Whether the option is added to or removed from the kernel command line. One of
-
Example:
# optional
bootloader__cmdline_options__group_var:
- name: 'psi'
value: 1
- name: 'quiet'
- name: 'nosmt'
state: 'absent'
Troubleshooting¶
The run aborts with Could not find or access '<family>.yml'
- The host runs an operating system family this role ships no tasks for. It manages the kernel command line through
grubbyon the Red Hat family and through a GRUB drop-in on the Debian family; there is no third path. The role aborts rather than skipping the host, so a kernel parameter never goes silently unapplied.
The run aborts with /boot/grub2/grubenv is a symlink onto the EFI System Partition
-
The host is a Red Hat family 8 machine that boots in BIOS mode from an image that also carries a UEFI boot path (see "Known Limitations"). The boot loader cannot read the file the kernel command line is stored in, so the option would be written and never applied. Replace the symlink with a regular copy of its target, which is what an installed BIOS host has:
bash cp --remove-destination "$(readlink --canonicalize /boot/grub2/grubenv)" /boot/grub2/grubenvThe next run then applies the options normally. Hosts booting in UEFI mode are not affected and are not checked.
The run aborts with grubby reports root outside the kernel command line
- the
rootoption is configured inbootloader__cmdline_options__*_var. It cannot be managed here (see "Known Limitations"); remove the entry. The root device belongs in the partitioning or in/etc/default/grub.
The run aborts with lfops__reboot_now is set, but /usr/local/sbin/schedule-reboot is missing
- The immediate reboot was requested on a host that does not have the reboot mechanism, so the role can neither reboot through it nor set the Icinga downtime and send the notification that go with it. The check runs before the boot entries are written, so the host is left untouched, and it runs on every host carrying the variable rather than only on those that need a reboot. Either run the schedule_reboot role on the host, which the
bootloaderplaybook does by default unlessbootloader__skip_schedule_rebootis set, or droplfops__reboot_nowand reboot the host yourself.
The option is configured, but /proc/cmdline does not contain it
- The host has not been rebooted since the change. Check the boot entries with
grubby --info=ALLrespectivelygrep linux /boot/grub/grub.cfg; they carry the new command line right away,/proc/cmdlineonly after the reboot.
On a Red Hat-family host a newly installed kernel boots without the configured options
- The kernel was installed while the change was still pending a reboot, so it inherited the command line of the running kernel. Run the role again to update the entry of the new kernel.
On a Debian-family host an option is still on the command line although it is set to state: 'absent'
- The option comes from
/etc/default/grubor from another drop-in in/etc/default/grub.d/, which this role does not touch. Remove it there.