Migrating Single Disk to Raid Mirror on ubuntu 20.04

Summary.

This procedure is based on my own personal desktop installation of ubuntu 20.04.2. I had a single disk installation containing the following partitions: EFI, root (including boot) on an nvme drive. My goal was to obtain a second nvme of the same make and model, and, migrate to a mdadm Raid installation without backup and restore. In searching, I found many tutorials were quite old, nothing recent and some things have changed since those older tutorials were written. If you have a different partition layout, you’ll have to adjust accordingly. Despite what my goal was, I still did take the backup in advance and you should too! If you understand the steps, the risk should be close to non existant.

Some Definitions

My original drive was /dev/nvme0n1, partition 1 was EFI and partition 2 was root/boot of type ext4. The new drive was /dev/nvme1n1. I had an efi installation and GPT. I am using the bash shell. All commands are done as root, so, before starting:

$ sudo -s

Software you may need to install

You may or may not have all of the packages needed to follow the instructions. So:

$ apt install mdadm

Partition the new drive

You should check your existing partitions to see if they match what I started with via:

$ sgdisk -p /dev/nvme0n1

Remember to replace your device names where mine are shown. Also potentially partition numbers. We’re going to copy the partitions and layout of the old drive to the new drive:

$ sgdisk -R /dev/nvme1n1 /dev/nvme0n1
$ sgdisk -G /dev/nvme1n1
$ sgdisk -t 2:0xFD00 /dev/nvme1n1
$ partprobe

The first command copies the partition table from the old device to the new device. Note the paramaters look backwards, but they are not, that’s how sgdisk works.

The second command generates a new UUID for the new drive and it’s partitions since we don’t want or need duplicate UUIDs.

The third command changes the parition type for the root/boot partition, which for me was partition 2 as numbered by sgdisk. 0xFD00 is for mdadm Raid on GPT.

The last command tells ubuntu about the new partitions.

Create a Raid array

We’ll be creating a mdadm mirror array for us to use. For now, we’ll just have the new drive in that array, we’ll add the existing drive to it later once we can boot onto the Raid array. Execute:

$ mdadm --create /dev/md0 --level=mirror --raid-devices=2 missing /dev/nvme1n1p2
$ mdadm --examine --scan >/etc/mdadm/mdadm.conf

The first command generates a new mdadm mirrored array with a device name of /dev/md0, with 2 devices. One of the devices is the new drive partition for root and boot (mine was parition 2), and the other device is missing for now. Answer y to the warning prompt.

The second command saves our Raid configuration.

Create ext4 Filesystem

Our raid device /dev/md0 is just a container, it must be initialized for use as a filesystem, we’re using ext4:

$ mkfs.ext4 /dev/md0
$ mkdir /mnt/root
$ mount /dev/md0 /mnt/root

The first command formats the Raid container with an ext4 filesystem.

The second command creates a mount point to use with the new filesystem

The third command mounts the new filesystem so we can use it

Copy Our Files Over

We’ll want to copy all files from our existing drive to the new Raid drive:

$ rsync -aAHXx / /mnt/root
$ rsync -aAHX /boot/efi/ /mnt/root/boot/efi

The first command copies all files from our root partition, not descending into any other mounted filesystems.

The second command does the same for our EFI partition.

Chroot into our new filesystem

We’ll be making use of chroot to make things a little simpler and easier. This will pretend we are already booted on the new system.

$ mount --bind /dev /mnt/root/dev
$ mount --bind /sys /mnt/root/sys
$ mount -t proc /proc /mnt/root/proc
$ chroot /mnt/root

The first 3 commands set up our chroot environment by making sure we can still access key directories from our existing drive and booted environment in our chroot environment.

The last command does the actuall chroot, so, now it is as if were were booted on the Raid drive.

Modify fstab

We need to modify /etc/fstab on our new raid drive since it currently points to the old drive, meaning we won’t boot under Raid:

$ blkid /dev/md0
$ blkid /dev/nvme1n1p1
$ vi /etc/fstab

