From 1d424bd197e4798832d89c0b0913e84612d30d96 Mon Sep 17 00:00:00 2001 From: Djeex Date: Fri, 11 Jul 2025 16:35:14 +0000 Subject: [PATCH] Script backup luks header --- content/5.nonsense/1.bash.md | 81 +++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/content/5.nonsense/1.bash.md b/content/5.nonsense/1.bash.md index f704422..3118abc 100644 --- a/content/5.nonsense/1.bash.md +++ b/content/5.nonsense/1.bash.md @@ -144,4 +144,83 @@ So, in conclusion, I: - Learned that Qwen on a RTX 5090 is more coherent than ChatGPT-4o on server farms (not even mentioning โ€œnormalโ€ ChatGPT) - Learned that even with 100TB of storage, monitoring it wouldโ€™ve alerted me much earlier to the 12TB of duplicates lying around -Catch you next time for more exciting adventures. +## Backup of LUKS Headers for Encrypted Disks/Volumes +--- + +I recently realized that having just the password is not enough to unlock a LUKS volume after a failure or corruption. I learned how to dump the LUKS headers from disks/volumes and to use the serial numbers along with partition names to accurately identify which header corresponds to which disk/partition (I have 10 of them!). + +After struggling to do this manually, I asked Qwen3 (an LLM running on my RTX 5090) to create a script that automates the listing and identification of disks, dumps the headers, and stores them in an encrypted archive ready to be backed up on my backup server. + +This script: +* Lists and identifies disks with their serial numbers +* Lists partitions +* Dumps headers into a secured folder under `/root` +* Creates a temporary archive +* Prompts for a password +* Encrypts the archive with that password +* Deletes the unencrypted archive + +```bash +#!/bin/bash + +# Directory where LUKS headers will be backed up +DEST="/root/luks-headers-backup" +mkdir -p "$DEST" + +echo "๐Ÿ” Searching for LUKS containers on all partitions..." + +# Loop through all possible disk partitions (including NVMe and SATA) +for part in /dev/sd? /dev/sd?? /dev/nvme?n?p?; do + # Skip if the device doesn't exist + if [ ! -b "$part" ]; then + continue + fi + + # Check if the partition is a LUKS encrypted volume + if cryptsetup isLuks "$part"; then + # Find the parent disk device (e.g. nvme0n1p4 โ†’ nvme0n1) + disk=$(lsblk -no pkname "$part" | head -n 1) + full_disk="/dev/$disk" + + # Get the serial number of the parent disk + SERIAL=$(udevadm info --query=all --name="$full_disk" | grep ID_SERIAL= | cut -d= -f2) + if [ -z "$SERIAL" ]; then + SERIAL="unknown" + fi + + # Extract the partition name (e.g. nvme0n1p4) + PART_NAME=$(basename "$part") + + # Build the output filename with partition name and disk serial + OUTPUT="$DEST/luks-header-${PART_NAME}__${SERIAL}.img" + + echo "๐Ÿ” Backing up LUKS header of $part (Serial: $SERIAL)..." + + # Backup the LUKS header to the output file + cryptsetup luksHeaderBackup "$part" --header-backup-file "$OUTPUT" + if [[ $? -eq 0 ]]; then + echo "โœ… Backup successful โ†’ $OUTPUT" + else + echo "โŒ Backup failed for $part" + fi + fi +done + +# Create a timestamped compressed tar archive of all header backups +ARCHIVE_NAME="/root/luks-headers-$(date +%Y%m%d_%H%M%S).tar.gz" +echo "๐Ÿ“ฆ Creating archive $ARCHIVE_NAME..." +tar -czf "$ARCHIVE_NAME" -C "$DEST" . + +# Encrypt the archive symmetrically using GPG with AES256 cipher +echo "๐Ÿ” Encrypting the archive with GPG..." +gpg --symmetric --cipher-algo AES256 "$ARCHIVE_NAME" +if [[ $? -eq 0 ]]; then + echo "โœ… Encrypted archive created: ${ARCHIVE_NAME}.gpg" + # Remove the unencrypted archive for security + rm -f "$ARCHIVE_NAME" +else + echo "โŒ Encryption failed" +fi +``` + +**Donโ€™t forget to back up `/etc/fstab` and `/etc/crypttab` as well!**