Chapter 31. Configuring the GRUB boot loader by using RHEL system roles By using the bootloader RHEL system role, you can automate the configuration and management tasks related to the GRUB boot loader. This role currently supports configuring the GRUB boot loader, which runs on the following CPU architectures: AMD and Intel 64-bit architectures (x86-64) The 64-bit ARM architecture (ARMv8.0) IBM Power Systems, Little Endian (POWER9) 31.1. Updating the existing boot loader entries by using the bootloader RHEL system role You can use the bootloader RHEL system role to update the existing entries in the GRUB boot menu in an automated fashion. This way you can efficiently pass specific kernel command-line parameters that can optimize the performance or behavior of your systems. For example, if you leverage systems, where detailed boot messages from the kernel and init system are not necessary, use bootloader to apply the quiet parameter to your existing boot loader entries on your managed nodes to achieve a cleaner, less cluttered, and more user-friendly booting experience. Prerequisites You have prepared the control node and the managed nodes You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. You identified the kernel that corresponds to the boot loader entry you want to update. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Update existing boot loader entries ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_settings: - kernel: path: /boot/vmlinuz-5.14.0-362.24.1.el9_3.aarch64 options: - name: quiet state: present bootloader_reboot_ok: true The settings specified in the example playbook include the following: kernel Specifies the kernel connected with the boot loader entry that you want to update. options Specifies the kernel command-line parameters to update for your chosen boot loader entry (kernel). bootloader_reboot_ok: true The role detects that a reboot is required for the changes to take effect and performs a restart of the managed node. For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Check that your specified boot loader entry has updated kernel command-line parameters: Additional resources /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file /usr/share/doc/rhel-system-roles/bootloader/ directory Working With Playbooks Using Variables Roles Configuring kernel command-line parameters 31.2. Securing the boot menu with password by using the bootloader RHEL system role You can use the bootloader RHEL system role to set a password to the GRUB boot menu in an automated fashion. This way you can efficiently prevent unauthorized users from modifying boot parameters, and to have better control over the system boot. Prerequisites You have prepared the control node and the managed nodes You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Store your sensitive variables in an encrypted file: Create the vault: After the ansible-vault create command opens an editor, enter the sensitive data in the <key> : <value> format: pwd: <password> Save the changes, and close the editor. Ansible encrypts the data in the vault. Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com vars_files: - vault.yml tasks: - name: Set the bootloader password ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_password: "{{ pwd }}" bootloader_reboot_ok: true The settings specified in the example playbook include the following: bootloader_password: "{{ pwd }}" The variable ensures protection of boot parameters with a password. bootloader_reboot_ok: true The role detects that a reboot is required for the changes to take effect and performs a restart of the managed node. Important Changing the boot loader password is not an idempotent transaction. This means that if you apply the same Ansible playbook again, the result will not be the same, and the state of the managed node will change. For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification On your managed node during the GRUB boot menu screen, press the e key for edit. You are prompted for a username and a password: Enter username: root The boot loader username is always root and you do not need to specify it in your Ansible playbook. Enter password: <password> The boot loader password corresponds to the pwd variable that you defined in the vault.yml file. You can view or edit configuration of the particular boot loader entry: Additional resources /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file /usr/share/doc/rhel-system-roles/bootloader/ directory 31.3. Setting a timeout for the boot loader menu by using the bootloader RHEL system role You can use the bootloader RHEL system role to configure a timeout for the GRUB boot loader menu in an automated way. You can update a period of time to intervene and select a non-default boot entry for various purposes. Prerequisites You have prepared the control node and the managed nodes You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: Configuration and management of the GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Update the boot loader timeout ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_timeout: 10 The settings specified in the example playbook include the following: bootloader_timeout: 10 Input an integer to control for how long the GRUB boot loader menu is displayed before booting the default entry. For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Remotely restart your managed node: On the managed node, observe the GRUB boot menu screen. The highlighted entry will be executed automatically in 10s For how long this boot menu is displayed before GRUB automatically uses the default entry. Alternative: you can remotely query for the "timeout" settings in the /boot/grub2/grub.cfg file of your managed node: Additional resources /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file /usr/share/doc/rhel-system-roles/bootloader/ directory 31.4. Collecting the boot loader configuration information by using the bootloader RHEL system role You can use the bootloader RHEL system role to gather information about the GRUB boot loader entries in an automated fashion. You can use this information to verify the correct configuration of system boot parameters, such as kernel and initial RAM disk image paths. As a result, you can for example: Prevent boot failures. Revert to a known good state when troubleshooting. Be sure that security-related kernel command-line parameters are correctly configured. Prerequisites You have prepared the control node and the managed nodes You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Gather information about the boot loader configuration ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_gather_facts: true - name: Display the collected boot loader configuration information debug: var: bootloader_facts For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification After you run the preceding playbook on the control node, you will see a similar command-line output as in the following example: The command-line output shows the following notable configuration information about the boot entry: args Command-line parameters passed to the kernel by the GRUB2 boot loader during the boot process. They configure various settings and behaviors of the kernel, initramfs, and other boot-time components. id Unique identifier assigned to each boot entry in a boot loader menu. It consists of machine ID and the kernel version. root The root filesystem for the kernel to mount and use as the primary filesystem during the boot. Additional resources /usr/share/ansible/roles/rhel-system-roles.bootloader/README.md file /usr/share/doc/rhel-system-roles/bootloader/ directory Understanding boot entries