We’ll be needing the uuid of our md0 device (first command) and the EFi partition (second command) to use in modifying /etc/fstab. My EFI partition was number 1.

Using your favorite editor (vi shown here), edit /etc/fstab and replace the UUID for / (from the first command) and /boot/efi (from the second command) with the new UUIds discovered in the first 2 commands. For me, my modified fstab entries now look like:

UUID=ae87a6c4-cb56-432f-b1dd-8c4aec0ffb87 /               ext4    errors=remount-ro 0       1
UUID=4599-5926  /boot/efi       vfat    umask=0077,nofail      0       1

Setup Our New Boot Environment

Now it’s time to recreate grub and initramfs:

$ uname -r and capture current kernel version.
$ update-initramfs -k 5.8.0-44-generic -c
$ update-grub
$ mount /boot/efi
$ grub-install /dev/nvme1n

The first command is needed to get our current kernel version. For me, this was 5.8.0-44-generic

The second command generates our new initramfs image so we can boot with our new environment using Raid. Replacfe the kernel version with the one found from command 1.

The third command updates grub

The fourth and fifth commands add grub to our new drive

Test Raid Boot Environment

Now it’s time to test our new Raid setup and see if we can boot. Using the GUI or command line, reboot your machine. We’ll want to pick a new boot drive when booting, this differs depending on your motherboard. For mine, I simply entered BIOS setup and there was an option there to temporarily change the boot device. This may differ for you, but, you want to pick the EFI partition on the new drive, not the old one. When you get to the grub menu, you can check this. Just hit ‘e’ and make sure there is a line that says:

insmod mdraid1x

If there is that line, you have likely picked the correct drive and partition. If not, try rebooting and picking a different choice.

Check Boot Results

Check if you have booted on the correct drive:

$ df

You should see /dev/md0 mounted at /, and, /dev/nvme1n1p1 mounted at /boot/efi. Here’s what mine looks like:

/dev/md0                  124369340   32305552    85703060  28% /
/dev/nvme1n1p1               497696       7988      489708   2% /boot/efi

Congratulations, you are now booted into (degraded) Raid!

Prepare Old Drive

Now that we are using a degraded Raid, let’s prepare the old drive so we can add it to the mirror set:

$ sgdisk -R /dev/nvme0n1 /dev/nvme1n1
$ sgdisk -G /dev/nvme0n1

The first command copies the parition table from our booted to Raid drive.

The second command generated a new UUID for the drive and each partition.

Add Old Drive to Raid

We are ready to get our mirror running:

$ mdadm --manage /dev/md0 --add /dev/nvme0n1p2
$ mdadm --detail /dev/md0 to check status, should be rebuilding

The first command adds our old drive to the Raid set so we can have a full mirror.

The second command checks the status of the now complete mirror Array, it should say rebuilding.

Configure Second EFI Partition

We need to make sure both EFI partitions get mounted so both can be updated if an update is made by ubuntu:

$ blkid /dev/nvme0n1p1
$ vi /etc/fstab
$ mount /dev/eficopy
$ dpkg-reconfigure grub-efi-amd64-signed

Use vi or your favorite editor to edit /etc/fstab. Duplicate the line for /boot/efi and change /boot/efi to /boot/eficopy, and, change the UUID to match the UUID obtained by the blkid command. I also added ,nofail to each efi partition, making mine look like this:

UUID=4599-5926  /boot/efi       vfat    umask=0077,nofail      0       1
UUID=40D0-E7C3  /boot/eficopy       vfat    umask=0077,nofail      0       1

As long as both drives are in your boot sequence as defined by your boot order in the motherboard config, it should boot from either drive if one fails.

The last command tells ubuntu to maintain the efi partition. When you run it, select both drives you used for Raid.

Finalize

Just one more step:

$ mdadm --examine --scan >/etc/mdadm/mdadm.conf

Update our Raid config file now that both drives are in the array. If you got this far, it worked and you should eventually see the drives synced when you check via cat /proc/mdstat.

If you got it to work or have any corrections, please leave a comment. I enjoy hearing.