Qubes OS backup transfer from old to new computer

Comment on Mastodon

Introduction

With the recent release of Qubes OS 4.2, I took the opportunity to migrate to a newer laptop (from a Thinkpad T470 to a NovaCustom NV41) so I had to backup all the qubes from the T470 and restore them on the NV41.

The fastest way to proceed is to create the backups on the new laptop directly from the old one, which is quite complicated to achieve due to Qubes OS compartmentalization.

In this guide, I'll share how I created a qube with a network file server to allow one laptop to send the backups to the new laptop.

Qubes OS official project website

Of course, this whole process could be avoided by using a NAS or external storage, but they are in my opinion slower than directly transferring the files on the new machine, and you may not want to leave any trace of your backups.

Explanation about the setup

As the new laptop has a very fast NVME disk, I thought it would be nice to use it for saving the backups as it will offload a bit of disk activity for the one doing backups, and it shouldn't be slowed down during the restore process even if it has to write and read the backups at the same time.

The setup consists in creating a dedicated qube on the new laptop offering an NFS v4 share, make the routing at the different levels, and mount this disk in a qube on the old laptop, so the backup could be saved there.

I used a direct Ethernet connection between the two computers as it allows to not think much about NFS security

Preparing the backup receiver

Storage qube configuration

On the new laptop, create a standalone qube with the name of your choice (I'll refer to it as `nfs`), the following commands have been tested with the fedora-38-xfce template. Make sure to give it enough storage space for the backup.

First we need to configure the NFS server, we need to install the related package first:

$ sudo dnf install nfs-utils

After this, edit the file `/etc/exports` to export the path `/home/user/backup` to other computers, using the following content:

/home/user/backup *(rw,sync)

Create the directory we want to export, and make `user` the owner of it:

install -d -o user /home/user/backup

Now, run the NFS server now and at boot time:

systemctl enable --now nfs-server

You can verify the service started successfully by using the command `systemctl status nfs-server`

You can check the different components of the NFS server are running correctly, if the two following commands have an output this mean it's working:

Allow the NFS server at the firewall level, run the following commands AND add them at the end of `/rw/config/rc.local`:

nft add rule qubes custom-input tcp dport 2049 accept
nft add rule qubes custom-input udp dport 111 accept

Route the service from the physical LAN

Now the service is running within the qube, we need to allow the remote computer to reach it, by default the network should look like this:

We will make sys-net to nat the UDP port 111 and TCP port 2049 to sys-firewall, which will nat them to the nfs qube, which will already accept connections on those ports.

                         +------------------------------------------------+
  +--------+             |               DESTINATION SYSTEM               |
  | SOURCE |  ethernet   |  +---------+     +--------------+     +-----+  |
  | SYSTEM | <-------->  |  | sys-net | --> | sys-firewall | --> | nfs |  |
  +--------+             |  +---------+     +--------------+     +-----+  |
                         +------------------------------------------------+

sys-net routing

Write the following script inside the `sys-net` qube of the destination system, make sure to update the value of the variable `DESTINATION` with `sys-firewall`'s IP address, it can be found by looking at the qube settings.

#!/bin/sh

PORT=111
DESTINATION=10.138.31.246

if ! nft -nn list table ip qubes | grep "chain nat {" ; then
	nft add chain qubes nat { type nat hook prerouting priority dstnat\; }
fi

nft add rule qubes custom-input udp dport "${PORT}" accept
nft add rule qubes custom-forward udp dport "${PORT}" accept
nft add rule qubes nat iifname != "vif*" udp dport "${PORT}" dnat "${DESTINATION}"

PORT=2049
nft add rule qubes custom-input tcp dport "${PORT}" accept
nft add rule qubes custom-forward tcp dport "${PORT}" accept
nft add rule qubes nat iifname != "vif*" tcp dport "${PORT}" dnat "${DESTINATION}"

Make the script executable by running the command `chmod +x` on the script file. You will execute them later once the network is safe.

sys-firewall routing

Write the following script inside the `sys-firewall` qube of the destination system, make sure to update the value of the variable `DESTINATION` with `nfs`'s IP address, it can be found by looking at the qube settings.

#!/bin/sh

PORT=111
DESTINATION=10.137.0.10

if ! nft -nn list table ip qubes | grep "chain nat {" ; then
	nft add chain qubes nat { type nat hook prerouting priority dstnat\; }
fi

nft add rule qubes custom-input udp dport "${PORT}" accept
nft add rule qubes custom-forward udp dport "${PORT}" accept
nft add rule qubes nat iifname != "vif*" udp dport "${PORT}" dnat "${DESTINATION}"

PORT=2049
nft add rule qubes custom-input tcp dport "${PORT}" accept
nft add rule qubes custom-forward tcp dport "${PORT}" accept
nft add rule qubes nat iifname != "vif*" tcp dport "${PORT}" dnat "${DESTINATION}"

Make the script executable by running the command `chmod +x` on the script file. You will execute them later once the network is safe.

Backup process

On the source system, we need to have a running qube that will mount the remote NFS server, this can be a disposable qube, an AppVM qube with temporary changes, a standalone etc...

Mounting qube

On the mounting qube, run the following command to install the NFS tools we need:

dnf install nfs-utils

Configure both systems network

In this step, you need to configure the network with the direct Ethernet cable, so the two systems can speak to each other, please disconnect from any Wi-Fi connections as you didn't set any security for the file transfer (it's encrypted but still).

