Introduction

Set up a nightly backup job in Proxmox VE and it just works. Every night at 2 AM, a fresh copy of your VM lands on your NFS share or local disk. That feels great for about three weeks, right up until someone checks the storage and finds it's 80% full of .vma.zst files going back to installation day. Nothing was ever configured to delete the old ones.

This is one of the more common surprises for people moving from VMware or just running their first homelab node. Proxmox VE doesn't guess how many backups you want to keep. Left on its defaults, a storage with no retention rule attached will hold on to every backup forever, and your disk fills up until a job fails with a write error at 3 AM.

The fix is retention, sometimes called pruning: telling Proxmox exactly how many backups to keep, at what intervals, and letting it delete the rest automatically. This guide covers how that works for regular vzdump-based backups going to local disk, NFS, or CIFS storage — not Proxmox Backup Server, which uses its own separate deduplication and garbage-collection system with different commands. If you're on PBS, the rules below don't apply to you the same way.

What You Will Learn

  • What backup retention actually means in Proxmox VE, and why the default behavior isn't what most people expect
  • The six keep-* options and how they combine to build a retention policy
  • How to set retention on a storage so it applies to every backup job using it
  • How to override that default for a single backup job
  • The pvesm and vzdump commands for setting and testing retention from the shell
  • Errors you'll hit if a policy is misconfigured, and how to read them
  • A few realistic policies depending on how much history you actually need

What Is This Feature?

Backup retention in Proxmox VE is a rule set attached to a storage (or to an individual backup job) that decides which backup archives get kept after a new one is created, and which ones get deleted. The setting itself is called prune-backups, and it's built from up to six counters:

OptionWhat it keeps
keep-lastThe N most recent backups, regardless of date
keep-hourlyOne backup per hour, for the last N hours
keep-dailyOne backup per day, for the last N days
keep-weeklyOne backup per week, for the last N weeks
keep-monthlyOne backup per month, for the last N months
keep-yearlyOne backup per year, for the last N years

There's also keep-all, which just means "never delete anything" and can't be combined with the others. That's effectively what an unconfigured storage does by default, minus the honesty of it being written down anywhere.

After every backup run, Proxmox looks at every existing archive for that VM or container on that storage, applies whichever counters are set, and removes anything that doesn't satisfy at least one of them. A backup only needs to match one rule to survive — the counters are additive, not stacked as separate deductions from a total.

If you've used older Proxmox guides, you might see a setting called maxfiles instead. That's the legacy option from before PVE 6, and it only does the equivalent of keep-last — a flat count with no concept of hourly, daily, or weekly tiers. It still works on current versions for backward compatibility, but there's no reason to use it over prune-backups on a new setup.

Why Would You Use It?

Two reasons, really. The obvious one is disk space — backups are large, and a storage with no limit will eventually fill up, usually at the worst possible moment. The less obvious one is that "more backups" isn't automatically better. A restore point from fourteen months ago that nobody will ever use is just wasted space that could be doing something useful, like giving you more daily or weekly coverage instead.

A good retention policy matches how you actually recover from problems. Most of the time you're restoring because something broke in the last day or two — a bad update, a config change, a typo in a script. Hourly and daily coverage handles that. Weekly and monthly coverage is there for the "I didn't notice this was broken until last month" scenario, which happens less often but does happen. Keeping every single nightly backup going back a year covers neither case particularly well; it just burns disk.

There's also a quieter benefit: once retention is configured, you stop having to think about it. No more manually deleting old backups from the GUI every few weeks because someone noticed the storage warning turn orange.

Prerequisites

Before setting this up, you'll want:

  • A working Proxmox VE install — this guide applies to 8.x and 9.x, since the retention logic hasn't changed in years
  • At least one backup storage already added (local directory, NFS, or CIFS — anything with the Backup content type enabled, not Proxmox Backup Server)
  • One or more existing backup jobs, or a VM/LXC you can test a manual backup against
  • Shell access to the node if you want to use pvesm and vzdump directly, though everything here can also be done from the web GUI

