Skip to content

Instantly share code, notes, and snippets.

@andyjessop
Last active March 6, 2026 10:20
Show Gist options
  • Select an option

  • Save andyjessop/87510d7a79c2663c9626869c86ef14f4 to your computer and use it in GitHub Desktop.

Select an option

Save andyjessop/87510d7a79c2663c9626869c86ef14f4 to your computer and use it in GitHub Desktop.
Headless Ubuntu Server NVMe Boot Setup on Pi 5

Raspberry Pi 5: Headless Ubuntu Server NVMe Boot Setup

This guide outlines the process for configuring a Raspberry Pi 5 to boot Ubuntu Server 24.04 from an NVMe SSD using a Geekworm (or similar) PCIe shield, entirely via SSH (no monitor required).

1. Hardware Assembly

  • Connect the NVMe Shield to the Raspberry Pi 5 PCIe FFC port.
  • Ensure the ribbon cable is seated firmly (blue tab facing the specified direction).
  • Install the M.2 NVMe SSD into the shield.

2. Phase 1: The "Unlocker" SD Card

Since the Pi 5 PCIe port is disabled by default, we use a temporary microSD card to enable the hardware.

  1. Flash Raspberry Pi OS Lite (64-bit) to a microSD card using Raspberry Pi Imager.
  2. Use OS Customization to:
  • Enable SSH.
  • Set a username/password (e.g., pi/raspberry).
  • Configure Wi-Fi (if not using Ethernet).
  1. Insert the SD card, power on the Pi, and find its IP address.

3. Phase 2: Firmware & Hardware Configuration

SSH into the Pi (ssh pi@<IP_ADDRESS>) and run the following:

Update Bootloader (EEPROM)

sudo rpi-eeprom-update -a
sudo rpi-eeprom-config --edit

Ensure these lines exist in the config:

  • BOOT_ORDER=0xf416 (Prioritizes NVMe boot)
  • PCIE_PROBE=1 (Probes the PCIe bus)

Enable PCIe Port

sudo nano /boot/firmware/config.txt

Add to the bottom:

dtparam=pciex1
dtparam=pciex1_gen=3  # Optional: For Gen 3 speeds

Reboot: sudo reboot. Verify the drive appears with lsblk.

4. Phase 3: Headless Ubuntu Installation

From the SD card SSH session, download and flash Ubuntu Server directly to the SSD.

Download Image

wget https://cdimage.ubuntu.com/releases/noble/release/ubuntu-24.04.4-preinstalled-server-arm64+raspi.img.xz

Flash to NVMe (CLI Method)

Since the GUI imager fails on headless servers due to missing libEGL libraries, use dd:

xzcat ubuntu-24.04.4-preinstalled-server-arm64+raspi.img.xz | sudo dd of=/dev/nvme0n1 bs=4M status=progress conv=fsync

5. Phase 4: Injecting Headless Config (Cloud-Init)

Before rebooting, you must "prime" the Ubuntu installation so it allows SSH access and recognizes the PCIe port.

  1. Mount the SSD Boot Partition:
sudo mkdir -p /mnt/nvme_boot
sudo mount /dev/nvme0n1p1 /mnt/nvme_boot
  1. Copy User/Network Credentials: Copy the working cloud-init files from your current SD card to the SSD:
sudo cp /boot/firmware/user-data /mnt/nvme_boot/
sudo cp /boot/firmware/network-config /mnt/nvme_boot/
sudo touch /mnt/nvme_boot/ssh
  1. Enable PCIe in Ubuntu's Config:
sudo nano /mnt/nvme_boot/config.txt

Add dtparam=pciex1 and dtparam=pciex1_gen=3 to the bottom. 4. Unmount and Power Off:

sudo umount /mnt/nvme_boot
sudo poweroff

6. Phase 5: Final Boot & Verification

  1. Remove the microSD card.
  2. Power on the Pi. Wait ~5 minutes for the first-boot initialization.
  3. SSH in: ssh <user>@<IP_ADDRESS>.
  4. Verify Boot Source: lsblk (Root / should be on nvme0n1p2).
  5. Check SSD Health:
sudo apt install smartmontools -y
sudo smartctl -a /dev/nvme0n1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment