Black screen after installing NVIDIA on Fedora Linux

I recently installed Fedora 44 on my desktop, next to Windows. Fresh install, KDE, encrypted disk, RTX 5080. Everything worked. Then I installed the NVIDIA driver, rebooted, and got a black screen.

Not a crash. Not an error message. Just black.

Short version

If you have an encrypted root and you get a black screen with no passphrase prompt after installing the NVIDIA driver, your initramfs has no GPU driver in it. Add the modules back with a file in /etc/dracut.conf.d and regenerate. It has to be regenerated again after every kernel update, because the automatic rebuild runs before the module for the new kernel exists, and a systemd drop-in will do that for you. Driver updates are the case the drop-in misses, and they leave your fallback kernels unbootable rather than your current one.

This is not an installation guide. RPM Fusion already has those, and they are the ones to follow:

What follows is just the story of what went wrong for me and what it turned out to be. The cause was two perfectly sensible decisions that only break when you put them together, and I could not find anyone describing that particular combination.

About this post

I am not a Linux expert. I have spent years on Windows and macOS and my Linux knowledge is well out of date. I debugged this with Claude Code, which went through the config files, package metadata and source RPMs with me, and which also helped me write this post. I am publishing it because the answer was genuinely hard to find, not because I am the right person to be explaining any of it.

The symptom

GRUB showed up fine. I picked Fedora, pressed enter, and then nothing. The monitor went to standby. The keyboard was lit up, so the machine was alive, but there was no output at all.

The detail I did not notice at first: the LUKS passphrase prompt never appeared. I was so focused on "the desktop is broken" that it did not register that I had never been asked to unlock the disk. That is the whole answer, and I walked past it about three times.

LUKS

The standard full disk encryption on Linux. If you ticked "encrypt my data" during the install, you have it. Every boot asks for a passphrase before anything on the disk can be read.

Nothing in the logs

My first instinct was to read the journal from the failed boot:

sudo journalctl -b -1

That gave me plenty of output, which sent me down the wrong path for a while. -b -1 means "the previous boot", and because the failed boots never recorded anything at all, it quietly handed me an older successful one instead.

The command that actually shows the problem is this one:

journalctl --list-boots

The failed boots are not in the list. As far as the journal is concerned they never happened.

That should have told me something straight away. Log entries are buffered in memory early on and only written to disk once the root filesystem is mounted. No journal at all means root was never mounted. So the boot was not failing late, at the graphical session. It was failing before the disk had even been unlocked.

Getting back in

To look at anything I needed a console. At the GRUB menu you can press e and edit the boot entry for one boot only, and adding 3 nomodeset to the end of the linux line was enough. The 3 skips the graphical login and drops you at a text prompt. nomodeset disables kernel mode setting completely, so no GPU driver tries to take over the screen and you get a plain text console.

Why there was no display at all

The driver install had added this to the kernel command line:

rd.driver.blacklist=nouveau,nova_core modprobe.blacklist=nouveau,nova_core

That is normal and expected. It blocks the open source NVIDIA drivers so the proprietary one can take over. The rd. prefix means the block applies inside the initramfs as well.

Nouveau

The open source driver for NVIDIA cards, written without NVIDIA's help and shipped in the kernel. It is what draws your desktop on a fresh Fedora install, before you install anything from NVIDIA. nova_core is its newer Rust based replacement, which is why both names show up in the blacklist.

initramfs

A small temporary filesystem the kernel loads into memory before your real disk is available. Its only job is to get far enough to mount the root filesystem and then hand over. On an encrypted system, that includes asking you for the passphrase.

The other half was in /usr/lib/dracut/dracut.conf.d/99-nvidia-dracut.conf:

omit_drivers+=" nvidia nvidia-drm nvidia-modeset nvidia-uvm "

RPM Fusion deliberately keeps the NVIDIA modules out of the initramfs, and the file says why: so you do not have to regenerate it every time the driver updates. That is a sensible trade on its own.

dracut

The tool that builds the initramfs. It reads config files from /usr/lib/dracut/dracut.conf.d and /etc/dracut.conf.d to decide what goes in.

Put those two together and the initramfs ends up with no GPU driver at all. Nouveau is blocked, and NVIDIA was never put in there.

On a normal install nobody ever notices, because the initramfs does not need to draw anything. It mounts root and hands over.

With an encrypted root it does need to draw something. It has to ask for the passphrase. So the machine was sitting there waiting for me to type a password into a prompt that was never rendered.

The fix

Putting the NVIDIA modules back into the initramfs. Files in /etc/dracut.conf.d shadow same-named files in /usr/lib/dracut/dracut.conf.d, so creating a file with the same name replaces RPM Fusion's config, including the omit_drivers line:

echo 'add_drivers+=" nvidia nvidia_modeset nvidia_drm nvidia_uvm "' \
  | sudo tee /etc/dracut.conf.d/99-nvidia-dracut.conf
sudo dracut --force

The initramfs went from 187 MB to 285 MB, which is the modules plus the GSP firmware that Blackwell cards need.

Then I rebooted, and at the GRUB menu I edited the entry one more time to take rhgb quiet off the linux line. Not because the fix needed it, but because I had already sat through five black screens and wanted to actually watch this one if it went wrong again.

rhgb and quiet

rhgb turns on the graphical boot splash, and quiet hides the kernel messages behind it. Remove both and you get scrolling text instead, which is far easier to debug. GRUB edits made this way only apply to that one boot, so nothing is saved to disk.

