Sunday, May 3, 2026

 

Migrating Fedora from GRUB to systemd-boot

A Guide for Fedora 44

If you've been running Fedora for a while, your system almost certainly has the same partition layout the installer has been creating for years: a small FAT32 EFI partition and a separate /boot partition. This guide will walk you through replacing GRUB with systemd-boot and merging those two partitions into one clean setup.

Each step was tested on a Fedora 44 system. Follow carefully and you'll be done in about 30 minutes.

Before You Start

Who this guide is for

  • Fedora users on a single-drive, single-boot system (no Windows dual boot)
  • Systems with the standard Fedora partition layout: EFI partition + separate /boot partition
  • UEFI systems only (systemd-boot does not support Legacy BIOS)

Who should stop reading now

  • Dual-boot Windows users
  • BitLocker users
  • Systems with encrypted /boot
  • Legacy BIOS systems

What you'll need

  • A Fedora Live USB
  • Physical access to your machine
  • Your BIOS key (common choices: F2, Del, ESC, F7; check your motherboard manual)
  • About 30 minutes

Why bother?

GRUB has served Linux well for decades, but it is significantly more complex than most users need. It contains hundreds of thousands of lines of code, including its own filesystem drivers, all running before your OS starts, before any security protections are active. For the vast majority of users, that complexity exists purely to solve problems they don't have.

systemd-boot is simpler by design. It reads only FAT32 (the same filesystem your UEFI firmware reads natively), has a fraction of the codebase, and is straightforward to configure and maintain. Less code also means less attack surface. BootHole in 2020 demonstrated this concretely; a buffer overflow in GRUB's config parser allowed attackers to bypass Secure Boot entirely. That class of vulnerability doesn't exist in systemd-boot because the complexity that enabled it doesn't exist.

systemd-boot is also where Fedora, and the Linux ecosystem broadly, is heading. This guide gets you there now.

Understanding the Partition Problem

A standard Fedora install creates this:

/dev/nvme0n1p1   600MB   vfat               /boot/efi   ← EFI System Partition
/dev/nvme0n1p2   1GB     xfs/ext4/btrfs     /boot       ← Boot partition (kernels live here)
/dev/nvme0n1p3   64GB    swap
/dev/nvme0n1p4   1.8TB   xfs/btrfs          /           ← Root partition

Fedora's installer (Anaconda) has used different filesystems for /boot over the years depending on the version and installation choices:

  • XFS: common default in recent Fedora versions
  • ext4: was the default for many years, common on older installations
  • btrfs: increasingly common, especially when Fedora's btrfs-by-default option is selected

It doesn't matter which one you have. The problem is identical regardless: systemd-boot cannot read XFS, ext4, or btrfs. It only speaks FAT32, the same filesystem your UEFI firmware uses natively. GRUB worked with these filesystems because it carries its own filesystem drivers. systemd-boot deliberately does not, which is a feature: less code means less attack surface.

The solution is the same in every case: merge the two partitions into one larger FAT32 partition. This is the direction the Linux ecosystem is moving toward, with a single, larger EFI partition that holds both the bootloader and the kernels.

End result:

/dev/nvme0n1p1   1.7GB   vfat        /boot/efi   ← Single merged partition
/dev/nvme0n1p3   64GB    swap
/dev/nvme0n1p4   1.8TB   xfs/btrfs   /           ← Root partition (unchanged)

First: Check Your Layout

lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINTS

Confirm:

  • A vfat partition mounted at /boot/efi
  • A partition (xfs, ext4, or btrfs) mounted at /boot
  • Your root partition mounted at /

Phase 1: Prepare Your Running System

Do these steps before you boot the Live USB.

Step 1: Install systemd-boot

Fedora doesn't install the systemd-boot binaries by default. Install the unsigned version (we're disabling Secure Boot anyway):

run0 dnf install systemd-boot-unsigned
run0 bootctl install

Step 2: Set the Boot Layout

Tell Fedora's kernel management tools to use the Boot Loader Specification format instead of GRUB-specific entries:

run0 mkdir -p /etc/kernel
echo "layout=bls" | run0 tee /etc/kernel/install.conf

Step 3: Capture Your Kernel Command Line

Your current boot parameters need to be preserved. This command captures them and strips the GRUB-specific prefix:

cat /proc/cmdline | sed 's/BOOT_IMAGE=[^ ]* //' | run0 tee /etc/kernel/cmdline

Verify the output looks correct. It should be a single line starting with root=UUID=... and containing your boot parameters. If you have selinux=0 or other custom flags, confirm they are present.

Step 4: Set the Boot Order

Tell your firmware to prefer systemd-boot. First check current entries:

run0 efibootmgr

Find the ID number for "Linux Boot Manager" and put it first. For example, if Linux Boot Manager is 0001 and Fedora is 0000:

run0 efibootmgr -o 0001,0000

Step 5: Prevent tuned Conflicts

Fedora's tuned service tries to inject power management parameters into your boot entries. This works with GRUB but breaks systemd-boot. Disable it proactively:

run0 sed -i 's/TUNED_BOOT_CMDLINE_PARAM=.*/TUNED_BOOT_CMDLINE_PARAM=""/' /etc/tuned-main.conf

Phase 2: The Partition Merge (Live USB)

Reboot into your Fedora Live USB. Open a terminal and switch to root:

run0

Step 6: Mount Your Root Partition

mount /dev/nvme0n1p4 /mnt

Replace nvme0n1p4 with your actual root partition if different. If unsure, run lsblk to confirm.

Step 7: Mount Your EFI Partition

mkdir -p /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi

Step 8: Back Up Your EFI Partition

cp -r /mnt/boot/efi /mnt/temp_efi_backup

Verify the backup:

ls /mnt/temp_efi_backup

You should see folders like EFI, loader, and a long machine-id string.

Step 9: Unmount the EFI Partition

umount /mnt/boot/efi

Step 10: Check the Partition Layout

parted /dev/nvme0n1 print

Note the End value of your /boot partition (p2). You'll use this in the next step. In a standard Fedora install this is typically around 1704MB, but it will vary on your system.

Step 11: Delete the Boot Partition

parted /dev/nvme0n1 rm 2

You'll see a message saying you may need to update /etc/fstab. We'll handle that shortly.

Step 12: Resize the EFI Partition

Expand p1 to fill the space left by the deleted partition. Use the End value you noted in Step 10:

parted /dev/nvme0n1 resizepart 1 1704MB

Step 13: Format the Enlarged Partition

Since we changed the size, we need to reformat. Your backup is safe in /mnt/temp_efi_backup:

mkfs.fat -F32 /dev/nvme0n1p1

Step 14: Mount the New Partition

mount /dev/nvme0n1p1 /mnt/boot/efi

Step 15: Restore Your Backup

