Back to tutorials
Tutorial

Full-Server Backup Tutorial: Image-Level Backups with Proxmox vzdump + Offsite Sync (2026 Setup Guide)

Full-server backup tutorial for Proxmox: vzdump scheduling, encryption, offsite sync, and tested restores for VPS workloads in 2026.

By Anurag Singh
Updated on Jun 27, 2026
Category: Tutorial
Share article
Full-Server Backup Tutorial: Image-Level Backups with Proxmox vzdump + Offsite Sync (2026 Setup Guide)

File-based backups work—until you need to rebuild an entire server quickly. That rebuild usually includes the OS, configs, your web stack, and the one custom service nobody documented. This full-server backup tutorial shows a practical image-level workflow on Proxmox VE using vzdump. It then copies those backups offsite with clear retention and a real restore test.

It’s aimed at hosting workloads like WordPress, mail gateways, small SaaS apps, reseller nodes, and “snowflake” VPSes you do not want to reconstruct under stress.

If you run production VMs on a hypervisor (or you are a developer with a few critical instances), this gives you a recovery path. It does not depend on the guest OS being healthy.

Keep app-level backups for databases and other fast-changing data. Image-level backups cover the “won’t boot / disk died / upgrade went sideways” category.

Why image-level backups belong in your hosting stack (and where they don’t)

Image-level VM backups capture the full VM/LXC state (disk + config). That is different from the marketing term “snapshot backups.” In this workflow, Proxmox generates a consistent backup archive. It writes that archive to a Proxmox storage target you control.

  • Best for: fast full restores, recovering from failed upgrades, ransomware cleanup, accidental config damage, and rebuilding a node after disk failure.
  • Not enough by itself: high-change databases without quiescing, point-in-time needs, or compliance requirements that demand per-app restore granularity.

Restores often turn into mini-migrations. Expect DNS changes, TTL timing, validation steps, and rollback planning.

Keep a separate runbook for that part. See: DNS cutover tutorial for low downtime.

Prerequisites and a safe lab plan

This tutorial assumes:

  • Proxmox VE 8.3+ (recommended for 2026 production deployments)
  • A VM (KVM/QEMU) and/or an LXC container you want to protect
  • Offsite storage: an SFTP server, another Proxmox Backup Server, or any host you can push to via SSH

Lab first: pick one non-critical VM. Run the full loop: backup → copy offsite → restore into a new VM ID → boot → validate services.

This is where you catch permissions, missing space, and key/auth problems.

If you need a simple offsite target (SFTP/SSH, rsync receiver, object gateway, or a second box), a small HostMyCode VPS works well as a dedicated backup receiver.

Use a single-purpose user, locked-down SSH keys, and tight firewall rules.

Step 1: Create a dedicated backup storage on Proxmox

First, decide where Proxmox writes local backups. This is the staging area before you ship them offsite.

In most setups:

  • Put backups on a separate disk or ZFS dataset if you can.
  • Avoid keeping backups on the same RAID group as VM disks if “one failure takes all” is unacceptable.

Example (ZFS dataset):

zfs create -o compression=zstd -o atime=off rpool/backup
zfs set mountpoint=/rpool/backup rpool/backup
mkdir -p /rpool/backup/vzdump

In the Proxmox UI: Datacenter → Storage → Add → Directory

  • ID: local-vzdump
  • Directory: /rpool/backup/vzdump
  • Content: VZDump backup file

CLI check:

pvesm status
pvesm list local-vzdump | head

Step 2: Build a clean, consistent backup job with vzdump

Proxmox uses vzdump for scheduled backups. You can manage jobs in the UI or with cron.

UI jobs are easier to review later. They also survive routine platform changes.

In the Proxmox UI: Datacenter → Backup → Add

  • Storage: local-vzdump
  • Schedule: e.g. daily at 02:30
  • Selection mode: include specific VMs/CTs (start small)
  • Mode: Snapshot (best for minimal downtime) or Stop (most consistent, brief downtime)
  • Compression: ZSTD (good balance in 2026)
  • Notification: set an email target if you use Proxmox notifications

Choosing a mode:

  • Snapshot mode is usually fine for web servers and most WordPress stacks.
  • Stop mode is safer for write-heavy systems if you can tolerate a short outage.
  • For mail workloads, test both. You care about queue and mailbox consistency, not just uptime.

Run a one-off backup from CLI (useful for verifying the basics):

# VM example
vzdump 101 --storage local-vzdump --compress zstd --mode snapshot --notes-template '{{guestname}} {{vmid}} {{node}}'

# LXC example
vzdump 201 --storage local-vzdump --compress zstd --mode snapshot

Where to check when something fails:

tail -n 200 /var/log/vzdump.log
journalctl -u pvedaemon -n 200 --no-pager

Step 3: Add retention that matches real recovery needs

Backups without retention turn into a storage incident. Start with something simple. It should also be easy to defend later.

  • 7 daily
  • 4 weekly
  • 6 monthly (if storage allows)

Proxmox backup jobs can prune in the UI. Whether you can do that depends on the storage type.

If you use a plain directory target, handle retention with a small script. Delete older vzdump archives by count or date.

Simple count-based retention (per VMID): create /usr/local/sbin/pve-prune-vzdump.sh:

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/rpool/backup/vzdump"
KEEP=7

shopt -s nullglob
for vmid in $(ls -1 "$BACKUP_DIR"/vzdump-*.{vma.zst,lzo,zst,tar.zst} 2>/dev/null | sed -E 's/.*vzdump-[a-z]+-([0-9]+)-.*/\1/' | sort -u); do
  files=( $(ls -1t "$BACKUP_DIR"/vzdump-*-"$vmid"-*.{vma.zst,tar.zst} 2>/dev/null || true) )
  if [ "${#files[@]}" -gt "$KEEP" ]; then
    for f in "${files[@]:$KEEP}"; do
      rm -f -- "$f"
    done
  fi
done

Make it executable and run it after backups:

chmod +x /usr/local/sbin/pve-prune-vzdump.sh
/usr/local/sbin/pve-prune-vzdump.sh

Tip: If you do not want to maintain retention scripts, Proxmox Backup Server (PBS) is built for dedupe, pruning, and verification. If you host PBS offsite, it becomes both storage and policy.

Step 4: Encrypt before offsite sync (two safe options)

Encrypt anything you send offsite. Two approaches are common:

  • Option A (preferred): back up to PBS, which encrypts and verifies by design.
  • Option B: encrypt the vzdump artifacts before pushing them to an SFTP/SSH host.

This tutorial uses Option B because it works with any SSH-accessible host.

Create a GPG key on the Proxmox node (or import a key used only for backups):

gpg --full-generate-key
# Choose: RSA and RSA, 4096 bits, set an expiry, add a strong passphrase

Encrypt a backup file:

cd /rpool/backup/vzdump
FILE="vzdump-qemu-101-2026_06_27-02_30_01.vma.zst"

gpg --output "${FILE}.gpg" --symmetric --cipher-algo AES256 "$FILE"
sha256sum "$FILE" "${FILE}.gpg" > "${FILE}.sha256"

Once you trust the flow, decide what you want to keep locally.

Many teams keep plaintext locally for fast restores. They store only encrypted copies offsite.

Step 5: Push offsite with rsync over SSH (locked down)

Use an offsite Linux host with enough disk and a single-purpose user.

If it is reachable from the public Internet, treat SSH like production access.

On the offsite host:

adduser --disabled-password --gecos "" backups
mkdir -p /srv/offsite/pve-vzdump
chown -R backups:backups /srv/offsite/pve-vzdump

On the Proxmox node, create an SSH key just for backups:

