About me: My name is Solène Rapenne, pronouns she/her. I like learning and sharing knowledge. Hobbies: '(BSD OpenBSD Qubes OS Lisp cmdline gaming security QubesOS internet-stuff). I love percent and lambda characters. Qubes OS core team member, former OpenBSD developer solene@. No AI is involved in this blog.

Contact me: solene at dataswamp dot org or @solene@bsd.network (mastodon).

I'm a freelance OpenBSD, FreeBSD, Linux and Qubes OS consultant, this includes DevOps, DevSecOps, technical writing or documentation work. If you enjoy this blog, you can sponsor my open source work financially so I can write this blog and contribute to Free Software as my daily job.

Qubes OS backup transfer from old to new computer

Written by Solène, on 24 December 2023.
Tags: #security #qubesos #networking

Comments on Fediverse/Mastodon

1. 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.

2. 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

3. Preparing the backup receiver §

3.1. 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:

  • ss -lapteun | grep 2049
  • ss -lapteun | grep 111

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

3.2. 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 |  |
  +--------+             |  +---------+     +--------------+     +-----+  |
                         +------------------------------------------------+

3.2.1. 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.

3.2.2. 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.

4. 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...

4.1. Mounting qube §

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

dnf install nfs-utils

4.2. 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.

4.3. 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.

4.4. 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.

4.5. 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!

  • reboot qubes OS
  • don't log in, instead press ctrl+alt+F2 to run commands as the root user in a console (tty)
  • move the backup outside /home/solene with mv /home/solene/home-restore* /home/
  • delete your home directory /home/solene with rm -fr /home/solene
  • put the old backup at the right place with mv /home/home-restore*/dom0-home/solene /home/
  • press ctrl+alt+F1
  • log-in as user

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

5. Cleaning up §

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

6. 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.