Homelab the Right Way

Home › Posts

Never delete this stopped Proxmox VM

A Proxmox template is always stopped, so it looks exactly like an abandoned VM. Here is how full and linked clones differ, how to find every guest that depends on a base, and how to retire a template safely.

· 4 min read · proxmoxtemplateslinked cloneshomelab

Never delete this stopped Proxmox VM

Templates are one of Proxmox's best features. You build a base image once, and new guests come off it in seconds. They are also one of its quietest traps, because they create dependencies you cannot see in the guest list, and those dependencies bite on the day you tidy up.

This post is about that day: what a template really is to the guests built from it, how to prove whether one is load-bearing, and how to retire one without breaking anything.

Full clones vs linked clones

When you clone a template, Proxmox offers two modes:

  • Full clone: a complete, independent copy of the disk. Slower to create, uses more space, depends on nothing.
  • Linked clone: a thin copy that stores only the differences from the template's disk. Instant, tiny, and permanently tied to the template's base disk.

That last part is the whole story. A linked clone is not a copy of the template. It is a layer of changes sitting on top of it. Take away the bottom layer and the top layer has nothing to stand on.

You can see the relationship in the disk names. A template's disks are named like base-9000-disk-0, and a linked clone's config refers to that base, like this:

local-lvm:base-9000-disk-0/vm-105-disk-0

Read it left to right: VM 105's disk lives on top of template 9000's base disk.

The trap: "it's stopped, so it's junk"

Templates are always stopped. In a list of guests, a template looks exactly like an abandoned VM.

There is a nastier version too. A plain stopped container that was converted to a template, then used as the source for linked clones, looks like any other forgotten container. Nothing about it shouts "other guests need me".

Delete that base, and what happens depends on your storage:

StorageWhat happens when you delete the base
ZFS and some othersProxmox refuses, because the base still has dependents
File-based (qcow2 on a directory or NFS)The clones' backing file can simply vanish, and every linked clone built from it stops booting

Either way, you find out at the worst possible moment. The rule of thumb from the book: never delete a template, or anything named base-*, until you have proven nothing references it.

The fix, part 1: find every dependent

Every guest config lives in /etc/pve, so one grep tells you who depends on a base. For template 9000:

# Who uses template 9000's disks?
grep -rl "base-9000-" /etc/pve/nodes/*/qemu-server/ /etc/pve/nodes/*/lxc/

If the grep returns anything other than the template's own config, the template is load-bearing. Leave it, label it, and move on.

To see every template on the cluster in the first place:

# All templates on the cluster
grep -l "^template: 1" /etc/pve/nodes/*/qemu-server/*.conf \
  /etc/pve/nodes/*/lxc/*.conf

The fix, part 2: label the load-bearing guests

The cheapest fix in the whole chapter is a note and a tag. Write it in the guest's Notes field (the Summary tab), and add a keep tag:

qm set 9000 --tags "template,keep" \
  --description "BASE TEMPLATE. Linked clones depend on this. Do not delete."
pct set 9050 --tags "template,keep"

Tags show up as colored pills in the resource tree. A bright red keep tag stops a lot of 1 a.m. mistakes, and the note tells whoever is cleaning up why the guest is there.

The same idea carries into any cleanup script. The book's backup-before-delete loop skips templates outright before it touches anything:

grep -q "^template: 1" /etc/pve/{lxc,qemu-server}/$id.conf 2>/dev/null && \
  { echo "SKIP $id: template"; continue; }

The fix, part 3: untangle before you retire

Sometimes you really do want a template gone: it is old, its OS is out of date, and you have built a better one. You can retire it, but only after its linked clones stop needing it. That means turning each linked clone into a full, independent guest first.

The simplest way is a fresh full clone of each linked clone:

# VM: full, independent copy of linked clone 105 as 305
qm clone 105 305 --full 1 --name app-server
# Container: same idea
pct clone 205 405 --full 1 --hostname app-ct

Moving a disk to a different storage also writes a full copy:

qm disk move 105 scsi0 other-store --delete 1

For containers, pct move-volume does the same job.

Then work through it in order:

  1. Test the full clone.
  2. Retire the linked one.
  3. Rerun the dependents grep for that template.
  4. When it comes back with nothing but the template's own config, the template is finally safe to remove.

Deleting it is still a cleanup like any other: back it up, verify the archive, then destroy with purge.

Long-lived guests should be full clones

Linked clones are instant and tiny, which makes them tempting. But the book's checklist is clear: long-lived production guests should be full clones, so they depend on nothing and a future cleanup cannot pull the floor out from under them.

And because templates stick around, keep them fresh: rebuild or update them on a schedule, with a patched OS and current cloud-init, so new guests do not start life months behind.

Checklist

  • Every template is tagged keep, with a note saying what depends on it
  • You have grepped for base-<id>- before deleting anything that might be a base
  • Any cleanup script skips guests with template: 1 in their config
  • Long-lived production guests are full clones, not linked clones
  • Before retiring a template: full-clone (or disk-move) each linked clone, test it, retire the linked one, rerun the grep
  • Templates are rebuilt or updated on a schedule (patched OS, current cloud-init)

More articles