A simple, repeatable workflow for one VM image (Kali.qcow2), root-owned files, and an SMB share.

Overview

I run a Kali Linux virtual machine under QEMU/KVM and wanted to use the same VM across three different machines, while keeping a central backup on my NAS. The approach below keeps one master copy on the NAS and uses rsync to push updates from whichever host I used last and pull them on the next host.

Step 1 — The Starting Point

On my main machine, virt-manager created the Kali VM image at:

~/Documents/VMs/Kali.qcow2

This qcow2 file is the only thing I sync.

Step 2 — Create a Location on the NAS

Create a folder on the NAS to store the master copy:

/mnt/nas/vms/Kali/

Step 3 — Mount the SMB Share on Each Host

  1. Install SMB client tools:
sudo apt install cifs-utils
  1. Create a mount point:
sudo mkdir -p /mnt/nas/vms
  1. Mount the share (adjust server/share, user, and options to your environment):
sudo mount -t cifs //nas/vms /mnt/nas/vms \
 -o username=nasuser,password=secret,vers=3.0,uid=root,gid=root

Add an /etc/fstab entry for auto-mount at boot:

//nas/vms /mnt/nas/vms cifs username=nasuser,password=secret,vers=3.0,uid=root,gid=root 0 0

Tip: For better security, store credentials in /etc/samba/credentials and reference with credentials=/etc/samba/credentials instead of inline username=/password=.

Step 4 — Push the VM to the NAS (Create/Update the Master Copy)

Shut down the VM, then from the host you just used:

sudo rsync -a --sparse --info=progress2 \
 ~/Documents/VMs/Kali.qcow2 \
 /mnt/nas/vms/Kali/Kali.qcow2

This preserves ownership/permissions, handles sparse qcow2 efficiently, and only transfers changed blocks after the first run.

Step 5 — Pull the VM to Another Machine

On a different host, before starting work, pull the latest image down:

sudo rsync -a --sparse --info=progress2 \
 /mnt/nas/vms/Kali/Kali.qcow2 \
 ~/Documents/VMs/Kali.qcow2

Then start the VM:

virsh start Kali

…or open it in virt-manager.

Daily Workflow Summary

  • After using the VM: shut it down → push to NAS.
  • Before using it on another host: pull from NAS → start VM.

Core commands:

# Push (backup/update)
sudo rsync -a --sparse ~/Documents/VMs/Kali.qcow2 /mnt/nas/vms/Kali/Kali.qcow2

# Pull (restore/update)
sudo rsync -a --sparse /mnt/nas/vms/Kali/Kali.qcow2 ~/Documents/VMs/Kali.qcow2

Best Practices

  • Always shut down the VM before syncing to avoid image corruption.
  • Keep the mount point consistent across all machines (e.g., /mnt/nas/vms) to reuse the same commands.
  • Occasionally make versioned backups for restore points: sudo rsync -a --sparse \ ~/Documents/VMs/Kali.qcow2 \ /mnt/nas/vms/Kali/Kali-$(date +%Y%m%d).qcow2
  • Do not run the same VM simultaneously on two hosts—this workflow is for sync, not shared live access.
  • (Optional) If your VM uses UEFI and a persistent NVRAM file, sync that too (path varies by distro).

Wrap-up: With a single master copy on the NAS and two rsync commands (push & pull), I can move my Kali VM between machines in seconds without changing ownership from root:root.

Keeping the libvirt XML in Sync (Portable XML)

In addition to syncing the Kali.qcow2 image, keep the VM’s libvirt definition (the domain XML used by Virtual Machine Manager / virt-manager) portable and synced via your NAS. This approach is simple and manual, fits the rsync workflow, and avoids per-host drift.

1) Export once on the source host

Dump the inactive domain XML to your home folder:

virsh dumpxml --inactive Kali > ~/Documents/VMs/Kali.xml

2) Store it on the NAS next to the image

Push the XML to your mounted SMB share (mounted at /mnt/nas/vms):

sudo rsync -a ~/Documents/VMs/Kali.xml /mnt/nas/vms/Kali/Kali.xml

3) (Re)define from the NAS on other hosts

On any other machine, pull the image as usual, then (re)define the VM from the NAS copy:

sudo virsh define /mnt/nas/vms/Kali/Kali.xml
virsh autostart Kali # optional, one-time

4) When you change VM settings

If you edit CPU/RAM/devices in virt-manager on any host:

# Re-export XML on the host where you made changes
virsh dumpxml --inactive Kali > ~/Documents/VMs/Kali.xml

# Update the NAS copy
sudo rsync -a ~/Documents/VMs/Kali.xml /mnt/nas/vms/Kali/Kali.xml

# On the other hosts, re-define from NAS
sudo virsh define /mnt/nas/vms/Kali/Kali.xml

Portable XML checklist

  • Disk path: use the same local path on all hosts, e.g. <source file='~/Documents/VMs/Kali.qcow2'/>. Keep that path consistent across machines so you don’t have to edit XML per host.
  • Network: prefer a portable choice such as the default NAT network: <interface type='network'> <source network='default'/> </interface> or ensure the same bridge name exists on each host.
  • MAC address: to avoid conflicts if two hosts might be online with the VM config, remove the fixed MAC from the XML (libvirt will generate one on define), or maintain distinct MACs per host.
  • UEFI firmware: if your XML includes OVMF, ensure each host has a valid <loader ...>OVMF_CODE.fd</loader> path. For the NVRAM line:
    • Either copy the VARS file to the same path on all hosts and keep the <nvram> line,
    • or remove the <nvram> line and let libvirt create a fresh VARS file on each host.
  • Host-specific devices: avoid pinning GPU PCI addresses or USB passthrough in the shared XML unless all hosts match. Keep those in per-host overrides if needed.

Commands recap (image + XML)

Push updated image and XML from a host you just used:

sudo rsync -a --sparse ~/Documents/VMs/Kali.qcow2 /mnt/nas/vms/Kali/Kali.qcow2
sudo rsync -a ~/Documents/VMs/Kali.xml /mnt/nas/vms/Kali/Kali.xml

Pull image and (re)define on another host:

sudo rsync -a --sparse /mnt/nas/vms/Kali/Kali.qcow2 ~/Documents/VMs/Kali.qcow2
sudo virsh define /mnt/nas/vms/Kali/Kali.xml
virsh start Kali

NOTE: if default network not starting, try

sudo virsh net-start default 
# or for autostart
sudo virsh net-autostart default

Blogpost written with AI