In this post, we’re going to explore the grub.sh script, which is designed to handle the configuration and hardening of GRUB across various Linux distributions. This script is part of my Linux automation series on GitHub and is built to simplify boot-time settings for better security and system behavior. We’ll go over each line of the script to understand what it does and how it contributes to the overall configuration.
Why Customize GRUB?
The GRUB bootloader is a powerful tool that handles the boot process for Linux systems. Customizing GRUB settings can improve security, such as by disabling unnecessary services and protecting the boot menu with a password. It can also enhance system performance by removing verbose messages and setting timeout configurations to streamline booting. Our grub.sh script automates these customizations for several popular Linux distributions, so you can get consistent settings across different environments.
1. Step-by-Step Guide to grub.sh
Let’s break down each part of the script.
1.1 Check if the Current User is root
Since these scripts handle low-level configurations and essential Linux setup tasks, they need to run with root (Super-User) privileges. Thus, each script begins by checking if the current user has a user ID of 0, indicating root access.
check_root() {
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
}1.2 Detecting the GRUB Update Command
Different Linux distributions use different commands to update GRUB. The script begins by checking which command is available on your system and assigns it to the variable GRUB_UPDATE_CMD.
if command -v update-grub &> /dev/null; then
GRUB_UPDATE_CMD="update-grub"
elif command -v grub2-mkconfig &> /dev/null; then
GRUB_UPDATE_CMD="grub2-mkconfig -o /boot/grub2/grub.cfg"
else
echo "No supported GRUB update command found."
exit 1
fi
This section:
- Checks if
update-grubexists (typically found on Debian and Ubuntu) and uses it if available. - Checks for
grub2-mkconfig(used by Red Hat-based systems like Fedora and CentOS) and assigns it if found. - Exits if no recognized GRUB update command is found, indicating that GRUB might not be installed. Maybe it is still
LILOor something else.
1.3 Disabling IPv6 (Optional)
If you set the DISABLE_IPV6 variable to true or 1, this section will disable IPv6 system-wide. Disabling IPv6 is often a security measure in environments where IPv6 is not in use.
if [[ $DISABLE_IPV6 =~ true || $DISABLE_IPV6 =~ 1 ]]; then
echo "==> Disabling IPv6"
sed -i 's/^GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="ipv6.disable=1"/' /etc/default/grub
fi
This part of the script:
- Checks for the
DISABLE_IPV6variable in the environment. - Uses
sedto edit/etc/default/grub, appendingipv6.disable=1to theGRUB_CMDLINE_LINUXoption to disable IPv6 at the kernel level.
1.4 Configuring GRUB Boot Options
This section customizes how the GRUB boot menu behaves by modifying settings in /etc/default/grub. It hides unnecessary boot information and disables the GRUB boot menu for a cleaner boot process.
sed -i \
-e '/^GRUB_TIMEOUT=/aGRUB_RECORDFAIL_TIMEOUT=0' \
-e 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="quiet nosplash"/' \
/etc/default/grub
Here’s what this section does:
- Adds
GRUB_RECORDFAIL_TIMEOUT=0, which prevents the boot menu from appearing in case of a previous boot failure. - Sets
GRUB_CMDLINE_LINUX_DEFAULT="quiet nosplash", which hides verbose boot messages and the splash screen. This creates a cleaner, faster boot experience.
1.5 (Optional) Adding Password Protection for GRUB
Securing the GRUB menu with a password is a good way to prevent unauthorized access to the system’s kernel parameters. This section is disabled by default but can be enabled by providing USERNAME and PASSWORD_HASH as environment variables before the script execution.
# Check if PASSWORD_HASH and USERNAME are set in the environment
if [[ -n "$PASSWORD_HASH" && -n "$USERNAME" ]]; then
echo "Setting GRUB superuser and password."
# Write configuration to /etc/grub.d/40_custom
echo "set superusers=\"$USERNAME\"" >> /etc/grub.d/40_custom
echo "password_pbkdf2 $USERNAME $PASSWORD_HASH" >> /etc/grub.d/40_custom
else
echo "Skipping GRUB superuser configuration as PASSWORD_HASH or USERNAME is not set."
fiTo use this feature, run the script as following:
USERNAME='your_user' ; PASSWORD_HASH='your_passowrd_hash' ; grub.sh1.6. Applying the Configuration
After making all necessary changes, the script uses the $GRUB_UPDATE_CMD variable to apply the changes. This command updates the GRUB configuration so that changes are applied the next time the system boots.
echo "==> Applying GRUB configuration"
sudo $GRUB_UPDATE_CMD
This final step ensures that the GRUB settings are saved and ready to be enforced at the next boot.
2. The full overview of the script
#!/bin/bash -ex
# grub.sh - Configure GRUB settings (this usually requires setting up after kernel updates).
# Function to check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
}
check_root
# Detect the distribution and set the update command for GRUB
if command -v update-grub &> /dev/null; then
GRUB_UPDATE_CMD="update-grub"
elif command -v grub2-mkconfig &> /dev/null; then
GRUB_UPDATE_CMD="grub2-mkconfig -o /boot/grub2/grub.cfg"
else
echo "No supported GRUB update command found."
exit 1
fi
# Disable IPv6 if requested
if [[ $DISABLE_IPV6 =~ true || $DISABLE_IPV6 =~ 1 ]]; then
echo "==> Disabling IPv6"
sed -i 's/^GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="ipv6.disable=1"/' /etc/default/grub
fi
# Disable GRUB boot menu and splash screen
sed -i \
-e '/^GRUB_TIMEOUT=/aGRUB_RECORDFAIL_TIMEOUT=0' \
-e 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="quiet nosplash"/' \
/etc/default/grub
# Check if PASSWORD_HASH and USERNAME are set in the environment
if [[ -n "$PASSWORD_HASH" && -n "$USERNAME" ]]; then
echo "Setting GRUB superuser and password."
# Write configuration to /etc/grub.d/40_custom
echo "set superusers=\"$USERNAME\"" >> /etc/grub.d/40_custom
echo "password_pbkdf2 $USERNAME $PASSWORD_HASH" >> /etc/grub.d/40_custom
else
echo "Skipping GRUB superuser configuration as PASSWORD_HASH or USERNAME is not set."
fi
# Apply the GRUB configuration changes
echo "==> Applying GRUB configuration"
$GRUB_UPDATE_CMD
echo "GRUB configuration applied successfully."
Conclusion
This grub.sh script streamlines GRUB configuration across different Linux distributions, automating essential settings for security and user experience. Whether you’re disabling IPv6, simplifying boot menus, or adding password protection, these modifications improve both the security and efficiency of the boot process. By making GRUB changes centrally managed and easily repeatable, this script provides consistency and control over your Linux systems.
Check out the script and the rest of the automation series on my GitHub, and feel free to adapt it for your specific needs. The next time you’re configuring a Linux system, give this GRUB script a try to handle your bootloader setup swiftly and effectively.