1. Introduction
The Grand Unified Bootloader (GRUB) is a common tool for performing the boot process in most Linux distributions. Despite the intended similarity in the way it’s used, the method of managing it may vary from one Linux distribution to another.
In this tutorial, we’ll learn about the GRUB configuration in Fedora Linux and other RHEL-based distributions.
2. Fedora Distro GRUB Modifications
Let’s take as an example the Fedora distribution, which is a member of the Red Hat Linux family. Since releases 29 and 30, it has been featuring specific GRUB improvements.
First, we should look at how the GRUB menu entries are stored. The usual way is to keep definitions of entries in the /boot/grub2/grub.cfg file in the menuentry blocks. However, Fedora 30 adopted the BootLoaderSpec (BLS) specification, which demands keeping each entry definition in a separate file. We can find these files in the /boot/loader/entries folder. After a fresh installation, it contains our system’s GRUB configuration as well as a rescue configuration:
$ sudo ls /boot/loader/entries
aa2fe2e4c83744f98664b52388fba883-0-rescue.conf
aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64.conf
In addition, Fedora 29 introduced the menu auto-hide function, which hides the GRUB menu when only one kernel is available. The older kernel versions — preserved for the purpose of rescue, for example — don’t count here. Of course, if we’ve set the GRUB menu timeout properly, we can still get to the menu by pressing the F8 key.
We can disable this behavior using the grub2-editenv command:
$ sudo grub2-editenv - unset menu_auto_hide
Consequently, the GRUB menu shows right away.
3. The GRUB Configuration File
The GRUB parameters are stored in the /etc/default/grub file. This is the proper place to make any user modification. Let’s check its content:
$ cat /etc/default/grub
GRUB_TIMEOUT="5"
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT="saved"
GRUB_DISABLE_SUBMENU="true"
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG="true"
Note that the GRUB_ENABLE_BLSCFG parameter is set to true, which informs us that the configuration sticks to the BLS specification.
4. The grub2-mkconfig Command
To change the GRUB configuration, we first edit the /etc/default/grub file. Then, we use the grub2-mkconfig command to generate a new /boot/grub2/grub.cfg file using the contents of/etc/default/grub**.
By default, the GRUB menu is visible for four seconds. If this period is too short for us, we can extend it in the GRUB configuration. As an example, let’s set the timeout to 10 seconds. Thus, we need to change the value of the GRUB_TIMEOUT entry:
$ sudo nano /etc/default/grub
# ...
GRUB_TIMEOUT="10"
Subsequently, let’s update the grub.cfg file:
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
The -o option provides the name of the output file.
5. Setting the Default Kernel
Let’s take a look at the GRUB_DEFAULT=”saved” entry. This value says that the default kernel is the latest one to be installed. Additionally, we can change the kernel referred to as “saved” using the grub2-set-default command. We need to enter the zero-based index, which is 1 for the second entry:
$ sudo grub2-set-default 1
We can override this default by providing the desired entry name with the GRUB_DEFAULT key in /etc/default/grub:
GRUB_DEFAULT="Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)"
To find the entry name within the BLS framework, let’s grep the configuration files in the /boot/loader/entries folder for the title key:
$ sudo sh -c 'grep title /boot/loader/entries/* | cut -d " " -f2-'
Fedora Linux (0-rescue-aa2fe2e4c83744f98664b52388fba883) 38 (Workstation Edition)
Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)
For the changes to take effect, let’s generate the new GRUB configuration file:
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
6. The grubby Command Line Tool
The grubby command comes with the Fedora distribution, so we don’t need to install it. With grubby, we can modify, add, and remove GRUB menu entries. The command accepts a bunch of options to perform various tasks. grubby makes persistent changes to the GRUB configuration.
Let’s list all GRUB entries together with their parameters by employing the –info=ALL option:
$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root rhgb quiet"
root="UUID=f9a12274-d915-4f46-860e-08b3b8f0ea35"
initrd="/boot/initramfs-6.2.9-300.fc38.x86_64.img"
title="Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)"
id="aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64"
index=1
kernel="/boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883"
args="ro rootflags=subvol=root rhgb quiet"
root="UUID=f9a12274-d915-4f46-860e-08b3b8f0ea35"
initrd="/boot/initramfs-0-rescue-aa2fe2e4c83744f98664b52388fba883.img"
title="Fedora Linux (0-rescue-aa2fe2e4c83744f98664b52388fba883) 38 (Workstation Edition)"
id="aa2fe2e4c83744f98664b52388fba883-0-rescue"
First, note that we’re provided with the kernel’s index. Next, we see our system’s kernel entry. vmlinuz-6.2.9-300.fc38.x86_64, and the rescue entry with the vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883 kernel. Both kernels are in the same /boot directory.
Next, the id key provides the name of the entry’s configuration file in the /boot/loader/entries folder.
Now let’s check which entry is the default one with the –default-index option:
$ sudo grubby --default-index
0
Next, let’s find the corresponding kernel with the –default-kernel switch:
$ sudo grubby --default-kernel
/boot/vmlinuz-6.2.9-300.fc38.x86_64
Finally, we can obtain the default kernel’s title with –default-title:
$ sudo grubby --default-title
Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)
7. More Actions With grubby
The grubby actions are fired by passing the appropriate options to the command. If we need to specify the entry we want to print, modify, or delete, we can use the kernel name or entry index. In addition, the keywords DEFAULT and ALL refer to the default kernel and all kernels, respectively.
7.1. Adding and Removing Kernel Arguments
With the –args and –remove-arg options, we can respectively add and remove kernel arguments. Subsequently, we need the –update-kernel switch to point to the target kernel. As an example, let’s allow the boot messages on the screen. So, we need to remove the rhgb quiet combination to hide the splash screen:
$ sudo grubby --remove-args="rhgb quiet" --update-kernel /boot/vmlinuz-6.2.9-300.fc38.x86_64
Afterward, let’s review the changes:
$ sudo grubby --info vmlinuz-6.2.9-300.fc38.x86_64
index=0
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root"
# ...
As this kernel is the default one, we can achieve the same effect using DEFAULT:
$ sudo grubby --remove-args="rhgb quiet" --update-kernel DEFAULT
Finally, let’s use the entry’s index as well:
$ sudo grubby --remove-args="rhgb quiet" --update-kernel 0
7.2. Bulk Changes
We can modify the arguments of all available kernels with –arg and –remove-arg options combined with –update-kernel=ALL. So, let’s disable Fedora’s splash screen for all kernels:
$ sudo grubby --remove-args="rhgb quiet" --update-kernel=ALL
Now, let’s check all kernels:
$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root"
# ...
index=1
kernel="/boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883"
args="ro rootflags=subvol=root"
# ...
Finally, let’s restore the splash screen with –args:
$ sudo grubby --args="rhgb quiet" --update-kernel=ALL
7.3. Changing the Default Kernel
To set the default kernel, we can use the –set-default switch. As a reference, we can use the kernel name or index as well. So, let’s set the rescue kernel as the default one:
$ sudo grubby --set-default=/boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883
The default is /boot/loader/entries/aa2fe2e4c83744f98664b52388fba883-0-rescue.conf with index 1 and kernel /boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883
Next, let’s make the entry of index 0 the default one with –set-default-index:
$ sudo grubby --set-default-index=0
The default is /boot/loader/entries/aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64.conf with index 0 and kernel /boot/vmlinuz-6.2.9-300.fc38.x86_64
7.4. Booting Into Text Mode
A typical case when we’re working with GRUB is enabling text mode. Thus, we need to add 3 to the argument list. Let’s do that for the rescue kernel:
$ sudo grubby --args="3" --update-kernel /boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883
As usual, let’s check the result:
$ sudo grubby --info /boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883
index=1
kernel="/boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883"
args="ro rootflags=subvol=root rhgb quiet 3"
# ...
In this example, we have the splash screen, but we end up in the text console.
7.5. Adding New Entries
With the grubby command, we can add or remove entries in the GRUB menu. So, let’s add the text mode entry permanently with the –add-kernel option:
$ sudo sh -c 'grubby --add-kernel $(grubby --default-kernel) --copy-default --args="3" --title "The text-mode kernel"'
An entry for kernel 6.2.9-300.fc38.x86_64 already exists, adding /boot/loader/entries/aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64.0~custom.conf
First, let’s take a close look at the command construction. The argument to –add-kernel is the path to the kernel, to which we want to add a new entry. We obtained it with the grubby –default-kernel invocation. Of course, we can do it explicitly with –add-kernel vmlinuz-6.2.9-300.fc38.x86_64.
Next comes the –copy-defaults option, which copies as many settings as possible from the current default kernel. Then, we’re adding the 3 text mode argument to the new kernel. Finally, we set the title for the new entry.
Additionally, we could make the new entry the default one by means of the –make-default switch.
Then, let’s examine the results of this command by listing all kernels:
$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root rhgb quiet 3"
root="UUID=f9a12274-d915-4f46-860e-08b3b8f0ea35"
initrd="/boot/initramfs-6.2.9-300.fc38.x86_64.img"
title="The text-mode kernel"
id="aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64.0~custom"
index=1
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root rhgb quiet"
root="UUID=f9a12274-d915-4f46-860e-08b3b8f0ea35"
initrd="/boot/initramfs-6.2.9-300.fc38.x86_64.img"
title="Fedora Linux (6.2.9-300.fc38.x86_64) 38 (Workstation Edition)"
id="aa2fe2e4c83744f98664b52388fba883-6.2.9-300.fc38.x86_64"
# ...
Let’s observe that the new kernel has been added at the first position of the list. We’re going to check if it has automatically become the default one. Let’s recall that, so far, the default one was the kernel with the index 0:
$ grubby --default-index
1
So, the default kernel’s index has been updated accordingly and points to the correct entry.
7.6. Removing Kernel Entries
By passing the index to the –remove-kernel option, we can remove the corresponding entry. So, let’s get rid of the text mode entry of index 0:
$ sudo grubby --remove-kernel=0
Then, let’s verify that the entries have been reindexed:
$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-6.2.9-300.fc38.x86_64"
args="ro rootflags=subvol=root rhgb quiet"
# ...
index=1
kernel="/boot/vmlinuz-0-rescue-aa2fe2e4c83744f98664b52388fba883"
# ...
Therefore, if we’re about to remove more entries, we should always check new indices.
The –remove-kernel option accepts the kernel name as an argument, too. However, we should be extremely cautious when using this approach because all entries that use the same kernel would be removed.
8. Conclusion
In this article, we reviewed Fedora’s and other RHEL-based distributions’ way of maintaining the GRUB menu. First, we talked about the specifics of GRUB configuration in RHEL-based Linux. Next, we learned the grub2-mkconfig command, which applies custom changes to the GRUB configuration.
Next, we focused on the grubby command, designed to fully manage the GRUB menu. We used it to modify kernel arguments, set the default kernel, and create custom configurations.