feat: add redundant root with EFI mirror setup guide
Covers disk formatting, BTRFS RAID1 conversion, fstab configuration, and the update-efi-mirror script with apt post-install hook setup. Includes a separate procedure for migrating to a new disk.
This commit is contained in:
parent
89e4bd519a
commit
b098c94e19
@ -10,6 +10,7 @@ This repository is structured into several key directories:
|
||||
- `scripts/library/`: Libraries used by Python scripts.
|
||||
- `venv_utils.py`: Utility functions for creating, activating, and managing Python virtual environments.
|
||||
- `change_case.py`: A script for renaming files and directories by changing their case.
|
||||
- `update-efi-mirror.sh`: Script for syncing a two drive EFI mirror.
|
||||
- `video_autoreduce.py`: A script for automatic resolution reduction of video files.
|
||||
- `video_autoreduce_rename.py`: A script for automated renaming of video files post resolution reduction.
|
||||
- `video_manage_audio.py`: A script for removing audio from video files.
|
||||
@ -27,6 +28,7 @@ This repository is structured into several key directories:
|
||||
- `pip-packaging.md`: Packaging and publishing Python projects with pip.
|
||||
- `ssh.md`: SSH configuration, key management, and tunneling tips.
|
||||
- `storage.md`: Storage tooling — smartctl, badblocks, dd, hdparm, fdisk, and fstab/mount management.
|
||||
- `update-efi-mirror.md`: Redundant root with EFI mirror setup guide.
|
||||
- `wordpress.md`: WordPress debugging and tips.
|
||||
|
||||
- **pages/other/**: Templates for other pages, such as the homepage of my Debian package repository. These are provided as inspiration and should not be used as-is.
|
||||
@ -40,6 +42,7 @@ This repository is structured into several key directories:
|
||||
|
||||
- **setups/**: A collection of markdown files containing notes on configuring servers, including:
|
||||
- `debian_setup_aptly.md`: Comprehensive guide for installing Aptly on Debian.
|
||||
- `debian_setup_dolibarr.md`: Comprehensive guide for installing Dolibarr on Debian.
|
||||
- `debian_setup_gitea.md`: Comprehensive guide for installing Gitea on Debian.
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
334
notes/update-efi-mirror.md
Normal file
334
notes/update-efi-mirror.md
Normal file
@ -0,0 +1,334 @@
|
||||
# Redundant Root with EFI Mirror
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Redundant Root with EFI Mirror](#redundant-root-with-efi-mirror)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Overview](#overview)
|
||||
- [Placeholders](#placeholders)
|
||||
- [How It Works](#how-it-works)
|
||||
- [Paths](#paths)
|
||||
- [Setup Procedure](#setup-procedure)
|
||||
- [1. Format the Disks](#1-format-the-disks)
|
||||
- [2. Convert the Root Filesystem to BTRFS RAID1](#2-convert-the-root-filesystem-to-btrfs-raid1)
|
||||
- [3. Configure fstab](#3-configure-fstab)
|
||||
- [4. Install the Sync Script](#4-install-the-sync-script)
|
||||
- [5. Configure apt to Run the Script Post-Install](#5-configure-apt-to-run-the-script-post-install)
|
||||
- [6. Test](#6-test)
|
||||
- [Moving to a New Disk](#moving-to-a-new-disk)
|
||||
|
||||
## Overview
|
||||
|
||||
This setup provides a redundant Debian root drive using BTRFS RAID1 across two disks, with a synced EFI partition on both so the machine can boot from either. The script `update-efi-mirror` keeps the backup EFI in sync and re-installs GRUB on both physical disks. It is triggered automatically after every `apt` operation.
|
||||
|
||||
## Placeholders
|
||||
|
||||
Replace the placeholders below with the appropriate values for your setup:
|
||||
|
||||
- **Devices**
|
||||
- Primary disk: `<primary-disk>` (e.g., /dev/sda, /dev/nvme0n1)
|
||||
- Backup disk: `<backup-disk>` (e.g., /dev/sdb, /dev/nvme1n1)
|
||||
- Primary EFI partition: `<primary-efi-part>` (e.g., /dev/sda1, /dev/nvme0n1p1)
|
||||
- Backup EFI partition: `<backup-efi-part>` (e.g., /dev/sdb1, /dev/nvme1n1p1)
|
||||
- Primary root partition: `<primary-root-part>` (e.g., /dev/sda2, /dev/nvme0n1p2)
|
||||
- Backup root partition: `<backup-root-part>` (e.g., /dev/sdb2, /dev/nvme1n1p2)
|
||||
- Primary swap partition: `<primary-swap-part>` (e.g., /dev/sda3, /dev/nvme0n1p3)
|
||||
- Backup swap partition: `<backup-swap-part>` (e.g., /dev/sdb3, /dev/nvme1n1p3)
|
||||
|
||||
- **UUIDs**
|
||||
- Primary EFI UUID: `<primary-efi-uuid>` (e.g., D167-0F46)
|
||||
- Backup EFI UUID: `<backup-efi-uuid>` (e.g., 08E8-A87C)
|
||||
- Root BTRFS UUID: `<root-uuid>` (e.g., 387526ec-f3bd-4fa8-a17e-e985121ada0b)
|
||||
- Primary swap UUID: `<primary-swap-uuid>`
|
||||
- Backup swap UUID: `<backup-swap-uuid>`
|
||||
|
||||
## How It Works
|
||||
|
||||
- The root filesystem is BTRFS RAID1 across two partitions. Either disk alone can serve reads and writes.
|
||||
- Each disk has its own EFI partition. GRUB is installed on both physical disks.
|
||||
- After every `apt` install or upgrade, an apt hook calls `update-efi-mirror`, which:
|
||||
1. Rsyncs the live `/boot/efi` to the backup EFI partition.
|
||||
2. Runs `grub-install` on both physical disks.
|
||||
- Either disk can be removed and the system will still boot and run.
|
||||
|
||||
## Paths
|
||||
|
||||
- **Sync script**: `/usr/local/sbin/update-efi-mirror`
|
||||
- **Apt hook**: `/etc/apt/apt.conf.d/99-update-efi-mirror`
|
||||
- **fstab**: `/etc/fstab`
|
||||
|
||||
## Setup Procedure
|
||||
|
||||
### 1. Format the Disks
|
||||
|
||||
**Verify which disks are present before touching anything**
|
||||
|
||||
```bash
|
||||
lsblk
|
||||
lsblk -f
|
||||
```
|
||||
|
||||
**Open `fdisk` on the backup disk**
|
||||
|
||||
If the disk was previously used at a smaller capacity, the GPT backup table may be misaligned — `fdisk` will correct it on write.
|
||||
|
||||
```bash
|
||||
fdisk <backup-disk>
|
||||
```
|
||||
|
||||
Create a GPT partition table if not already present:
|
||||
|
||||
```
|
||||
g
|
||||
```
|
||||
|
||||
**Check the primary disk partition layout and note the exact sector boundaries**
|
||||
|
||||
```bash
|
||||
fdisk -l <primary-disk>
|
||||
```
|
||||
|
||||
This shows the `Start` and `End` sectors for each partition. Use these values when partitioning the backup disk so the layouts match exactly.
|
||||
|
||||
**Create the three partitions to match the layout of the primary disk**
|
||||
|
||||
| # | Size | Type |
|
||||
| --- | --------- | ---------- |
|
||||
| 1 | 830M | EFI System |
|
||||
| 2 | ~12G | Linux fs |
|
||||
| 3 | Remainder | Linux swap |
|
||||
|
||||
Inside `fdisk`, the sequence is:
|
||||
|
||||
```
|
||||
n # new partition
|
||||
# enter the exact End sector from the primary disk to match partition sizes
|
||||
t # change type
|
||||
1 # select partition 1
|
||||
EFI System # set type to EFI
|
||||
t # change type
|
||||
3 # select partition 3
|
||||
Linux swap # set type to swap
|
||||
w # write and exit
|
||||
```
|
||||
|
||||
**Partition sizes must be at least as large as the corresponding primary partition** — the BTRFS replace will fail if the target partition is smaller than the source.
|
||||
|
||||
**Format the new EFI partition**
|
||||
|
||||
```bash
|
||||
apt install dosfstools # if not installed
|
||||
mkfs.fat -F32 <backup-efi-part>
|
||||
```
|
||||
|
||||
**Format the new swap partition**
|
||||
|
||||
```bash
|
||||
mkswap <backup-swap-part>
|
||||
```
|
||||
|
||||
**Check UUIDs of the new partitions**
|
||||
|
||||
```bash
|
||||
lsblk -f <backup-disk>
|
||||
```
|
||||
|
||||
### 2. Convert the Root Filesystem to BTRFS RAID1
|
||||
|
||||
**Add the backup partition to the BTRFS volume**
|
||||
|
||||
```bash
|
||||
btrfs device add <backup-root-part> /
|
||||
```
|
||||
|
||||
**Convert to RAID1**
|
||||
|
||||
```bash
|
||||
btrfs balance start -mconvert=raid1 -dconvert=raid1 /
|
||||
```
|
||||
|
||||
Monitor the balance:
|
||||
|
||||
```bash
|
||||
btrfs balance status /
|
||||
```
|
||||
|
||||
**Verify the final layout**
|
||||
|
||||
```bash
|
||||
btrfs filesystem show /
|
||||
btrfs fi usage /
|
||||
```
|
||||
|
||||
### 3. Configure fstab
|
||||
|
||||
Edit `/etc/fstab` to mount the primary EFI partition normally and document the backup EFI UUID in a commented-out entry. The script reads the backup UUID from this comment.
|
||||
|
||||
**Edit fstab**
|
||||
|
||||
```bash
|
||||
nano /etc/fstab
|
||||
```
|
||||
|
||||
The fstab should contain:
|
||||
|
||||
```
|
||||
# Primary EFI — mounted at boot
|
||||
UUID=<primary-efi-uuid> /boot/efi vfat umask=0077 0 1
|
||||
|
||||
# Backup EFI — not auto-mounted, used by update-efi-mirror
|
||||
#UUID=<backup-efi-uuid> /boot/efi vfat umask=0077 0 1
|
||||
|
||||
# Root — BTRFS RAID1 (both partitions share the same UUID)
|
||||
UUID=<root-uuid> / btrfs defaults,noatime 0 1
|
||||
|
||||
# Swap — both disks
|
||||
UUID=<primary-swap-uuid> none swap sw 0 0
|
||||
UUID=<backup-swap-uuid> none swap sw 0 0
|
||||
```
|
||||
|
||||
The backup EFI line must start with `#UUID=` — this is the format the script greps for:
|
||||
|
||||
```bash
|
||||
grep "^#UUID=" /etc/fstab | grep "/boot/efi"
|
||||
```
|
||||
|
||||
**Reload systemd after editing fstab**
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
```
|
||||
|
||||
### 4. Install the Sync Script
|
||||
|
||||
**Create the script**
|
||||
|
||||
```bash
|
||||
nano /usr/local/sbin/update-efi-mirror
|
||||
```
|
||||
|
||||
Paste the contents of `update-efi-mirror.sh`.
|
||||
|
||||
**Set ownership and permissions**
|
||||
|
||||
```bash
|
||||
chown root:root /usr/local/sbin/update-efi-mirror
|
||||
chmod 755 /usr/local/sbin/update-efi-mirror
|
||||
```
|
||||
|
||||
The script will:
|
||||
|
||||
1. Detect the currently mounted EFI partition and its disk.
|
||||
2. Read the backup EFI UUID from the `#UUID=` comment in `/etc/fstab`.
|
||||
3. Mount the backup EFI to a temp directory, rsync all files from the live EFI, then unmount.
|
||||
4. Run `grub-install --recheck` on both physical disks.
|
||||
|
||||
### 5. Configure apt to Run the Script Post-Install
|
||||
|
||||
**Create the apt hook**
|
||||
|
||||
```bash
|
||||
nano /etc/apt/apt.conf.d/99-update-efi-mirror
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```
|
||||
DPkg::Post-Invoke {"if [ -x /usr/local/sbin/update-efi-mirror ]; then /usr/local/sbin/update-efi-mirror; fi";};
|
||||
```
|
||||
|
||||
This runs the sync script after every `apt` operation that invokes `dpkg` — including kernel upgrades, which update `/boot/efi` with new initramfs and GRUB config.
|
||||
|
||||
### 6. Test
|
||||
|
||||
**Run the script manually**
|
||||
|
||||
```bash
|
||||
/usr/local/sbin/update-efi-mirror
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
Syncing EFI files: <primary-efi-uuid> -> <backup-efi-uuid>
|
||||
EFI Files Sync Complete.
|
||||
Updating GRUB bootloader on both physical disks...
|
||||
Redundancy Complete: Files synced and GRUB updated on <primary-disk> and <backup-disk>.
|
||||
```
|
||||
|
||||
**Test the apt hook**
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade -y
|
||||
```
|
||||
|
||||
The sync output should appear at the end of the upgrade, after GRUB regenerates its config.
|
||||
|
||||
**Verify the backup EFI contents match**
|
||||
|
||||
```bash
|
||||
TMPMNT=$(mktemp -d)
|
||||
mount -U <backup-efi-uuid> "$TMPMNT"
|
||||
diff -r /boot/efi/ "$TMPMNT/"
|
||||
umount "$TMPMNT"
|
||||
rmdir "$TMPMNT"
|
||||
```
|
||||
|
||||
**Verify GRUB is installed on both disks**
|
||||
|
||||
```bash
|
||||
fdisk -l <primary-disk> | grep -i efi
|
||||
fdisk -l <backup-disk> | grep -i efi
|
||||
```
|
||||
|
||||
**`Optional` Boot from the backup disk**
|
||||
|
||||
Swap the boot order in BIOS/UEFI to confirm the machine boots cleanly from `<backup-disk>`.
|
||||
|
||||
## Moving to a New Disk
|
||||
|
||||
Use this procedure when replacing one of the two disks in the BTRFS RAID1 — for example when upgrading to a larger drive.
|
||||
|
||||
**1. Partition the new disk** following [Step 1](#1-format-the-disks).
|
||||
|
||||
**2. Find the device ID of the partition to be replaced:**
|
||||
|
||||
```bash
|
||||
btrfs filesystem show /
|
||||
```
|
||||
|
||||
**3. Shrink the filesystem on the disk being replaced to fit the new partition:**
|
||||
|
||||
```bash
|
||||
btrfs filesystem resize <device-id>:<size> /
|
||||
```
|
||||
|
||||
**4. Replace the old partition with the new one:**
|
||||
|
||||
```bash
|
||||
btrfs replace start <device-id> <new-root-part> /
|
||||
btrfs replace status /
|
||||
```
|
||||
|
||||
**5. Grow the new partition to max:**
|
||||
|
||||
```bash
|
||||
btrfs filesystem resize <device-id>:max /
|
||||
```
|
||||
|
||||
**6. Update fstab** if the backup EFI UUID has changed (new disk = new EFI UUID):
|
||||
|
||||
```bash
|
||||
lsblk -f <new-disk>
|
||||
nano /etc/fstab
|
||||
systemctl daemon-reload
|
||||
```
|
||||
|
||||
**7. Run the sync script** to install GRUB on the new disk and populate its EFI partition:
|
||||
|
||||
```bash
|
||||
/usr/local/sbin/update-efi-mirror
|
||||
```
|
||||
|
||||
**8. Verify** following [Step 6](#6-test).
|
||||
Loading…
Reference in New Issue
Block a user