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.
|
- `scripts/library/`: Libraries used by Python scripts.
|
||||||
- `venv_utils.py`: Utility functions for creating, activating, and managing Python virtual environments.
|
- `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.
|
- `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.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_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.
|
- `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.
|
- `pip-packaging.md`: Packaging and publishing Python projects with pip.
|
||||||
- `ssh.md`: SSH configuration, key management, and tunneling tips.
|
- `ssh.md`: SSH configuration, key management, and tunneling tips.
|
||||||
- `storage.md`: Storage tooling — smartctl, badblocks, dd, hdparm, fdisk, and fstab/mount management.
|
- `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.
|
- `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.
|
- **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:
|
- **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_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.
|
- `debian_setup_gitea.md`: Comprehensive guide for installing Gitea on Debian.
|
||||||
|
|
||||||
## 📖 Documentation
|
## 📖 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