cp -r /mnt/temp_efi_backup/* /mnt/boot/efi/

Verify the restore:

ls /mnt/boot/efi

You should see your EFI files back in place.

Step 16: Get the New UUID

Reformatting created a new UUID. Write this down, you will need it for fstab:

lsblk -o NAME,UUID /dev/nvme0n1p1

Step 17: Check and Update fstab

cat /mnt/etc/fstab

You need to make two changes:

  1. Update the UUID for the /boot/efi line to the new UUID from Step 16
  2. Delete the line for /boot entirely, as that partition no longer exists

Edit the file:

nano /mnt/etc/fstab

Note: In some cases Fedora's fstab may already show the correct UUID if the partition inherited it. Always verify before assuming.

Step 18: Verify the Final Partition Table

parted /dev/nvme0n1 print

You should see only three partitions: p1 (fat32, ~1.7GB), p3 (swap), p4 (your root filesystem). No p2.

Step 19: Check Boot Entries Exist

ls /mnt/boot/efi/loader/entries/

You should see .conf files here. If this folder is empty, your kernel entries didn't survive the migration. In that case run:

kernel-install add [KERNEL_VERSION] /lib/modules/[KERNEL_VERSION]/vmlinuz

Replace [KERNEL_VERSION] with your actual kernel version (e.g. 7.0.3-200.fc44.x86_64). If unsure of the version, check /mnt/lib/modules/ to see what's installed. If entries are present, skip this step.

Phase 3: First Boot into systemd-boot

Reboot the machine and immediately enter your BIOS/UEFI settings.

In the BIOS:

  1. Disable Secure Boot. This is required because we installed the unsigned systemd-boot binary. Without this the firmware will refuse to run it.
  2. Set boot order. Move "Linux Boot Manager" to position #1.
  3. Save and exit.

What to expect:

Instead of the Fedora GRUB menu, you'll see a simple black-and-white text menu. Use arrow keys to select your kernel and press Enter.

If you see a blank screen or "File not found" error, reboot and press your boot menu key (usually F12) to manually select an entry. If you still have the GRUB Fedora entry available, select it to get back into your system and troubleshoot.

Phase 4: Post-Boot Cleanup

These final steps clean up after the migration.

Step 20: Verify systemd-boot is Running

run0 bootctl status

You should see Product: systemd-boot under Current Boot Loader, with all features showing ✓.

Step 21: Verify Kernel Entries

run0 bootctl list

Your current kernel should appear as (default) (selected). If you have multiple kernels installed they should all be listed.

Step 22: Clean Up Stale EFI Entries

Check what's in your EFI variables:

run0 efibootmgr

Delete any remaining Fedora/GRUB entries, as they are no longer needed. For each stale entry ID (e.g. 0000, 0006):

run0 efibootmgr -b 0000 -B

Leave only "Linux Boot Manager" in the list.

Step 23: Enable Automatic Bootloader Updates

As of systemd version 250, a service exists that keeps the systemd-boot binary itself up to date automatically. Enable it:

run0 systemctl enable systemd-boot-update.service
run0 systemctl start systemd-boot-update.service

Without this, the systemd-boot binary on your ESP can fall out of sync with the version installed by dnf.

Step 24: Configure the Boot Menu

Set a timeout so you have time to select a different kernel if needed:

run0 nano /boot/efi/loader/loader.conf

It should contain:

timeout 3
console-mode keep
default @saved

timeout 3 gives you a 3 second window before it boots automatically. default @saved remembers whichever kernel you last booted. Without a timeout configured, systemd-boot skips the menu entirely, which means you'll have no way to select an older kernel if a bad update comes through.

Step 25: Final Verification

Run these verification checks:

run0 bootctl status
run0 bootctl list
systemctl is-enabled systemd-boot-update.service
run0 efibootmgr
run0 cat /boot/efi/loader/loader.conf

Everything should be clean: one boot entry in EFI variables, all kernels listed, service enabled, timeout configured.

Will Future Kernel Updates Work Automatically?

Yes, with one caveat. Fedora's kernel-install scripts will automatically place new kernels on your ESP when you run dnf update. However, the scripts still contain some GRUB references that generate harmless warnings like:

grub2-editenv: error: failed to get canonical path of `/boot/grub2'

This is benign. The kernel installs correctly regardless. After any kernel update, verify with:

run0 bootctl list

If the new kernel appears, everything is working. If it doesn't appear, use the emergency kernel-install add command from Step 19.

What About Secure Boot?

Secure Boot is disabled in this guide because we installed the unsigned systemd-boot binary. For most home users this is a reasonable tradeoff. The security benefit of Secure Boot is primarily protection against physical "evil maid" attacks on unattended hardware.

The path to re-enabling Secure Boot with systemd-boot involves Unified Kernel Images (UKIs), which are single signed .efi files that combine the kernel, initrd, and command line into one tamper-evident package. Fedora is actively working toward making this the default. Your current setup is already compatible since systemd-boot supports UKIs natively and your ESP has sufficient space.

Troubleshooting

Blank screen on boot: Secure Boot is probably still enabled. Enter BIOS and disable it.

"No entries found" in systemd-boot menu: Your .conf files are missing. Boot into the Live USB, mount your ESP, and run kernel-install add as described in Step 19.

System drops to emergency shell: Your fstab UUID is wrong. Boot the Live USB, mount your root partition, and correct the UUID in /mnt/etc/fstab.

"Error preparing initrd": The tuned service injected a bad parameter. Press e at the boot menu to edit the entry and remove any initrd /tuned... reference from the options line. Then re-run the tuned fix from Step 5 and reinstall the kernel entry.

GRUB keeps loading despite boot order change: Some firmware ignores efibootmgr changes and hardcodes a preference for \EFI\fedora\shimx64.efi. Enter your BIOS boot menu manually (usually F7 or F12) and select "Linux Boot Manager" directly. Once confirmed working, the EFI variable order should stick on subsequent boots.

btrfs /boot note: If your /boot was formatted as btrfs the deletion and reformat process is identical. btrfs requires no special handling. It is simply another filesystem that systemd-boot cannot read, and the partition merge resolves that the same way as XFS or ext4.

Summary

You now have:

  • systemd-boot replacing GRUB
  • A single clean ~1.7GB FAT32 boot partition
  • Automatic bootloader updates configured
  • A 3 second boot menu timeout
  • A setup compatible with the upcoming UKI and Secure Boot transition

Fedora's default partition layout was designed around GRUB, which is why this manual migration is necessary in the first place. On a fresh install configured correctly from the start, none of this would be needed.

Saturday, November 1, 2025

PostgreSQL Upgrade - Fedora 43

NOTE: Fedora 42 shipped PostgreSQL 16 and Fedora 43 jumps to PostgreSQL 18.
postgresql-upgrade only provides PG17 binaries, so the PG16 toolchain needed for pg_upgrade is not present. 

Until this is fixed in Fedora, see Bug 2411778 for the workaround.

Fedora 43 will upgrade your PostgreSQL database to 18.0-1.

Since this is a major upgrade it will require that you upgrade your database.

Here is how to do it:

  1. Install the upgrade utilities:  sudo dnf5 install postgresql-upgrade 
  2. Become user postgres:  sudo su - postgres
    1. Rename the data directory:  mv /var/lib/pgsql/data/ /var/lib/pgsql/data_16/
  3. As user root, initialize your 18.0 database:  sudo postgresql-setup --initdb --unit postgresql 
  4. As user postgres, Copy your pg_hba.conf:  cp /var/lib/pgsql/data_16/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf
  5. To avoid any potential password issues, temporarily change "md5" to "trust" in both pg_hba.conf files
  6. Run the upgrade process:  pg_upgrade -b /usr/lib64/pgsql/postgresql-16/bin/ -B /usr/bin/ -d data_16/ -D data
  7. Change "trust" to md5" if you changed in step 6 
  8. Enable your postgresql.service:  sudo systemctl enable postgresql.service
  9. Start your postgresql.service:  sudo systemctl start postgresql.service
  10. Migration from 16 to 18 will cause a collation version mismatch, to fix sudo su - postgres and: 
    1. psql -U postgres -d postgres -c "REINDEX DATABASE CONCURRENTLY postgres;" 
    2. psql -U postgres -d postgres -c "ALTER DATABASE postgres REFRESH COLLATION VERSION;" 
  11.  Now fix for each of your databases:
    1.  psql -U postgres -d database_name -c "REINDEX DATABASE CONCURRENTLY database_name;" 
    2. psql -U postgres -d database_name -c "ALTER DATABASE database_name REFRESH COLLATION VERSION;" 
  12. Run as suggested: /usr/bin/vacuumdb --all --analyze-in-stages --missing-stats-only
  13. Run as suggested:  /usr/bin/vacuumdb --all --analyze-only
  14. Run as suggested: ./delete_old_cluster.sh script
Note:  When running commands as the postgres user, it is assumed you are running them from the postgres user $home directory.  This will be your location after you enter the command in step 2.  If you for some reason change to another directory from this userid, just remember to enter:  cd $home before entering any postgresql commands - otherwise you may not be able to execute the desired command, or may receive a permission error.  In steps 3, 8 and 9 you must issue the commands as root.  If you don't have sudoers setup for the postgres user, it will fail.  In this case just issue the "su" command to enter root without "sudo".  Remember to issue "exit" to return to the user "postgres".

Monday, December 16, 2024

Using Unifi WiFiman Desktop with Fedora Linux

Ubiquiti does not provide a WiFiMan Desktop installation method for RPM based distributions, such as Fedora Linux.

Since this is the case I've hacked together a makeshift process, using files generated by running the Ubiquity Debian WiFiman package through the pkg2appimage program. A simple script then is used to place the files in an appropriate location.  Nothing fancy, but it appears to work.

Hopefully, this will suffice until Ubiquiti decides to provide either an RPM, Flakpak or AppImage.

Here is how to install:

  1. Download the tarball: wifiman-desktop.tar.gz
  2. Extract the tarball into your home directory: tar -xvf wifiman-desktop.tar.gz
  3. Make your current directory wifiman-desktop: cd wifiman-desktop
  4. Install files: ./wifiman_integration.sh --install

  Here is how uninstall:

  1. Make your current directory wifiman-desktop: cd wifiman-desktop
  2. Uninstall files: ./wifiman_integration.sh --uninstall
 Here is how to use it:
  1. Start the wifiman-desktop.service: sudo systemctl start wifiman-desktop.service
  2. Launch the application: WiFiman Desktop
Note:  WiFiman Desktop requires the wifiman-desktop.service to be running.  After you are finished using the application you may wish to stop the wifiman-desktop.service, or you can leave it running.  If you wish wifiman-desktop.service to be automatically started, you must enable it via:  sudo systemctl enable wifiman-desktop.service

Thursday, April 11, 2024

PostgreSQL Upgrade - Fedora 40

Fedora 40 will upgrade your PostgreSQL database from 15.6-~ to 16.1-7.

Since this is a major upgrade it will require that you upgrade your database.

Here is how to do it:

  1. Install the upgrade utilities:  dnf install postgresql-upgrade
  2. Become user postgres:  sudo su - postgres
  3. Rename the data directory:  mv /var/lib/pgsql/data/ /var/lib/pgsql/data_15.6/
  4. As root, initialize your 16.1 database:  sudo postgresql-setup --initdb --unit postgresql
  5. As user postgres, Copy your pg_hba.conf:  cp /var/lib/pgsql/data_15.6/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf
  6. To avoid any potential password issues, temporarily change "md5" to "trust" in both pg_hba.conf files
  7. Run the upgrade process:  pg_upgrade -b /usr/lib64/pgsql/postgresql-15/bin/ -B /usr/bin/ -d data_15.6/ -D data
  8. Change "trust" to md5" if you changed in step 6 
  9. Enable your postgresql.service:  sudo systemctl enable postgresql.service
  10. Start your postgresql.service:  sudo systemctl start postgresql.service
  11. Run the analyse_new_cluster.sh script as suggested
  12. Run the delete_old_cluster.sh script as suggested
Note:  When running commands as the postgres user, it is assumed you are running them from the postgres user $home directory.  This will be your location after you enter the command in step 2.  If you for some reason change to another directory from this userid, just remember to enter:  cd $home before entering any postgresql commands - otherwise you may not be able to execute the desired command, or may receive a permission error.  In steps 4, 9 and 10 you must issue the commands as root.  If you don't have sudoers setup for the postgres user, it will fail.  In this case just issue the "su" command to enter root without "sudo".  Remember to issue "exit" to return to the user "postgres".

Friday, August 11, 2023

TransFLAC - Convert FLAC audio files to Lossy Formats

FLAC: The Lossless Audio Compression Format

FLAC, or Free Lossless Audio Codec, is a lossless audio compression format that preserves all the original audio data. This means that FLAC files can be decoded to an identical copy of the original audio file, without any loss in quality. However, lossless compression typically results in larger file sizes than lossy compression.

FLAC is a popular format for archiving digital audio files, as well as for storing music collections on home computers. It is also becoming increasingly common for music streaming services to offer FLAC as an option for high-quality audio.

For portable devices, where storage space is limited, lossy audio formats such as MP3, AAC, and OGG Vorbis are often used. These formats can achieve much smaller file sizes than lossless formats, while still providing good sound quality.

In general, FLAC is a good choice for applications where lossless audio quality is important, such as archiving, mastering, and critical listening. Lossy formats are a good choice for applications where file size is more important, such as storing music on portable devices or streaming music over the internet.

TransFLAC: Convert FLAC to Lossy Format

TransFLAC is a command-line application that converts FLAC audio files to a lossy format at a specified quality level. It can keep both the FLAC and lossy libraries synchronized, either partially or fully. TransFLAC also synchronizes album art stored in the directory structure, such as cover, albumart, and folder files. You can run TransFLAC interactively in a terminal window, or you can schedule it to run automatically using applications such as cron or systemd.

Four parameters are required to be specified:

  1. Input FLAC Directory: The directory to recursively search for FLAC audio files. The case of the directory name matters. TransFLAC will convert all FLAC audio files in the directory tree to the specified lossy codec format. The program will resolve any symlinks encountered and display the physical path.
  2. Output Lossy Directory: The directory to store the lossy audio files. The case of the directory name matters. The program will resolve any symlinks encountered and display the physical path.
  3. Lossy Codec: The codec used to convert the FLAC audio files. The case of the codec name does not matter. OPUS generally provides the best sound quality for a given file size or bitrate, and is the recommended codec.
    Valid values are: OPUS | OGG | AAC | MP3
  4. Codec Quality: The quality preset used to encode the lossy audio files. The case of the quality name does not matter. OPUS STANDARD quality provides full bandwidth, stereo music, good audio quality approaching transparency, and is the recommended setting.
    Valid values are: LOW | MEDIUM | STANDARD | HIGH | PREMIUM

TransFLAC allows for customization of certain items in the configuration.  The project wiki provides additional information.

Installation on Fedora: sudo dnf install transflac

 

[gbcox@charon ~]$ [gbcox@charon ~]$ t [gbcox@charon ~]$ tr [gbcox@charon ~]$ tra [gbcox@charon ~]$ tran [gbcox@charon ~]$ trans [gbcox@charon ~]$ transf [gbcox@charon ~]$ transfl [gbcox@charon ~]$ transfla [gbcox@charon ~]$ transflac [gbcox@charon ~]$ transflac _____ _____ _ _ ____ |_ _| __ __ _ _ __ ___| ___| | / \ / ___| | || '__/ _` | '_ \/ __| |_ | | / _ \| | | || | | (_| | | | \__ \ _| | |___ / ___ \ |___ |_||_| \__,_|_| |_|___/_| |_____/_/ \_\____| Please enter input FLAC directory and press[ENTER]: [ENTER]: m [ENTER]: mu [ENTER]: mus [ENTER]: musi [ENTER]: music [ENTER]: music _____ _____ _ _ ____ |_ _| __ __ _ _ __ ___| ___| | / \ / ___| INPUT Directory /home/gbcox/music accepted | || '__/ _` | '_ \/ __| |_ | | / _ \| | Please enter output directory and press[ENTER]: o [ENTER]: op [ENTER]: opu [ENTER]: opus [ENTER]: opusm [ENTER]: opusmu [ENTER]: opusmus [ENTER]: opusmusi [ENTER]: opusmusic [ENTER]: opusmusic OUTPUT Directory /home/gbcox/opusmusic acceptedPlease enter desired output CODECSupported: OPUS | OGG | AAC | MP3[ENTER]: [ENTER]: o [ENTER]: op [ENTER]: opu [ENTER]: opus [ENTER]: opus Transcoding: FLAC to OPUS Please enter desired CODEC QUALITYSupported: LOW | MEDIUM | STANDARD | HIGH | PREMIUM [ENTER]: [ENTER]: s [ENTER]: st [ENTER]: sta [ENTER]: stan [ENTER]: stand [ENTER]: standa [ENTER]: standar [ENTER]: standard [ENTER]: standard Quality Setting: STANDARD INPUT Directory /home/gbcox/music OUTPUT Directory /home/gbcox/opusmusic *** 18 FLAC files are being processed *** ../tina_turner/simply_the_best 17: 01_the_best 16: 02_better_be_good_to_me 15: 07_what_you_get_is_what_you_see 14: 09_river_deep_-_mountain_high 5: 03_i_can't_stand_the_rain 4: 04_what's_love_got_to_do_with_it 4: 04_what's_love_got_to_do_with_it 3: 05_i_don't_wanna_lose_you 2: 06_nutbush_city_limits_(the_90's_version) 1: 08_let's_stay_together 1: 08_let's_stay_together Completing remaining 4 processes...[--------------------------------------------------] 0%[#########################-------------------------] 50%[#####################################-------------] 75%[##################################################] 100%Syncing all album art files...Processing complete[gbcox@charon ~]$ e [gbcox@charon ~]$ ex [gbcox@charon ~]$ exi [gbcox@charon ~]$ exit [gbcox@charon ~]$ exitexit