ssh-keygen -t ed25519 -f /root/.ssh/pve_offsite_ed25519 -C "pve-offsite-backup"

Add the public key to /home/backups/.ssh/authorized_keys on the offsite host. Then restrict it.

Example restriction line (adjust paths):

command="/usr/bin/rrsync -ro /srv/offsite/pve-vzdump",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc ssh-ed25519 AAAA... pve-offsite-backup

Install rrsync (often shipped with rsync docs, path varies). On Debian/Ubuntu it’s typically in /usr/share/doc/rsync/scripts/rrsync. Copy it:

cp /usr/share/doc/rsync/scripts/rrsync /usr/bin/rrsync
chmod +x /usr/bin/rrsync

Rsync the encrypted backups:

rsync -avh --progress -e "ssh -i /root/.ssh/pve_offsite_ed25519" \
  /rpool/backup/vzdump/*.gpg /rpool/backup/vzdump/*.sha256 \
  backups@OFFSITE_IP:/srv/offsite/pve-vzdump/

Offsite integrity check:

ssh -i /root/.ssh/pve_offsite_ed25519 backups@OFFSITE_IP "cd /srv/offsite/pve-vzdump && sha256sum -c --ignore-missing *.sha256 | tail -n 20"

If you also need a baseline firewall setup, pair this with a simple rule set. See: UFW firewall configuration tutorial.

Step 6: Automate the full pipeline (backup → encrypt → offsite sync)

Let Proxmox run the backup job. Then schedule encryption + offsite sync with cron.

The simplest pattern is “run after the backup window.” For example, run it at 03:30.

Create /usr/local/sbin/pve-offsite-sync.sh:

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/rpool/backup/vzdump"
SSH_KEY="/root/.ssh/pve_offsite_ed25519"
OFFSITE="backups@OFFSITE_IP:/srv/offsite/pve-vzdump/"

cd "$BACKUP_DIR"

# Encrypt any new .vma.zst or .tar.zst files that don't have a .gpg yet
for f in vzdump-*.vma.zst vzdump-*.tar.zst; do
  [ -f "$f" ] || continue
  if [ ! -f "${f}.gpg" ]; then
    gpg --batch --yes --symmetric --cipher-algo AES256 --output "${f}.gpg" "$f"
    sha256sum "$f" "${f}.gpg" > "${f}.sha256"
  fi
done

# Sync encrypted artifacts and checksums
rsync -avh -e "ssh -i $SSH_KEY" \
  --include='*.gpg' --include='*.sha256' --exclude='*' \
  "$BACKUP_DIR/" "$OFFSITE"

Enable and schedule it:

chmod +x /usr/local/sbin/pve-offsite-sync.sh
crontab -e

Add:

30 3 * * * /usr/local/sbin/pve-offsite-sync.sh >> /var/log/pve-offsite-sync.log 2>&1

Operational habit: check that log weekly. Alert on failures.

If you already centralize logs, it is easier to spot “quietly broken” backups before you need them. Related reading: log shipping with rsyslog + TLS.

Step 7: Restore test (the part everyone skips)

A backup you have not restored is just storage you pay for.

Do a restore test after your first successful offsite run. Repeat after major changes like OS upgrades, storage changes, and disk layout changes.

Restore a VM backup into a new VMID

Pick a backup file from local storage. Local restores are faster for testing:

ls -1 /rpool/backup/vzdump/vzdump-qemu-101-*.vma.zst | tail -n 3

Restore to a new VM ID (example: 901):

qmrestore /rpool/backup/vzdump/vzdump-qemu-101-2026_06_27-02_30_01.vma.zst 901 --storage local-lvm

Start it and watch console:

qm start 901
qm status 901

Validation checklist:

  • VM boots without filesystem repair prompts
  • Network comes up (check MAC/IP expectations)
  • Web server responds on localhost: curl -I http://127.0.0.1
  • SSL cert files exist and services reload cleanly
  • App-level checks: WordPress admin loads, scheduled jobs run, mail queue behaves

Restore from offsite (decrypt first)

If the offsite copy is encrypted (as it should be), pull it back first:

rsync -avh -e "ssh -i /root/.ssh/pve_offsite_ed25519" \
  backups@OFFSITE_IP:/srv/offsite/pve-vzdump/vzdump-qemu-101-2026_06_27-02_30_01.vma.zst.gpg \
  /root/restore-tests/

Decrypt it:

cd /root/restore-tests
gpg --output vzdump-restore.vma.zst --decrypt vzdump-qemu-101-2026_06_27-02_30_01.vma.zst.gpg

Then restore:

qmrestore /root/restore-tests/vzdump-restore.vma.zst 902 --storage local-lvm
qm start 902

If you want a real disaster drill (fresh node, DNS cutover, full validation), run it quarterly. Write down timings.

Restore tests are also where DNS TTL assumptions and certificate renewal edge cases show up. For SSL issues after a restore, keep this close: SSL renewal troubleshooting tutorial.

Common failure modes (and quick fixes)

  • Backups randomly fail with “No space left on device”: your local backup store is too small or retention isn’t running. Check with df -h, then prune or expand storage.
  • Snapshot backup stalls: high disk I/O can make snapshot merges drag. Check storage latency and iowait on the node. If the host is underpowered, moving backups (or workloads) to dedicated hardware may be the clean fix.
  • Restored VM boots but services fail: IP changes, DNS issues, or time drift. Verify /etc/resolv.conf, NTP, and any hard-coded allowlists.
  • Offsite rsync works once then breaks: SSH restrictions are too tight, or a path changed. Test with ssh -i KEY backups@OFFSITE_IP 'pwd' and review auth.log.

Operational checklist you can paste into a runbook

  • Backups stored locally on separate storage
  • Nightly backup job verified (latest archive timestamp matches schedule)
  • Retention confirmed (disk usage stable week to week)
  • Offsite copy encrypted and checksum-verified
  • Quarterly restore test documented (boot + service checks)
  • Credentials hardened (restricted SSH key, limited user, firewall rules)

Summary: a practical full-server backup workflow for 2026

Image-level backups will not replace app-aware backups. They are still the fastest way back from “the server is gone.”

With vzdump, sensible retention, encryption, and an offsite sync, you get a workflow you can run daily. More importantly, you can rely on it when something breaks.

If you are scaling beyond one node, keep your DNS and migration process just as disciplined.

A restore is still a migration in practice. TTL and record mistakes hurt just as much during an incident.

If you want an offsite target that stays stable, run your backup receiver on a dedicated HostMyCode VPS. If you’d rather hand off the operational load, move production to managed VPS hosting so backups, retention, and restore tests stay on a schedule. HostMyCode focuses on hosting operations that matter: uptime, recovery, and support that understands real workloads.

FAQ

Should I use Snapshot or Stop mode for Proxmox backups?

Use Snapshot for most web workloads to avoid downtime. Use Stop for VMs with heavy writes where consistency matters more than a brief outage. Test both and confirm you can boot and validate services.

Do I still need database backups if I run image-level backups?

Yes. Image-level backups restore the entire server, but they don’t give you granular restores like “just the database from 10:15.” Keep app-level backups for databases and treat VM backups as your safety net.

How much offsite storage do I need?

Start with 2–3x your protected VM disk usage if you keep a week of nightly backups. With compression and stable servers, you may use less, but assume growth and log/data churn.

How often should I do a restore test?

After initial setup, after major upgrades, and at least quarterly. Your goal is to measure time-to-recover and catch missing dependencies (DNS, firewall rules, SSL renewal) before an incident.

What if I’m not using Proxmox?

The same principles apply: consistent backups at the hypervisor layer, offsite copies, encryption, retention, and restore drills. The commands differ, but the runbook mindset stays the same.