You can choose any address as long as the two hosts are in the same subnet, an easy pick could be `192.168.0.2` for the source system, and `192.168.0.3` for the new system.

Now, both systems should be able to ping each other, it's time to execute the scripts in `sys-firewall` and `sys-net` to enable the routing.

On the "mounting" qube, run the following command as root to mount the remote file system:

mount.nvfs4 192.168.0.3:/home/user/backup /mnt

You can verify it worked if the output of `df` shows a line starting by `192.168.0.3:/home/user/backup`, and you can ensure your user can actually write in this remote directory by running `touch /mnt/test` with the regular user `user`.

Now, we can start the backup tool to send the backup to the remote storage.

Run the backup

In the source system dom0, run the Qubes OS backup tool, choose the qubes you want to transfer, uncheck "Compress backups" (except if you are tight on storage for the new system) and click on "Next".

In the field "Target qube", select the "mounting qube" and set the path to `/mnt/`, choose an encryption passphrase and run the backup.

If everything goes well, you should see a new file named `qubes-backup-YYYY-MM-DDThhmmss` in the directory `/home/user/backups/` of the `nfs` qube.

Restore the backups

In the destination system dom0, you can run the Restore backup tool to restore all the qubes, if the old `sys-net` and `sys-firewall` have any value, you may want to delete yours first otherwise the restored one will be renamed.

how to restore dom0 $home

When you backup and restore dom0, only the directory `/home/` is part of the backup, so it's only about the desktop settings themselves and not the Qubes OS system configuration. I actually use versioned files in the salt directories to have reproducible Qubes OS machines because the backups aren't enough.

Blog post: Using git bundle to synchronize a repository between Qubes OS dom0 and an AppVM

Blog post: Qubes OS dom0 files workflow using fossil

When you restore dom0, it creates a directory `/home/solene/home-restore-YYYY-MM-DDThhmmss` on the new dom0 that contains the previous `/home/` directory.

Restoring this directory verbatim requires some clever trick as you should not be logged in for the operation!

Your desktop environment should be like you left if during the backup. If you used some specific packages or desktop environment, make sure you also installed the according packages in the new dom0

Cleaning up

After you restored your backups, you can remove the scripts in `sys-firewall` and `sys-net` and even delete the nfs qube.

Conclusion

Moving my backup from the old system to the new one was pretty straightforward once the NFS server was established, I was able to quickly have a new working computer that looked identical to the previous one, ready to be used.