Reprovisioning Guix on a new machine

2023/03/15

No matter how often you backup, if you never test your recovery procedures - you’d be surprised when it comes to it. So let’s make a recovery plan and give it a test.

Back up user files

Having ~/.config/borgmatic/config.yaml in place it’s just one command:

borgmatic create

Disaster happens

I see two options:

  1. I just need to move my digital stuff to a new machine.
  2. I’ve lost access to my current machine.

Let’s follow the first option for now and prepare everything to migrate smoothly.

Make a raw disk image

That’s as simple as running guix system image.

guix system image --volatile --image-type=efi-raw ~/.dotfiles/guix/system.scm
The following derivations will be built:
  /gnu/store/q0gvw0s79wkjlanfq4yjjyf2f9ddk4iq-disk-image.drv
  /gnu/store/dp0p01bzgb9aarzx040iv7k5w1r7z5xx-genimage.cfg.drv
  /gnu/store/kr39hrsyvwp17ny5hcrj6ynfn56i2cq8-partition.img.drv
  /gnu/store/758yrvd3m7016i5vflzjyg9232j75k2r-system.drv
  /gnu/store/58xsyrsaqaqh3dsxzb7zc0h72v7ha3as-etc.drv
  /gnu/store/5kifgf0yqnki7k9wg0a8jlviqibirmxy-activate.scm.drv
  /gnu/store/rqyl2kcj5q84daw4qriza38l0vkrax0m-activate-service.scm.drv
  /gnu/store/5lnmmgrgpy58nnkcpy8z22a0kf54yv0k-boot.drv
  /gnu/store/ri65rz6rgh5kv6ff8g2q313fr9fjd5ac-provenance.drv
  /gnu/store/z62g9qwy9k65awaaxg2f3jzdadsk5iha-grub.cfg.drv
  /gnu/store/x1zyd14c5xnpd51ql6bcfdv0q06nla8a-partition.img.drv

building /gnu/store/ri65rz6rgh5kv6ff8g2q313fr9fjd5ac-provenance.drv...
building /gnu/store/58xsyrsaqaqh3dsxzb7zc0h72v7ha3as-etc.drv...
building /gnu/store/rqyl2kcj5q84daw4qriza38l0vkrax0m-activate-service.scm.drv...
building /gnu/store/5kifgf0yqnki7k9wg0a8jlviqibirmxy-activate.scm.drv...
building /gnu/store/5lnmmgrgpy58nnkcpy8z22a0kf54yv0k-boot.drv...
building /gnu/store/758yrvd3m7016i5vflzjyg9232j75k2r-system.drv...
building /gnu/store/z62g9qwy9k65awaaxg2f3jzdadsk5iha-grub.cfg.drv...
building /gnu/store/kr39hrsyvwp17ny5hcrj6ynfn56i2cq8-partition.img.drv...
building /gnu/store/x1zyd14c5xnpd51ql6bcfdv0q06nla8a-partition.img.drv...
building /gnu/store/dp0p01bzgb9aarzx040iv7k5w1r7z5xx-genimage.cfg.drv...
building /gnu/store/q0gvw0s79wkjlanfq4yjjyf2f9ddk4iq-disk-image.drv...

And the disk image is: /gnu/store/rj2i98lw7vjj0k48dbwfs0q9aqnd9nxk-disk-image

Let’s check its partition table:

fdisk -l $disk_image
Disk /gnu/store/rj2i98lw7vjj0k48dbwfs0q9aqnd9nxk-disk-image: 2.32 GiB, 2488737792 bytes, 4860816 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 389B45C2-0EC7-42EC-9D96-49B40F820311

Device                                                  Start     End Sectors  Size Type
/gnu/store/rj2i98lw7vjj0k48dbwfs0q9aqnd9nxk-disk-image1  2048   83967   81920   40M EFI System
/gnu/store/rj2i98lw7vjj0k48dbwfs0q9aqnd9nxk-disk-image2 83968 4860775 4776808  2.3G Linux filesystem

And filesystems labels are:

alias kpartx=$(guix build multipath-tools)/sbin/kpartx
kpartx -av $disk_image >/dev/null
lsblk -o NAME,FSTYPE,FSVER,LABEL,UUID /dev/loop0
kpartx -d $disk_image
NAME      FSTYPE FSVER LABEL      UUID
loop0
|-loop0p1 vfat   FAT16 GNU-ESP    572A-DDF3
`-loop0p2 ext4   1.0   Guix_image f6bc8ad8-ff1a-1754-eb2b-35d0f6bc8ad8

Note that the partition labels chosen by guix system image are not taken from the operating-system definition. They’re hardcoded in the guix sources and therefore I have to hardcode the same values in my operating-system. Without matching labels the system would just refuse to boot as they’re used in the EFI loader to find the boot partition and also in the fstab.

LABEL=Guix_image  /      ext4  defaults
LABEL=GNU-ESP     /boot  vfat  defaults

Putting disk image on a real machine

I have a Ventoy USB stick with Lubuntu Live CD on it. Let’s just copy the resulting image to the stick. Note, you might need to follow this recipe: Access USB stick on live ISO as by default the USB drive will not be accessible.

eval $(lsblk -P -o LABEL,MOUNTPOINT | grep Ventoy)
cp $disk_image $MOUNTPOINT/guixdisk.img
eject $MOUNTPOINT

And then reboot to the Live CD environment and run the following provisioning script.

dd /media/lubuntu/Ventoy/guixdisk.img of=/dev/sda status=progress

parted /dev/sda print
# Warning: Not all of the space available to /dev/sda appears to be used, you
# can fix the GPT to use all of the space (an extra 346740088 blocks) or
# continue with the current setting?
# Fix/Ignore? fix

parted -s /dev/sda resizepart 2 100%
fsck -y -f /dev/sda2
resize2fs /dev/sda2
reboot

Restoring backup

Log in as root (password is empty)

borgmatic and borg are baked in the disk image, use it to restore /storage

mkdir -m 0700 /storage && chown sarg:users /storage
mount /dev/sdb1 /mnt

cd /
latest=$(borg list --last 1 --short /mnt)
# borg manual recommends using the same user which made the backup
su sarg -c "borg extract /mnt::$latest"
exit

Revitalising Guix

guix-home profile is already in the image and it’s activated using a one-off shepherd service. It takes some time, so don’t rush to log in under your user. Check herd status guix-home-sarg first and /var/log/messages.

echo "Wait guix-home-sarg to complete"
until herd status guix-home-sarg | grep 'It is stopped'; do echo -n .; sleep 1; done

passwd root
passwd sarg
login sarg

cd /storage/devel/dotfiles/guix
guix pull -C /run/current-system/channels.scm
sudo guix system reconfigure system.scm
guix home reconfigure home.scm

# app-specific restore commands
doom sync
mu init -m ~/.mail
mu index

logout # sarg
logout # root