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
Structure
Lost when
Captured by
Partition table
Disk replaced, table overwritten
sfdisk --dump, sgdisk --backup
LVM metadata
PV header damaged, VG not importable
/etc/lvm/backup/, vgcfgbackup
Software RAID config
Array not assembled on a new host
mdadm --detail --scan
LUKS header
Header overwritten - data unrecoverable
cryptsetup luksHeaderBackup
Filesystem geometry
Restore target built with wrong sector or stripe size
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— --dump reads the table and writes nothing. The output records start sector, size, partition type GUID and partition UUID for each entry, plus the sector size the table was written against. That last line is why the dump belongs in the disaster-recovery bundle: a replacement disk with a different logical sector size cannot take this layout as-is, and the dump is where you find that out before you have restored 4 TB into it.
Read-only / Safebinary GPT backup— --backup writes the protective MBR, both GPT headers and the partition table to a file. Note that man 8 sgdisk says the backup reflects the CURRENT IN-MEMORY table, so if the on-disk structures are already damaged the backup may record a repaired version rather than the damage. Take these backups while the disk is healthy, not during the incident. --verify reports problems and corrects nothing.
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— vgcfgbackup rewrites /etc/lvm/backup/<vg> from the current metadata. It touches no volume and no data - it writes one text file. The two UUIDs are the reason this file matters: they are how a PV whose on-disk header is damaged can be re-created with its original identity rather than as a new, empty PV.
$ 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 metadatagrep -A3 'physical_volumes' /etc/lvm/backup/vg0# 2. recreate the PV header with that identity, on the right devicesudo pvcreate --uuid Tz5Wq8-Nb1L-Rk3X-cV7m-Jd2P-oU9s-Ay6Fe4 \ --restorefile /etc/lvm/backup/vg0 /dev/sda2# 3. put the volume group metadata backsudo vgcfgrestore --list vg0sudo vgcfgrestore -f /etc/lvm/backup/vg0 vg0sudo 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— Reads the LUKS header and keyslot area and writes it to a file. The device is not modified. Take one at LUKS creation time and again after every keyslot change, because a header backup taken before a keyslot was added does not contain that keyslot. Verify the file with 'sudo cryptsetup luksDump --header /root/dr/sda3-luks-header.img' which prints the keyslots it actually contains.
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 lists packages an operator asked for, excluding the hundreds pulled in as dependencies. That distinction is what makes the list usable: reinstalling 147 manual packages reproduces the host, while replaying a full dpkg --get-selections of 1400 entries reproduces the exact dependency state of a distribution version that may no longer exist. On RHEL-family hosts the equivalent is 'dnf repoquery --userinstalled --qf %{name}'.
$ apt-mark showmanual | tee /root/dr/packages-manual.txt | wc -l
147
Illustrative output
Package selection: apt-mark showmanual, or dnf repoquery --userinstalled. The deliberate set, not the dependency closure.
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.
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.
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.
Kernel command line and boot config: cat /proc/cmdline, plus /etc/default/grub. Anything set there is invisible to a filesystem restore of /.
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
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?
Q2. Removing a keyslot with cryptsetup luksKillSlot revokes that passphrase everywhere, including in header backups taken earlier.
Q3. Which of these belong in a structural-metadata capture that runs from cron on a production host? Select all that apply.
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.