Skip to main content
RunBook Academy

LinuxXLVII · Backup StrategyStructural metadata

Backing up what is not a file - partition tables, LVM metadata, LUKS headers and package state

Advanced⏱ ~18 minbashsfdisksgdiskvgcfgbackupcryptsetup

What you'll learn

  • Enumerate the structural metadata a file-level backup does not capture
  • Capture partition tables with sfdisk --dump and sgdisk --backup
  • Capture and restore LVM metadata, including recovering a lost PV header
  • Back up a LUKS header and handle it with the security consequences that follow
  • Record package selection, repository configuration and enabled unit state

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-11

Not yet marked complete on this device.

A file-level backup captures files. That is the whole of its job and it does it well. What it cannot capture is the structure those files were living in, because none of that structure is a file: where the partitions started, which physical volumes made up the volume group, which keyslot held the master key, which packages were installed and from which repositories, and the fact that /var/lib/mysql was a separate filesystem rather than a directory.

None of that is missed during the backup. All of it is missed during the rebuild, at the point where you have a blank disk, a restore archive, and no idea what shape to put the disk in before the archive can go back.

The inventory

StructureLost whenCaptured by
Partition tableDisk replaced, table overwrittensfdisk --dump, sgdisk --backup
LVM metadataPV header damaged, VG not importable/etc/lvm/backup/, vgcfgbackup
Software RAID configArray not assembled on a new hostmdadm --detail --scan
LUKS headerHeader overwritten - data unrecoverablecryptsetup luksHeaderBackup
Filesystem geometryRestore target built with wrong sector or stripe sizexfs_info, tune2fs -l
Mount topologyRestore lands one filesystem where three belong/etc/fstab, findmnt
Package selectionRebuilt host missing half its softwareapt-mark showmanual, dnf repoquery --userinstalled
Repository and key configPackages cannot be reinstalled at all/etc/apt/, /etc/yum.repos.d/
Enabled unit stateServices restored but not starting at bootsystemctl list-unit-files --state=enabled

Every capture below writes to a file, never to a device. All of them are safe on a live production host.

Partition tables

Two formats, and you want both. sfdisk --dump produces text you can read, review in a diff, and reason about six months later. sgdisk --backup produces a binary image of the protective MBR, both GPT headers and one copy of the partition table.

Read-only / Safehuman-readable partition backup
$ sudo sfdisk --dump /dev/sda
label: gpt
label-id: 4A1C8E2F-7B3D-4E56-9A01-2C3D4E5F6A7B
device: /dev/sda
unit: sectors
first-lba: 34
last-lba: 268435422
sector-size: 512

/dev/sda1 : start=        2048, size=     2097152, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=1B2C3D4E-..., name="EFI System Partition"
/dev/sda2 : start=     2099200, size=   266334208, type=E6D6D379-F507-44C2-A23C-238F2A3DF928, uuid=5F6A7B8C-..., name="lvm"

Illustrative output

Read-only / Safebinary GPT backup
$ sudo sgdisk --backup=/root/dr/sda-gpt.bin /dev/sda && sudo sgdisk --verify /dev/sda
The operation has completed successfully.
No problems found. 32 free sectors (16.0 KiB) available in 1
segments, the largest of which is 32 (16.0 KiB) in size.

Illustrative output

LVM metadata

LVM keeps this one for you. Every change to a volume group writes a new text copy of its metadata into /etc/lvm/backup/, and the previous versions into /etc/lvm/archive/. Backing up /etc therefore captures it - as long as somebody knows that is what those files are for.

Configuration changeforce a fresh metadata backup
$ sudo vgcfgbackup && head -20 /etc/lvm/backup/vg0
  Volume group "vg0" successfully backed up.
# Generated by LVM2 version 2.03.16(2)

contents = "Text Format Volume Group"
version = 1
description = "Created *after* executing 'lvextend -L +50G vg0/data'"

vg0 {
id = "kR3aZ1-9Xc2-Qw8T-mN4v-Lp6B-hY0d-Ke7Rs2"
seqno = 14
physical_volumes {
pv0 {
id = "Tz5Wq8-Nb1L-Rk3X-cV7m-Jd2P-oU9s-Ay6Fe4"
device = "/dev/sda2"
}
}
}

Illustrative output

The recovery this enables is the one worth rehearsing. A PV header damaged by a stray pvcreate, a dd to the wrong device, or a controller that wrote garbage leaves a volume group that will not activate because one of its members is unrecognisable. With the metadata file, the PV can be re-created with its original UUID and the group restored:

# 1. find the original PV UUID in the saved metadata
grep -A3 'physical_volumes' /etc/lvm/backup/vg0

# 2. recreate the PV header with that identity, on the right device
sudo pvcreate --uuid Tz5Wq8-Nb1L-Rk3X-cV7m-Jd2P-oU9s-Ay6Fe4 \
  --restorefile /etc/lvm/backup/vg0 /dev/sda2

# 3. put the volume group metadata back
sudo vgcfgrestore --list vg0
sudo vgcfgrestore -f /etc/lvm/backup/vg0 vg0
sudo vgchange -ay vg0

Steps 2 and 3 write LVM metadata to the device. They are recovery operations, not maintenance, and they belong in a runbook with the same care as a restore. vgcfgrestore --list first, always - it enumerates the available backup and archive files so you restore the version you meant rather than the most recent one, which may be the one that recorded the damage.

LUKS headers

The LUKS header holds the wrapped master key. The passphrase does not decrypt the data; it decrypts a keyslot, which yields the master key, which decrypts the data. Overwrite the header and the data is cryptographically gone - the correct passphrase is worth nothing without the keyslot it unlocks.

Configuration changeheader backup
$ sudo cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file /root/dr/sda3-luks-header.img

Package state, repositories and enabled units

A restored /etc and /var on a freshly installed OS is not the same host. The binaries came from packages, the packages came from repositories, and the services were enabled by symlinks that a file restore may or may not have carried.

Read-only / Safewhat was installed deliberately
$ apt-mark showmanual | tee /root/dr/packages-manual.txt | wc -l
147

Illustrative output

  1. Package selection: apt-mark showmanual, or dnf repoquery --userinstalled. The deliberate set, not the dependency closure.
  2. Repository configuration and signing keys: /etc/apt/sources.list, /etc/apt/sources.list.d/, /etc/apt/keyrings/ - or /etc/yum.repos.d/ and /etc/pki/rpm-gpg/. Without these the package list cannot be replayed at all.
  3. Enabled units: systemctl list-unit-files --state=enabled --no-legend. A restored unit file that was never enabled does not start at boot, and this is the check that catches it.
  4. Masked units too: systemctl list-unit-files --state=masked. A service deliberately masked on the old host will start on the rebuilt one unless the mask is reproduced.
  5. Kernel command line and boot config: cat /proc/cmdline, plus /etc/default/grub. Anything set there is invisible to a filesystem restore of /.
  6. sysctl settings: sysctl -a is the running state, /etc/sysctl.d/ is the intent. Capture the directory; capture the running state as evidence.

Knowledge check

Knowledge check · 4 questions

  1. Q1. A volume group will not activate because one PV header was overwritten. The file-level backup of /etc is intact. What makes recovery possible?

  2. Q2. Removing a keyslot with cryptsetup luksKillSlot revokes that passphrase everywhere, including in header backups taken earlier.

  3. Q3. Which of these belong in a structural-metadata capture that runs from cron on a production host? Select all that apply.

  4. Q4. You restore /etc and /var onto a freshly installed host from a complete file-level backup. Services are present but several do not start after a reboot. What was most likely missed?

Passing score: 75%. Answers are checked in this browser.