For those running Ubuntu Server (especially headless setups), encountering GRUB 2 stuck at the boot menu is particularly frustrating. The default configuration has some peculiar behaviors that can trigger this:
- After a failed boot attempt, GRUB disables its timeout counter
- Simply showing the menu counts as a "failed boot"
- This creates an infinite loop on headless systems
The standard /etc/default/grub
often contains these relevant parameters:
GRUB_DEFAULT=0
GRUB_TIMEOUT=2
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
While these settings suggest automatic booting, they don't address the core issue of GRUB's failure detection system.
To completely disable GRUB's interactive behavior, we need to modify its timeout logic at the source:
- Edit the GRUB configuration script:
- Locate the
make_timeout()
function and replace it with: - Update GRUB configuration:
sudo nano /etc/grub.d/00_header
make_timeout ()
{
echo "set timeout=0"
}
sudo update-grub2
For those who prefer not to modify system files, these parameters in /etc/default/grub
can help:
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_RECORDFAIL_TIMEOUT=0
However, the first solution is more comprehensive as it prevents all edge cases where GRUB might still wait for input.
After making changes, you can verify the new configuration by examining the generated file:
sudo cat /boot/grub/grub.cfg | grep timeout
You should see set timeout=0
in the output, confirming the changes took effect.
When managing headless Ubuntu servers (especially in embedded environments), you might encounter this frustrating scenario: after an unsuccessful boot attempt, GRUB 2 silently disables its timeout mechanism and waits indefinitely at the menu. This creates a chicken-and-egg problem where failed boots prevent future automatic boots.
The standard /etc/default/grub
often contains these relevant parameters:
GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=2
While these settings appear to configure a 2-second timeout, they don't account for GRUB's "last boot failed" logic that overrides these values.
To completely disable GRUB's timeout interference, modify the timeout generation logic in /etc/grub.d/00_header
:
make_timeout ()
{
echo "set timeout=0"
}
This change forces GRUB to immediately boot the default option regardless of previous boot attempts.
- Edit the file with root privileges:
sudo nano /etc/grub.d/00_header
- Locate the
make_timeout
function (around line 130 in most versions) - Replace its contents with the simple timeout override
- Save changes and update GRUB:
sudo update-grub2
This solution is particularly valuable for:
- Single-board computers (Raspberry Pi, Odroid, etc.)
- Industrial control systems
- Kiosk and digital signage deployments
- Cloud instances with serial console access only
The modification ensures reliable boot sequencing even after power interruptions or failed service starts.
To confirm the changes took effect:
grep "set timeout" /boot/grub/grub.cfg
Should return set timeout=0
in the generated configuration. For thorough testing, simulate boot failures by interrupting the boot process during kernel initialization.