How do I set a GRUB password in Fedora-bootc

Hi all,

I am building a custom fedora-bootc image and using bootc-image-builder to generate an ISO to provision bare metal. I want to be able to set a GRUB password.

I can build an image, generate an ISO and provision bare metal successfully.
What I am struggling to get right is setting the GRUB password.

I have this in my Containerfile:

FROM quay.io/fedora/fedora-bootc:42

RUN <<EOFRUN
set -euo pipefail

#Set GRUB password

#OPTION 1:

cat >> /etc/grub.d/40_custom << ‘EOF’
set superusers=“root”
password_pbkdf2 root grub.pbkdf2.sha512.10000.YOUR_HASH_HERE
EOF

/usr/bin/grub2-mkconfig -o /boot/grub2/grub.cfg

#OPTION 2:

mkdir -p /boot/grub2
cat > /boot/grub2/user.cfg << ‘EOF’
set superusers=“root”
 password_pbkdf2 root grub.pbkdf2.sha512.10000.YOUR_HASH_HERE
EOF
chmod 600 /boot/grub2/user.cfg

#Validate bootc compliance
bootc container lint

EOFRUN

# Required bootc labels
LABEL containers.bootc=1
LABEL ostree.bootable=1
ENV container=oci

STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]

When building the container,

  • option 1 produces: “/usr/bin/grub2-probe: error: failed to get canonical path of `overlay’.”
  • option 2 produces: “Lint warning: nonempty-boot: Found non-empty /boot: grub2”

I have also tried to set the GRUB password via Anaconda:

My config.toml file:

[customizations.installer.kickstart]
contents = """
# Reboot after installation
reboot --eject

%post --erroronfail
bootc switch --mutate-in-place --transport registry <MYCUSTOM_IMAGE>
# used during automatic image testing as finished marker
if \[ -c /dev/ttyS0 \]; then
  # continue on errors here, because we used to omit --erroronfail
  echo "Install finished" > /dev/ttyS0 || true
fi
%end

# Network information
network  --bootproto=dhcp --device=link --activate

# OSTree container setup
#ostreecontainer --transport="oci" --url="/run/install/repo/container"

# Generated using Blivet version 3.12.1
ignoredisk --only-use=sda,sdb
autopart --type=plain --fstype=xfs --nohome
# Partition clearing information
clearpart --all

#Root password
rootpw --lock
# Set GRUB password
bootloader --location=mbr --boot-drive=sda --iscrypted --password=grub.pbkdf2.sha512.10000.YOUR_HASH_HERE
"""

After installing the ISO generated using the above on to bare metal, I am still able to access GRUB without a password prompt.

Can anyone point me in the right direction please?

Regards,
Steve.

So I got this right by:

  • Specifying the GUB password in /etc/grub.d/40_custom
  • Fixing grub2-mkconfig script with: sed -i ‘/GRUB_DEVICE=/c\GRUB_DEVICE=“${grub_probe} --target=device /sysroot”’ /usr/bin/grub2-mkconfig

as part of the container build.

I also added a custom systemd service to run: grub2-mkconfig -o /boot/grub2/grub.cfg at first boot which regenerates the GRUB config.

This works.

I was hoping I did not need the systemd service though and could do everything declaratively in my Containerfile.

Still interested to know if there is a better way.

As far as I know, at the final stage of the build, the /boot directory in the Fedora bootable container image should be empty.

I haven’t tried to set the stage for modifying the GRUB config during a Fedora bootable container image build, so I am unable do be in any help here.

1 Like

I don’t recommend setting the password in the container image. Anyone with access to it will be able to brute force it. You should also not edit the default GRUB config from the container.

If you want to set a GRUB password, you should write on the system at installation time via Anaconda for example, in a distinct file that is included from the default GRUB config.

Thanks for your input Timothée.

For my use case I have a master image deployed to 1000s of edge devices and wanted all static configuration to be in one place (ideally).

Although the container is private and kept internal, I agree with you and have moved setting the GRUB password to the Anaconda installer, along with some other sensitive configuration.

For anyone else following this thread this is what I’m doing currently:

  1. Containerfile:
# Update GRUB to use the correct root device
RUN sed -i '/GRUB_DEVICE=/c\GRUB_DEVICE="`${grub_probe} --target=device /sysroot`"' /usr/bin/grub2-mkconfig
  1. bootc-image-builder → config.toml:
[customizations.installer.kickstart]
contents = """
# Basic setup
text
network --bootproto=dhcp --device=link --activate

# Basic partitioning
clearpart --all --initlabel --disklabel=gpt
reqpart --add-boot
part / --grow --fstype xfs

rootpw locked
reboot

# Set GRUB password in post-installation script
%post --interpreter /bin/bash

cat >> /etc/grub.d/40_custom <<EOF
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.10000.<PASSWORD_HASH>
EOF

grub2-mkconfig -o /boot/grub2/grub.cfg

%end
"""

Cheers,
Steve.

You should really not do that, this is not recommended. You are overwriting the static GRUB config defined and managed by bootupd. This is likely to break in the future. Why do you need that?

If that is not the recommended way to set a GRUB password, for a bare metal Fedora-bootc install, then what is?

Are you saying only the config file is required? Do I need to run bootupd to apply it or will it happen automatically on boot?

The default static GRUB config that is installed will load additional config commands from the /boot/grub2/custom.cfg file if it exists: bootupd/src/grub2/configs.d/41_custom.cfg at main · coreos/bootupd · GitHub

So you don’t need to update the default config.