Commands:
--- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Update existing boot loader entries ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_settings: - kernel: path: /boot/vmlinuz-5.14.0-362.24.1.el9_3.aarch64 options: - name: quiet state: present bootloader_reboot_ok: true
ansible-playbook --syntax-check ~/playbook.yml
ansible-playbook ~/playbook.yml
ansible managed-node-01.example.com -m ansible.builtin.command -a 'grubby --info=ALL' managed-node-01.example.com | CHANGED | rc=0 >> index=1 kernel="/boot/vmlinuz-5.14.0-362.24.1.el9_3.aarch64" args="ro crashkernel=1G-4G:256M,4G-64G:320M,64G-:576M rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap USDtuned_params quiet " root="/dev/mapper/rhel-root" initrd="/boot/initramfs-5.14.0-362.24.1.el9_3.aarch64.img USDtuned_initrd" title="Red Hat Enterprise Linux (5.14.0-362.24.1.el9_3.aarch64) 9.4 (Plow)" id="2c9ec787230141a9b087f774955795ab-5.14.0-362.24.1.el9_3.aarch64"
ansible-vault create vault.yml New Vault password: <vault_password> Confirm New Vault password: <vault_password>
pwd: <password>
--- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com vars_files: - vault.yml tasks: - name: Set the bootloader password ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_password: "{{ pwd }}" bootloader_reboot_ok: true
ansible-playbook --syntax-check --ask-vault-pass ~/playbook.yml
ansible-playbook --ask-vault-pass ~/playbook.yml
--- - name: Configuration and management of the GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Update the boot loader timeout ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_timeout: 10
ansible-playbook --syntax-check ~/playbook.yml
ansible-playbook ~/playbook.yml
ansible managed-node-01.example.com -m ansible.builtin.reboot managed-node-01.example.com | CHANGED => { "changed": true, "elapsed": 21, "rebooted": true }
ansible managed-node-01.example.com -m ansible.builtin.command -a "grep 'timeout' /boot/grub2/grub.cfg" managed-node-01.example.com | CHANGED | rc=0 >> if [ xUSDfeature_timeout_style = xy ] ; then set timeout_style=menu set timeout=10 Fallback normal timeout code in case the timeout_style feature is set timeout=10 if [ xUSDfeature_timeout_style = xy ] ; then set timeout_style=menu set timeout=10 set orig_timeout_style=USD{timeout_style} set orig_timeout=USD{timeout} # timeout_style=menu + timeout=0 avoids the countdown code keypress check set timeout_style=menu set timeout=10 set timeout_style=hidden set timeout=10 if [ xUSDfeature_timeout_style = xy ]; then if [ "USD{menu_show_once_timeout}" ]; then set timeout_style=menu set timeout=10 unset menu_show_once_timeout save_env menu_show_once_timeout
--- - name: Configuration and management of GRUB boot loader hosts: managed-node-01.example.com tasks: - name: Gather information about the boot loader configuration ansible.builtin.include_role: name: rhel-system-roles.bootloader vars: bootloader_gather_facts: true - name: Display the collected boot loader configuration information debug: var: bootloader_facts
ansible-playbook --syntax-check ~/playbook.yml
ansible-playbook ~/playbook.yml
"bootloader_facts": [ { "args": "ro crashkernel=1G-4G:256M,4G-64G:320M,64G-:576M rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap USDtuned_params quiet", "default": true, "id": "2c9ec787230141a9b087f774955795ab-5.14.0-362.24.1.el9_3.aarch64", "index": "1", "initrd": "/boot/initramfs-5.14.0-362.24.1.el9_3.aarch64.img USDtuned_initrd", "kernel": "/boot/vmlinuz-5.14.0-362.24.1.el9_3.aarch64", "root": "/dev/mapper/rhel-root", "title": "Red Hat Enterprise Linux (5.14.0-362.24.1.el9_3.aarch64) 9.4 (Plow)" } ]