You don't need any backups to already exist to configure retention — it's just a rule that gets applied the next time a backup runs. But it does help to have a few test backups around so you can actually see a prune happen instead of taking it on faith.

Step-by-Step Tutorial

Setting Retention on a Storage (the Default for Every Job)

  1. Log in to the Proxmox VE web interface and go to Datacenter in the left tree.
  2. Click Storage, select the storage you back up to (for example, your NFS share or local), and click Edit.
  3. Open the Backup Retention tab in the edit dialog.
  4. You'll see a checkbox for Keep all backups, which is what's effectively active if you leave everything blank. Uncheck it if it's ticked.
  5. Fill in whichever of the six fields — Keep Last, Keep Hourly, Keep Daily, Keep Weekly, Keep Monthly, Keep Yearly — apply to your situation. Leave the rest blank; a blank field means that rule isn't used at all, not zero.
  6. Click OK.

That's it — this policy now applies to every backup job that writes to this storage, unless a specific job overrides it in the next step.

Overriding Retention for a Single Backup Job

Sometimes one VM needs different treatment — a database server you want hourly snapshots of, sitting on the same NFS share as everything else that only needs daily ones.

  1. Go to Datacenter → Backup.
  2. Either click Add to create a new scheduled job, or select an existing one and click Edit.
  3. In the job dialog, open the Retention tab.
  4. By default this is set to Keep all backups as configured in the storage configuration — meaning it just inherits whatever you set in the previous section. Switch it to Keep the specified number of backups only.
  5. Fill in the counters for this job specifically. These now override the storage's defaults, but only for backups this job creates.
  6. Save the job.

Worth noting: this override applies to the job, not to the VM. If you also back up the same VM manually or through a second job, that other backup follows whatever retention rule applies to it.

Setting Retention from the Command Line

If you'd rather script this — Ansible, Terraform, or just a habit of doing everything from a terminal — the storage-level default is set with pvesm:

pvesm set local --prune-backups keep-last=3,keep-daily=7,keep-weekly=4,keep-monthly=6

Replace local with your storage ID. You can confirm it took effect by checking the storage config directly:

grep -A5 "^dir: local" /etc/pve/storage.cfg

For a one-off manual backup where you want to test a retention rule without touching the storage config at all, pass it straight to vzdump:

vzdump 100 --storage local --mode snapshot --prune-backups keep-last=3,keep-daily=7

This runs a backup of VM 100, then immediately applies that retention rule to the existing backups for VM 100 on that storage — a good way to see pruning happen once, right away, instead of waiting for tonight's scheduled job.

Commands Explained

pvesm set <storage> --prune-backups <rules>pvesm is the Proxmox VE storage manager. The set subcommand modifies an existing storage's configuration, and --prune-backups is the property that holds your retention rules as a comma-separated list of key=value pairs.

vzdump <vmid> --prune-backups <rules>vzdump is the actual backup tool Proxmox runs under the hood, whether triggered by the GUI, a scheduled job, or you typing it directly. Passing --prune-backups on the command line applies that policy to this run instead of whatever's set on the storage.

--mode snapshot — tells vzdump to use the storage's live-snapshot capability (LVM-thin, ZFS, or qcow2 snapshots) so the VM keeps running during the backup instead of being suspended. This isn't part of retention, but you'll see it in most vzdump examples, including the one above.

grep -A5 "^dir: local" /etc/pve/storage.cfg — reads five lines after the line defining your local storage from Proxmox's plain-text storage configuration file. It's a quick way to confirm a prune-backups value actually saved, without going back into the GUI.

Common Errors

"can't use keep-all together with other options" — you've got keep-all=1 set alongside one of the keep-* counters. They're mutually exclusive by design; pick one approach. Uncheck "Keep all backups" in the GUI, or drop keep-all from the CLI value entirely.

