Guide: restoring a Proxmox backup from BorgBackup

This guide follows Backing up Proxmox with BorgBackup, monitored with Borg-UI. It starts from the Borg repository already filled by the daily backup and explains how to get the data back, from a single container up to losing the whole host.

A backup that has never been restored is just a hypothesis. The number one tip of this whole guide: do a test restore now, on a small container, while you’re not in a hurry.

Before you start

The commands use these names, which you should adapt to your setup:

WhatExample value
Repository/mnt/nas-backup/borg-proxmox
Dump archivesproxmox-YYYY-MM-DD_HH-MM
Configuration archivespve-config-YYYY-MM-DD_HH-MM
Dump folder on the host/var/lib/vz/dump
Staging folder for the restore/mnt/nas-backup/restore

You need two things: the repository passphrase and, for disaster recovery, the repository key too (with repokey it’s inside the repository itself, but it’s still worth having an export off the host).

For convenience, load the passphrase into the environment. The backup reads it from a root-only file:

source /etc/borg-backup.env
export BORG_REPO=/mnt/nas-backup/borg-proxmox

If the passphrase isn’t available in that file, export it by hand with export BORG_PASSPHRASE='...' or let Borg prompt for it.

The lock. Borg holds a lock on the repository while someone is using it. If the backup script is running (in my case it starts at 08:00), the command may wait or fail. Wait for it to finish. Use borg break-lock only if you’re sure no process is working on the repository.


1. Find out what’s in the repository

List all archives:

borg list "$BORG_REPO"

Only the dumps, or only the configuration:

borg list "$BORG_REPO" --glob-archives 'proxmox-*'
borg list "$BORG_REPO" --glob-archives 'pve-config-*'

Look inside an archive and find the dump you need (ID 103 is an example):

borg list "$BORG_REPO"::proxmox-2026-11-06_08-00 | grep 'vzdump-.*-103-'

Paths inside the archive have no leading slash: the dump /var/lib/vz/dump/vzdump-lxc-103-...tar.zst shows up as var/lib/vz/dump/vzdump-lxc-103-...tar.zst. Copy the exact name from the output.

You can see the same information in Borg-UI by opening the repository and browsing the archives: handy for finding the right date before switching to the command line.


2. Extract only what you need

Don’t extract a whole archive: it contains every dump and can weigh hundreds of GB. Extract just the file you need.

Where to extract. Pick a volume with free space, not the host’s root filesystem (pve-root): it’s small, and filling it up puts Proxmox in trouble. The NAS or a large datastore is fine.

First a dry run, to check that the command does what you think:

borg extract --dry-run --list "$BORG_REPO"::proxmox-2026-11-06_08-00 \
    var/lib/vz/dump/vzdump-lxc-103-2026_11_06-08_00_01.tar.zst

Then the real extraction:

mkdir -p /mnt/nas-backup/restore
cd /mnt/nas-backup/restore

borg extract "$BORG_REPO"::proxmox-2026-11-06_08-00 \
    var/lib/vz/dump/vzdump-lxc-103-2026_11_06-08_00_01.tar.zst

The file appears in /mnt/nas-backup/restore/var/lib/vz/dump/.

Alternative: mount the archive. If FUSE is available you can mount the archive as if it were a folder and copy what you need:

mkdir -p /mnt/borg
borg mount "$BORG_REPO"::proxmox-2026-11-06_08-00 /mnt/borg
ls /mnt/borg/var/lib/vz/dump/
# ...copy what you need...
borg umount /mnt/borg

3. Restore a container (LXC)

Container dumps are vzdump-lxc-ID-...tar.zst files.

pct restore 203 /mnt/nas-backup/restore/var/lib/vz/dump/vzdump-lxc-103-2026_11_06-08_00_01.tar.zst \
    --storage local-lvm

Key points:

  • Use a new ID (here 203, while the original is 103). That way you don’t overwrite the existing container and can check that the restore works before replacing it.
  • Check the network before starting it: if the container uses a static IP, running the copy alongside the original causes an address conflict. Keep the copy stopped or change its IP. The --unique option of pct restore also generates a new MAC address for the copy.
  • If you want to replace the original, stop it and restore onto the same ID with --force, which overwrites the existing container:
pct stop 103
pct restore 103 /mnt/nas-backup/restore/var/lib/vz/dump/vzdump-lxc-103-2026_11_06-08_00_01.tar.zst \
    --storage local-lvm --force

Start it and check:

pct start 203
pct status 203

4. Restore a virtual machine (QEMU)

VM dumps are vzdump-qemu-ID-...vma.zst files.

qmrestore /mnt/nas-backup/restore/var/lib/vz/dump/vzdump-qemu-102-2026_11_06-08_00_01.vma.zst 202 \
    --storage local-lvm

The same rules as for containers apply: a new ID for testing (202), --force to overwrite, and watch out for duplicate IPs and MACs if you start the copy while the original is running. Here too, --unique gives the copy a new MAC.

qm start 202
qm status 202

5. Restore the Proxmox configuration

The pve-config-* archives contain /etc/pve, /etc/network/interfaces, /etc/hosts and /etc/hostname.

Extract into a temporary folder and copy by hand only the files you need:

mkdir -p /root/pve-restore
cd /root/pve-restore
borg extract "$BORG_REPO"::pve-config-2026-11-06_08-00

ls etc/pve/lxc etc/pve/qemu-server
cat etc/pve/storage.cfg

Examples of targeted recovery:

# a container's configuration, if you lost the .conf file
cp etc/pve/lxc/103.conf /etc/pve/lxc/103.conf

# storage definitions
diff etc/pve/storage.cfg /etc/pve/storage.cfg

Don’t extract directly over /etc/pve. It’s the Proxmox cluster filesystem (pmxcfs), not a regular folder: overwriting it with a batch of files can break the host. Compare, copy only what’s needed, and leave alone the files you don’t know.


6. Disaster recovery: the host is gone

Scenario: the system disk died or the host won’t boot, but the NAS with the repository is intact.

  1. Reinstall Proxmox VE on the hardware (same major version, if possible) with the same hostname and the same IP address.

  2. Restore networking and the NAS mount. Recreate the NAS mount at /mnt/nas-backup with the same path (NFS or CIFS, depending on how it was set up), because the script and the storages expect that mount point.

  3. Install Borg (apt install borgbackup). Check the version with borg --version: the repository is in Borg 1.x format, so you need a 1.x release (ideally the same as or newer than the one used for the backup). Borg 2 uses a different format and can’t open a 1.x repository directly.

  4. Get the passphrase and the key. With repokey the key is in the repository, so the passphrase is enough. If you exported the key instead:

    borg key import /mnt/nas-backup/borg-proxmox /path/to/borg-key-backup.txt
    
  5. Check that the repository opens:

    export BORG_PASSPHRASE='...'
    borg list /mnt/nas-backup/borg-proxmox | tail
    
  6. Recreate the storages with the same names the backups used (for example local-lvm), using the storage.cfg from the most recent pve-config-* archive.

  7. Restore VMs and containers one by one, as in sections 3 and 4, from the latest dump, with the original IDs (the new host has no conflicts).

  8. Recover the configuration files you need (section 5), without overwriting /etc/pve wholesale.

  9. Reinstall the backup script, the /etc/borg-backup.env file with 600 permissions, and the cron line.

  10. Check the first backup after the restore, by watching the log and making sure the new archive shows up.


7. Check regularly that the backups are healthy

Check the repository integrity (structure, not data) outside the cron window:

borg check --repository-only "$BORG_REPO"

With a large repository (hundreds of GB) the full data check takes a long time:

borg check --verify-data "$BORG_REPO"

Run it now and then, when you can leave the NAS busy for hours. Both commands hold the lock, so don’t run them while the backup is running.

The most important check, though, is the practical one: every so often, restore a small container with a new ID, start it, check that it works, then delete it:

pct destroy 203
rm -rf /mnt/nas-backup/restore

Quick checklist

  • Repository passphrase off the host (password manager)
  • Repository key exported with borg key export and stored elsewhere
  • Extract to a volume with free space, not the host root
  • New ID for test restores
  • Never extract directly over /etc/pve
  • At least one test restore done
  • borg check now and then

Useful references

  • Borg documentation: borg extract, borg mount, borg check, borg key
  • Proxmox documentation: vzdump, pct restore, qmrestore