Build a Self-Contained GRUB EFI Image with grub-mkstandalone

Sometimes you need one GRUB executable with its configuration baked in, not read from disk. grub-mkstandalone builds exactly that. This guide creates an x86_64 EFI image, checks it thoroughly, and stops well short of installing it anywhere. Allow about fifteen minutes, and have the grub-common package and enough disk space for the generated image. The examples were checked with GRUB 2.12-1ubuntu7.3 on this machine.

This command only creates a boot image. It does not install a boot entry, copy anything into an EFI System Partition, or change the machine's boot order. Keep those steps separate until the image has been inspected and tested.

1. Check the installed command and target format

Three read-only checks, none needing elevated privileges:

$ command -v grub-mkstandalone
/usr/bin/grub-mkstandalone
$ grub-mkstandalone --version
grub-mkstandalone (GRUB) 2.12-1ubuntu7.3
$ dpkg-query -W -f='${Package} ${Version}\n' grub-common
grub-common 2.12-1ubuntu7.3

The output format is chosen with -O or --format. This guide uses x86_64-efi, one of the formats the installed command lists. Pick a format that matches the firmware or loader that will actually consume the image; an EFI image is not a drop-in replacement for every GRUB platform.

Checkpoint: do not continue until --version and the package query both show the build you intend to use.

2. Prepare a small configuration

Create a temporary configuration outside any real project directory, with a zero-second timeout and one harmless entry:

work_dir=$(mktemp -d /tmp/grub-mkstandalone.XXXXXX)
printf '%s\n' \
    'set timeout=0' \
    'menuentry "Example" { true }' > "$work_dir/grub.cfg"
printf 'configuration: %s\n' "$work_dir/grub.cfg"

That redirection creates or truncates grub.cfg in the temporary directory, so use a fresh directory each time you test. Do not point this at a production /boot/grub/grub.cfg unless you have deliberately chosen that file and checked its permissions first.

Checkpoint: read back the exact file before embedding it:

$ sed -n '1,20p' "$work_dir/grub.cfg"
set timeout=0
menuentry "Example" { true }

3. Generate the standalone EFI image

Give the output path with -o and the platform with -O. The graft point syntax on the final argument maps a path inside the image to a source file on the host:

grub-mkstandalone \
    --format=x86_64-efi \
    --output="$work_dir/grubx64.efi" \
    "/boot/grub/grub.cfg=$work_dir/grub.cfg"

Here, the host file becomes /boot/grub/grub.cfg inside the generated image, which is written to $work_dir/grubx64.efi; nothing on the real system is touched. The command uses the default GRUB directory for the platform, documented as /usr/lib/grub/<platform>.

Run it as your ordinary user first. sudo has no part in image generation unless your chosen input or output path is deliberately protected, and running the whole build as root can hide ownership mistakes that only surface later during deployment.

Warning: --output names a real destination. Do not experiment against a path holding a valuable existing image; write a new file, verify it, then handle backup and replacement as a separate decision.

4. Verify the generated file

Confirm the output exists and that the host recognises the format:

$ file "$work_dir/grubx64.efi"
/tmp/grub-mkstandalone.XXXXXX/grubx64.efi: PE32+ executable (EFI application) x86-64 (stripped to external PDB), 4 sections
$ stat -c '%n %s bytes' "$work_dir/grubx64.efi"
/tmp/grub-mkstandalone.XXXXXX/grubx64.efi 5570560 bytes

The directory name and byte count will differ on your system. What matters is a successful exit status, a non-empty file, and an EFI application identified as x86-64. None of that proves every firmware implementation will boot it, or that every GRUB command in your configuration works.

The command can also read a graft source from standard input, handy when a script generates the configuration on the fly, as long as the output path itself stays explicit:

grub-mkstandalone \
    -O x86_64-efi \
    -o "$work_dir/grubx64-stdin.efi" \
    /boot/grub/grub.cfg=/dev/stdin < <(printf '%s\n' \
        'set timeout=0' \
        'menuentry "Pipe test" { true }')
file "$work_dir/grubx64-stdin.efi"

Use a real file instead when you need to review or archive the embedded configuration; process substitution here is a shell feature, not a special option of the command.

5. Control size and modules only when you need to

Start from the defaults until you know exactly which commands your configuration needs. Test any change with the same file and boot-path checks: a smaller file is not automatically compatible with whatever will consume it.

Common traps

To clean up this guide's temporary state, check that nothing else needs it, then remove the directory:

$ rm -rf -- "$work_dir"

Destructive action: that deletion is irreversible, though it only affects /tmp. It does not uninstall GRUB or touch any system boot configuration.

Done means