{"id":18000907,"url":"https://github.com/abbbi/qmpbackup","last_synced_at":"2026-02-12T14:17:33.978Z","repository":{"id":46035636,"uuid":"75234665","full_name":"abbbi/qmpbackup","owner":"abbbi","description":"Qemu Backup tool: Create full and incremental backups of running qemu machines by using dirty-bitmaps","archived":false,"fork":false,"pushed_at":"2026-02-03T14:34:04.000Z","size":832,"stargazers_count":84,"open_issues_count":4,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-04T04:27:26.964Z","etag":null,"topics":["backup","incremental","kvm","kvm-hypervisor","linux-server","proxmox","proxmox-backup","python3","qemu","qemu-kvm","restore","virtual-machine","virtualization"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abbbi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"abbbi","buy_me_a_coffee":"abbbi"}},"created_at":"2016-11-30T22:58:34.000Z","updated_at":"2026-02-03T14:36:32.000Z","dependencies_parsed_at":"2024-01-24T12:00:47.374Z","dependency_job_id":"0da75069-0e78-4bdd-8c12-0e9e862375a4","html_url":"https://github.com/abbbi/qmpbackup","commit_stats":{"total_commits":290,"total_committers":2,"mean_commits":145.0,"dds":"0.0034482758620689724","last_synced_commit":"dd3f190e7e9015da9f0a87829978ea7b85f426bf"},"previous_names":[],"tags_count":64,"template":false,"template_full_name":null,"purl":"pkg:github/abbbi/qmpbackup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abbbi%2Fqmpbackup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abbbi%2Fqmpbackup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abbbi%2Fqmpbackup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abbbi%2Fqmpbackup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abbbi","download_url":"https://codeload.github.com/abbbi/qmpbackup/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abbbi%2Fqmpbackup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29368210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup","incremental","kvm","kvm-hypervisor","linux-server","proxmox","proxmox-backup","python3","qemu","qemu-kvm","restore","virtual-machine","virtualization"],"created_at":"2024-10-29T23:15:18.779Z","updated_at":"2026-02-12T14:17:33.972Z","avatar_url":"https://github.com/abbbi.png","language":"Python","funding_links":["https://github.com/sponsors/abbbi","https://buymeacoffee.com/abbbi"],"categories":[],"sub_categories":[],"readme":"![ci](https://github.com/abbbi/qmpbackup/actions/workflows/ci-ubuntu-latest.yml/badge.svg)\n\nqmpbackup\n=========\n\nqmpbackup is designed to create live full and incremental backups of running\nqemu virtual machines via QMP protocol. It makes use of the dirty-bitmap\nfeature introduced in later QEMU versions. It works with standalone QEMU\nprocesses.\n\n![ScreenShot](https://raw.githubusercontent.com/abbbi/qmpbackup/refs/heads/master/qmpbackup.jpg)\n\nIf you want to backup QEMU virtual machines managed by `libvirt`, see this\nproject:\n\n https://github.com/abbbi/virtnbdbackup\n \n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**\n\n- [Installation](#installation)\n- [Prerequisites](#prerequisites)\n  - [Supported QEMU versions](#supported-qemu-versions)\n- [Usage](#usage)\n- [Backup](#backup)\n  - [Backup chains / unique bitmap names](#backup-chains--unique-bitmap-names)\n  - [Monthly Backups](#monthly-backups)\n  - [Excluding disks from backup](#excluding-disks-from-backup)\n  - [Filesystem Freeze](#filesystem-freeze)\n  - [Offline virtual machines](#offline-virtual-machines)\n  - [UEFI / BIOS (pflash devices)](#uefi--bios-pflash-devices)\n- [Restore](#restore)\n  - [Regular Rebase](#regular-rebase)\n  - [Rebase with commit](#rebase-with-commit)\n  - [Rebase into a new image](#rebase-into-a-new-image)\n  - [Rebase with adding snapshots](#rebase-with-adding-snapshots)\n- [Misc commands and options](#misc-commands-and-options)\n  - [Compressing backups](#compressing-backups)\n  - [List devices suitable for backup](#list-devices-suitable-for-backup)\n  - [Including raw devices (lvm, zfs, ceph)](#including-raw-devices-lvm-zfs-ceph)\n    - [Metadata qcow files for raw devices (lvm, zfs, ceph)](#metadata-qcow-files-for-raw-devices-lvm-zfs-ceph)\n  - [List existing bitmaps](#list-existing-bitmaps)\n  - [Cleanup bitmaps](#cleanup-bitmaps)\n  - [Speed limit](#speed-limit)\n- [Hypervisors](#hypervisors)\n  - [Proxmox](#proxmox)\n- [Limitations](#limitations)\n  - [Backing up libvirt virtual machines](#backing-up-libvirt-virtual-machines)\n  - [Backup target considerations](#backup-target-considerations)\n  - [TPM/SWTPM devices](#tpmswtpm-devices)\n  - [External Snapshots](#external-snapshots)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n# Installation\n\n*qmpbackup* makes use of [qemu.qmp](https://gitlab.com/jsnow/qemu.qmp)\n\n```\n python3 -m venv venv\n source venv/bin/activate\n pip3 install -r requirements.txt\n python3 setup.py install (alternatively use: `python -m pip install .` on systems deprecating setuptools)\n```\n\n# Prerequisites\n\nThe virtual machine must be reachable via QMP protocol on a unix socket,\nusually this happens by starting the virtual machine via:\n\n```\n qemu-system-\u003carch\u003e \u003coptions\u003e -qmp unix:/path/to/socket,server,nowait\n```\n\nYou can also configure qemu to provide the QMP protocol via TCP endpoint:\n\n```\n qemu-system-\u003carch\u003e \u003coptions\u003e  -qmp tcp:localhost:4444,server,wait=off\n```\n\n*qmpbackup* uses this socket to pass required commands to the virtual machine.\n\n`Note:` Use a dedicated socket for backup operations if possible, as qmp\nsockets only allow one connection at a time.\n\n## Supported QEMU versions\n\nUp until [Version 0.45](https://github.com/abbbi/qmpbackup/releases/tag/v0.45)\nQEMU \u003c= 7.0.0 is supported, all later versions introduce [image\nfleecing](https://abbbi.github.io/fleece/) and require at least QEMU Version\n7.1.\n\n# Usage\n\nIn order to create a full backup use the following command:\n\n```\n# remove already existent bitmaps from prior full backups:\n qmpbackup --socket /path/to/socket cleanup --remove-bitmaps\n# create a new full backup to an empty directory:\n qmpbackup --socket /path/to/socket backup --level full --target /tmp/backup/\n# example using a tcp endpoint:\n qmpbackup --socket tcp:localhost:4444  backup --level full --target /tmp/backup/\n```\n\nthe command will create a new unique dirty bitmap and backup the virtual\nmachines disks to ```/tmp/backup/\u003cdisk-bus-id\u003e/FULL-\u003ctimestamp\u003e```. It ensures\nconsistency by creating the bitmap and backup within one QMP transaction.\n\nMultiple disks attached to the virtual machine are backed up concurrently.\n\nDuring full and incremental backup, bitmaps will be created with `persistent\noption flag`. This means QEMU attempts to store them in the QCOW images, so\nthey are available between virtual machine shutdowns. The attached QCOW images\nmust be in qcow(v3) format, for this to work.\n\nIf you can't convert your QCOW images to newer formats, you still can use the\nbackup mode `copy`: it allows to execute a complete full backup but no further\nincremental backups.\n\nSecond step is to change some data within your virtual machine and let\n*qmpbackup* create an incremental backup for you, this works by:\n\n```\n qmpbackup --socket /path/to/socket backup --level inc --target /tmp/backup/\n```\n\nThe changed delta since your last full (or inc) backup will be dumped to\n`/tmp/backup/\u003cdisk-bus-id\u003e/INC-\u003ctimestamp\u003e`, the dirty-bitmap is automatically\ncleared after this and you can continue creating further incremental backups by\nre-issuing the command likewise.\n\nThere is also the `auto` backup level which combines the `full` and `inc`\nbackup levels. If there's no existing bitmap for the VM, `full` will run. If a\nbitmap exists, `inc` will be used.\n\n# Backup\n\n## Backup chains / unique bitmap names\n\nBy default a new full backup to an empty directory will create a new unique id\nfor the bitmap that is used to start a new backup chain.\n\nThis way you can create multiple backup chains, each of them using an\nunique bitmap to track the changes.\n\nThe `qmpbackup` utility will not cleanup those bitmaps by default if you can\ncleanup bitmaps that are not required via:\n\n```\n qmpbackup --socket /path/to/socket cleanup --remove-bitmaps\n qmpbackup --socket /path/to/socket cleanup --remove-bitmaps --uuid \u003cuuid\u003e\n```\n\nAlternatively you can specify the uuid to be used for the bitmap names during\nthe first full backup you create. This way the bitmaps will be reused and must\nnot be cleaned:\n\n```\n qmpbackup --socket /path/to/socket backup -l full -t /tmp/backup --uuid testme\n qmpbackup --socket /path/to/socket backup -l inc -t /tmp/backup\n```\n\n## Monthly Backups\n\nUsing the `--monthly` flag with the `backup` command, backups will be placed in\nmonthly folders in a YYYY-MM format.  The above combined with the `auto` backup\nlevel, backups will be created in monthly backup chains.\n\nExecuting the backup and the date being 2021-11, the following command: \n\n`qmpbackup --socket /path/to/socket backup --level auto --monthly --target /tmp/backup`\n\nwill place backups in the following backup path: `/tmp/backup/2021-11/`\n\nWhen the date changes to 2021-12 and *qmpbackup* is executed, backups will be\nplaced in `/tmp/backup/2021-12/` and a new full backup will be created.\n\n## Excluding disks from backup\n\nDisks can be excluded from the backup by using the *--exclude* option, the name\nmust match the devices \"node\" name (use the *info --show blockdev* option to\nget a list of attached block devices considered for backup)\n\nIf only specific disks should be saved, use the *--include* option.\n\n## Filesystem Freeze\n\nIn case the virtual machine has an guest agent installed you can set the QEMU\nGuest Agent socket (*--agent-socket*)  and request filesystem quiesce via\n*--quiesce* option:\n\n```\n  qmpbackup --socket /path/to/socket --agent-socket /tmp/qga.sock backup --level full --target /tmp/ --quisce\n```\n\nUse the following options to QEMU to enable an guest agent socket:\n\n```\n   -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \\\n   -device virtio-serial \\\n   -device \"virtserialport,chardev=qga0,name=org.qemu.guest_agent.0\" \\\n```\n\nIt is recommended to enable filesystem freeze during backup to ensure\nconsistency.\n\nIf the operating system running within the virtual machine does not include\nrequired agents and you need to ensure consistency, use the `--pause` option to\nsuspend the virtual machine during backup operation and resume afterwards.\n\n## Offline virtual machines\n\nIf you want to backup virtual machines without the virtual machine being in\nfully operational state, it is sufficient to bring up the QEMU process in\n`prelaunch` mode (The QEMU blocklayer is operational but no code is executed):\n\n```\n qemu-system-\u003carch\u003e -S \u003coptions\u003e\n```\n\n## UEFI / BIOS (pflash devices)\n\nIf the virtual machine uses UEFI, it usually has attached `pflash` devices\npointing to the UEFI firmware and variables files. These will be included in\nthe backup by default.\n\n\n# Restore\n\nRestoring your data is a matter of rebasing the created qcow images by using\nstandard tools such as *qemu-img* or *qmprestore*. There are three major\nfeatures implemented within the restore command: rebase, merge and\nsnapshotrebase.\n\nThe `rebase` and `snapshotrebase` commands will alter the directory\nin-place: this means your backup files will be changed.\n\nThe `merge` functionality will merge the data into a separate, new qcow file\noutside of your backup folder.\n\nA image backup based on a backup folder containing the following backups:\n\n```\n/tmp/backup/ide0-hd0/\n├── FULL-1706260639-disk1.qcow2\n├── INC-1706260646-disk1.qcow2\n└── INC-1706260647-disk1.qcow2\n```\n\ncan be recovered the following ways:\n\n## Regular Rebase\n\n\nA regular rebase will update the backing image for each backup file in-place:\n\n```\n qmprestore rebase --dir /tmp/backup/ide0-hd0\n```\n\nAfter rebase you will find an symlink `/tmp/backup/image`, which points to the\nlatest image to use with qemu or other tools.\n\n`Note:` It makes sense to copy the existing backup directory to a temporary\nfolder before rebasing, if you do not want to alter your existing backups.\n\nUsing the `--until` option rollback to a specific incremental point in \ntime is possible:\n\n```\n qmprestore rebase --dir /tmp/backup/ide0-hd0 --until INC-1480542701\n```\n\n## Rebase with commit\n\nIf you want to rebase and actually commit back the changes to the images use:\n\n```\n qmprestore commit --dir /tmp/backup/ide0-hd0\n```\n\nAfter rebase you will find the merged image file with all changes committed\nin the target folder.\n\n`Note:` It makes sense to copy the existing backup directory to a temporary\nfolder before rebasing, if you do not want to alter your existing backups.\n\n\n## Rebase into a new image \n\nIt is also possible to restore and rebase the backup files into a new target\nfile image, without altering the original backup files:\n\n```\n qmprestore merge --dir /tmp/backup/ide0-hd0/ --targetfile /tmp/restore/disk1.qcow2\n```\n\n## Rebase with adding snapshots\n\nUsing the `snapshotrebase` functionality it is possible to rebase/commit the\nimages back into an full backup, but additionally the rebase process will\ncreate an internal snapshot for the qemu image, for each incremental backup\napplied.\n\nThis way it is easily possible to switch between the backup states after\nrebasing.\n\n```\n qmprestore snapshotrebase --dir /tmp/backup/ide0-hd0/\n [..]\n qemu-img snapshot -l /tmp/backup/ide0-hd0/FULL-1706260639-disk1.qcow2\n Snapshot list:\n ID        TAG               VM SIZE                DATE     VM CLOCK     ICOUNT\n 1         FULL-BACKUP           0 B 2024-10-21 12:50:45 00:00:00.000          0\n 2         2024-10-21-12:42:48      0 B 2024-10-22 09:23:39 00:00:00.000       0\n 3         2024-10-21-12:42:49      0 B 2024-10-22 09:23:39 00:00:00.000       0\n```\n\n# Misc commands and options\n\n## Compressing backups\n\nThe `--compress` option can be used to enable compression for target files\nduring the `blockdev-backup` operation. This can save quite some storage space on\nthe created target images, but may slow down the backup operation.\n\n```\n qmpbackup --socket /path/to/socket backup [..] --compress\n```\n\n## List devices suitable for backup\n\n```\n qmpbackup --socket /path/to/socket info --show blockdev\n```\n\n## Including raw devices (lvm, zfs, ceph)\n\nAttached raw devices (format: raw) do not support incremental backup. The\nonly way to create backups for these devices is to create a complete full\nor copy backup.\n\nBy default `qmpbackup` will ignore such devices, but you can use the\n`--include-raw` option to create a backup for those devices \"as is\".\n\n### Metadata qcow files for raw devices (lvm, zfs, ceph)\n\nA better solution is to use the qcow2 data-file setting that has been\nintroduced in later qemu versions. It allows to create metadata qcow images\nthat can store the persistent bitmap information, but the real data can reside\non any storage backend. This allows to use the full backup featureset.\n\nAs example, you can create a metadata qcow image like so:\n\n```\n # point the data-file to a temporary file, as create will overwrite whatever it finds here\n qemu-img create -f qcow2 /vm1/metadata.qcow2 -o data_file=/tmp/TEMPFILE,data_file_raw=true ..\n rm -f /tmp/TEMPFILE\n```\n\nAnd then modify the image to point where the real data is provided (for example\na lvm device):\n\n```\n qemu-img amend /vm1/metadata.qcow2 -o data_file=/dev/lvm/vm1,data_file_raw=true\n```\n\nNow configure the metadata image `/vm1/metadata.qcow2` as primary disk in your\nqemu command call.\n\n## List existing bitmaps\n\nTo query existing bitmaps information use:\n\n```\n qmpbackup --socket /path/to/socket info --show bitmaps\n```\n\n## Cleanup bitmaps\n\nIn order to remove existing dirty-bitmaps use:\n\n```\n qmpbackup --socket /path/to/socket cleanup --remove-bitmaps\n```\n\nIf you create a new backup chain (new full backup to an empty\ndirectory) you should cleanup old bitmaps before.\n\n## Speed limit\n\nYou can set an speed limit (bytes per second) for all backup operations to\nlimit throughput:\n\n```\n qmpbackup --socket /path/to/socket backup [..] --speed-limit 2000000\n```\n\n# Hypervisors\n\n## Proxmox\n\nTo backup virtual machines running on Proxmox hypervisors it is recommended to\nre-configure the virtual machines to provide a second dedicated qmp socket.\nThis can be done using the `qm` command.\n\nFirst, show the command line that is used to start the vm (id 110 in this\nexample):\n\n```\n qm stop 110\n qm showcmd 110\n /usr/bin/kvm -id 110 -name [..] -chardev 'socket,id=qmp,path=/var/run/qemu-server/110.qmp,server=on,wait=off'\n```\n\nNow add an additional command line parameter to the VM configuration:\n\n```\n qm set 110 --args \"-chardev 'socket,id=qmp-backup,path=/var/run/qemu-server/110-backup.qmp,server=on,wait=off' -mon 'chardev=qmp-backup,mode=control'\"\n update VM 110: -args -chardev 'socket,id=qmp-backup,path=/var/run/qemu-server/110-backup.qmp,server=on,wait=off' -mon 'chardev=qmp-backup,mode=control'\n qm start 110\n```\n\nAfter the VM has started, a new qmp socket is available for backup:\n\n```\n ls -ah /var/run/qemu-server/110-backup.qmp\n /var/run/qemu-server/110-backup.qmp\n qmpbackup --socket /var/run/qemu-server/110-backup.qmp backup  [..]\n```\n\n\n# Limitations\n\n## Backing up libvirt virtual machines\n\nUsing the QMP protocol it cannot be used together with libvirt as libvirt\nexclusively uses the virtual machines monitor socket. See\n[virtnbdbackup](https://github.com/abbbi/virtnbdbackup).\n\n## Backup target considerations\n\nQEMUs ```drive-backup``` function does currently not support dumping data as a\nstream, it also cannot work with fifo pipes as the blockdriver expects\nfunctions like ftruncate and fseek to work on the target file, so the backup\ntarget must be a directory.\n\n## TPM/SWTPM devices\n\nCurrently the utility will not handle backup of related (SW)TPM devices\nattached to the virtual machine. A warning will be issued if such devices are\ndetected during backup.\n\n## External Snapshots\n\nIn case a external snapshot is created for certain devices, as in:\n\n ```\n blockdev-add driver=qcow2 node-name=snap_1 file={\"driver\":\"file\",\"filename\":\"/mysnapshot.qcow2\"}\n blockdev-snapshot node=disk1 overlay=snap_1\n ```\n\nthe backup process will always backup the active snapshot device (the device\n\"snap_1\"), not the original file it is based on.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabbbi%2Fqmpbackup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabbbi%2Fqmpbackup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabbbi%2Fqmpbackup/lists"}