Boot messages scrolled past, and then there it was, the passphrase prompt, in plain text. I typed it in, the disk unlocked, and KDE came up.

That still left a loose end. I had changed two things, the initramfs and the boot options, so I did not actually know which one had fixed it. It was entirely possible that the real problem had been the splash screen failing to draw the prompt, and that the initramfs work had been beside the point.

So I rebooted one more time and left the entry alone, rhgb quiet and all.

It went straight through to the login screen. The initramfs was the whole story, and the graphical splash had nothing to do with it.

The fix does not survive a kernel update

Fedora pushed a kernel update, 7.1.5 to 7.1.6. These come along every week or two. Scrolling back through the dnf output afterwards, there was this:

dracut-install: Failed to find module 'nvidia'
dracut[E]: FAILED: /usr/lib/dracut/dracut-install ... -m nvidia nvidia_modeset nvidia_drm nvidia_uvm

Installing a kernel is not one action. It runs a directory of small numbered scripts, and two of them matter here:

/usr/lib/kernel/install.d/50-dracut.install            builds the new kernel's initramfs
/usr/lib/kernel/install.d/95-akmodsposttrans.install   builds the NVIDIA module for it

They run in numeric order, so dracut goes first. At that moment the NVIDIA module for the new kernel has not been compiled yet, so my add_drivers line has nothing to add. Then akmods builds it, and nothing comes back afterwards to regenerate the image.

akmods

Rebuilds out of tree kernel modules automatically whenever a new kernel is installed. It is the thing that stops the NVIDIA driver from breaking on every kernel update.

Kernel install hooks

Anything that needs to happen when a kernel is installed hooks in by dropping a numbered file into /usr/lib/kernel/install.d/. The numbers are the running order. Two packages can each be perfectly correct on their own and still end up in the wrong order relative to each other.

In my case the gap was twenty seconds. The initramfs was written at 22:37:05, and akmods reported Building and installing nvidia-kmod [ OK ] at 22:37:25.

So the new kernel had a perfectly valid initramfs with no GPU driver in it, sitting there waiting for me to reboot into the exact same black screen.

The file size gives it away instantly:

ls -l /boot/initramfs-*.img

On this machine 285 MB is a good one and 187 MB is a bad one. The difference is the modules and the GSP firmware, and it is big enough that you do not have to look any closer than that.

Getting through a kernel update

The whole trick is doing this before rebooting. Nothing is broken while you are still running the old kernel.

Install the update as normal. Then wait for akmods to finish compiling the module for the new kernel, which takes a couple of minutes:

systemctl status akmods@7.1.6-201.fc44.x86_64.service

Swap in your own version there. rpm -q --last kernel-core | head -1 will tell you which one just arrived.

Once that reports success, check the module exists and is the one you want:

modinfo -k 7.1.6-201.fc44.x86_64 -F license nvidia
modinfo -k 7.1.6-201.fc44.x86_64 -F signer nvidia

Dual MIT/GPL is the open module, which is what a 50 series card needs. If you have Secure Boot enabled, the second command should come back with your own MOK (Machine Owner Key), the signing key you enrolled so your firmware would accept a module built on your own machine; see Howto/Secure Boot. Without Secure Boot it returns nothing, which is fine. Then rebuild that kernel's initramfs and confirm it took:

sudo dracut --force --kver 7.1.6-201.fc44.x86_64
ls -l /boot/initramfs-7.1.6-201.fc44.x86_64.img

Back up around 285 MB and you are done.

Note the --kver. A plain sudo dracut --force rebuilds the image for the kernel you are running right now, which is the old one, and the old one was already fine.

If you forget and reboot into a black screen anyway, Fedora keeps the last three kernels and GRUB still renders, so you can pick the previous entry and carry on.

Getting the computer to do it

Doing that by hand after every kernel update was never going to last, so I went looking for somewhere to hook it.

The kernel install fires akmods@<version>.service, and systemd lets you extend a packaged unit without editing it by dropping a file into /etc/systemd/system/akmods@.service.d/:

[Service]
ExecStartPost=/usr/bin/dracut --force --kver %i

%i is the template instance, which the kernel hook sets to the version that just arrived. Nothing to parse, nothing to keep in sync. The unit is Type=oneshot, so ExecStartPost only runs once the module has finished building.

The next kernel update was the test. The transaction printed the same dracut[E]: FAILED as always, and then a minute later the image was sitting there at full size with the new modules inside it, without me touching anything.

It only covers kernel updates though, and that is where I had been too relaxed. Driver updates go through a different path with no systemd unit to attach to, and akmods builds the new module for only two kernels: the bootloader default and the one you are running. Your older kernels keep the module they were built with, while the userspace libraries on the root filesystem move on without them. Nothing regenerates their initramfs images either. So a fallback entry still boots and still draws the passphrase prompt, then hands over to a driver that no longer matches. Driver/library version mismatch, no desktop. The safety net rots quietly and you find out at the worst possible moment.

Two commands per kernel you want to keep bootable. Regenerating the image on its own is not enough, because it would just repackage the module that is already stale:

sudo akmods --kernels <the-older-kernel>
sudo dracut --force --kver <the-older-kernel>

Which is exactly the maintenance RPM Fusion was trying to spare everyone by leaving the modules out in the first place.

Was it worth it

At 3440x1440, nouveau offered exactly one refresh rate, 60 Hz. It is now running at 360 Hz.

So yes.