"unable to parse prune-backups option" — usually a typo in the CLI syntax, most often a space where a comma should be, like keep-last=3 keep-daily=7 instead of keep-last=3,keep-daily=7. No spaces around the commas or equals signs.

Backups aren't being deleted even though retention is set — pruning only runs as part of a backup job, right after that job finishes creating its new archive. It's not a background service checking your storage every hour. If you set a policy but haven't run a backup since, nothing gets cleaned up yet — the next scheduled run will apply it.

A VM's backup count doesn't match what you expected — retention is calculated per VM ID, not per job or per storage as a whole. If you back up VM 100 from two different jobs onto the same storage, each job's archives get pruned according to whichever rule applies to that job, and the counts can look uneven at a glance.

Troubleshooting

If you're not sure whether your policy is doing what you think, don't guess — check the actual task log. Go to the node's Tasks panel (or the VM's Backup tab) after a scheduled job runs, and open the log for that backup task. Near the end, you'll see a summary listing exactly which archives vzdump decided to keep and which it removed, with the reason for each.

If the pruning section of the log is missing entirely, retention probably isn't configured on that storage or that job — go back and check both the storage's Backup Retention tab and the job's Retention tab, since either one being set to "keep all" will suppress pruning silently rather than throwing an error.

If backups are disappearing faster than expected, the most likely cause is a job's retention override being more aggressive than you remember setting — check the job's Retention tab specifically, not just the storage default, since the job-level setting wins when both are present.

One thing that surprises people the first time: keep-monthly=6 doesn't mean "keep backups from the last 6 months plus everything else." It only looks at the most recent 6 calendar months and keeps one backup from each. Anything older than that window is gone unless another rule (like a high keep-yearly) also covers it.

Best Practices

  • Set retention on the storage first, as a sane default, then override per-job only for VMs that genuinely need different treatment.
  • Combine tiers instead of relying on one — keep-last alone gives you a flat count with no sense of "how far back can I reach," while daily plus weekly plus monthly gives you both recent granularity and long-term coverage.
  • Match retention to your backup schedule. Setting keep-hourly=24 on a job that only runs once a day accomplishes nothing, since there's never more than one backup per day to count.
  • Watch your storage usage for the first month after changing a policy — the old backups from before the change don't retroactively disappear until the next backup run triggers a prune, so there's a lag before you see the real steady-state disk usage.
  • Don't set retention so aggressive that a single bad backup run leaves you with nothing recent. keep-last=1 means exactly one backup exists at any time, which is risky if that one backup happens to be from a VM that was already in a broken state when it was taken.

Frequently Asked Questions

Does this apply to Proxmox Backup Server too?

No. PBS uses its own prune and garbage collection system, configured per-datastore through proxmox-backup-manager or the PBS web interface, with different mechanics around deduplicated chunks. The prune-backups option covered here is for regular vzdump storage like local disk, NFS, and CIFS.

What happens to backups that already exist when I add a new retention policy?

Nothing, until the next backup runs for that VM on that storage. Pruning is triggered by a backup completing, not by saving a config change.

Can I set retention without ever running out of keep-last space?

keep-last has no hard upper bound in the config itself, but every backup you keep still takes up real disk space. There's no way around that trade-off — more retention always costs more storage.

Is there a way to test a policy before trusting it?

Run a manual backup with vzdump <vmid> --prune-backups <rules> against a low-priority test VM first, then check the task log's pruning summary to see exactly what it would have removed.

What's the difference between the storage-level and job-level retention settings?

Storage-level is the default applied to any backup landing on that storage. Job-level, set in a specific backup job's Retention tab, overrides that default for backups created by that job only.

Conclusion

Retention isn't something you need to get perfect on day one. Start with a storage-level default that covers the basics — a couple weeks of daily backups and a few months of weekly ones is a reasonable starting point for most homelabs — and adjust once you actually see how fast your storage fills up. The important part is just having a policy at all, instead of finding out the hard way that "keep everything forever" was the default the whole time.