Backup script for KVM virtual machines

KVM is a great virtualization engine, open source and light way. I’m running my Home Assistant VM inside an Intel NUC without any issues and super stable.

But what KVM lacks is a proper out of the box GUI or management interface that makes your life a bit easier in terms of VMs administration (there are open source options, I’m using Cockpit for basic management).

Having said that, this is the general purpose backup script I gathered to weekly backup my Home Assistant instance:



if [ -z "$BACKUPDEST" -o -z "$DOMAIN" ]; then
    echo "Usage: ./vm-backup-simple <backup-folder> <domain> [max-backups]"
    exit 1

echo "Beginning backup for $DOMAIN"

# Generate the backup path
BACKUPDATE=`date "+%Y-%m-%d.%H%M%S"`
mkdir -p "$BACKUP"

# Get the list of targets (disks) and the image paths.
TARGETS=`virsh -c qemu:///system domblklist "$DOMAIN" --details | grep file | awk '{print $3}'`
IMAGES=`virsh -c qemu:///system domblklist "$DOMAIN" --details | grep file | awk '{print $4}'`

# Shutdown VM.

echo "Shuting down $DOMAIN"
virsh -c qemu:///system shutdown "$DOMAIN"
sleep 30

# Copy disk images
echo "Copying disk images"
for t in $IMAGES; do
    NAME=`basename "$t"`
    cp "$t" "$BACKUP"/"$NAME"

# Dump the configuration information.
echo "Dump config information"
virsh -c qemu:///system dumpxml "$DOMAIN" >"$BACKUP/$DOMAIN.xml"

# Cleanup older backups.
echo "Deleting old backups"
LIST=`find "$BACKUPDOMAIN" -type d -mtime +7`
for b in $LIST; do
    echo "Removing old backup "`basename $b`
    rm -rf "$b"

echo "Starting up $DOMAIN"
virsh -c qemu:///system start "$DOMAIN"
sleep 90

echo "Finished backup"
echo ""

First we have 3 parameters:

  • BACKUPDEST: the full path to where backups will be stored.
  • DOMAIN: the KVM domain of the VM to backup.

The script first creates a destination directory in the backups path provided to store the files.

Then queries virsh for the list of disks that the VM has. The backup procedure is as simple as copying the disk images and some metadata.

With the disk information, the VM is shutdown. There is a way to take live snapshots that I’m not covering in this scenario, as it’s cleaner and safer for me to do a full backup with the VM down.

All disk images are copied to the previously created directory. Then the VM metadata is also dumped into the backup directory.

Finally, all backups longer than 7 days are just deleted, and the VM restarted.

When running this script in cron, just make sure to indicate all the full paths, so there is no path related issues.

As I’m specifically backing up Home Assistant, right after the backup is complete I run a second script to upgrade HA and make sure I’m using the latest version. It’s safe to do it this way as if anything breaks, I already have a backup:


ssh [email protected] ha core update

Finally, as all my backups reside on the same disk where HA is running, I do an rsync to an external hard drive for more reliability:


rsync -avzh --delete /home/user/backupdir/domain/ [email protected]:/path/media/backup/vmbackups

I usually keep the last 2 copies of backups (no longer than 7 days old), should be enough for any undetected situation that needs a rollback.

Let me know if these scripts are useful for you, and any improvements you may find. Cheers!

Related Posts

NFS share with external SSD Raid 1 disks

When planning to provide my Kubernetes cluster with a dynamic storage provisioning option, I decided to use NFS to be able to attach volumes to multiple nodes…

Expose Home Assistant on CG-NAT networks

There is no doubt that Home Assistant is a great home automation software that lets automate a wide range of home appliances. Open source and in constant…

5 1 vote
Article Rating
Notify of

Inline Feedbacks
View all comments