first commit

This commit is contained in:
Marko Oldenburg 2025-04-30 08:23:38 +02:00
commit f6c25300f1
3 changed files with 254 additions and 0 deletions

83
README.md Normal file
View File

@ -0,0 +1,83 @@
# uefi-copy-with-grub
Copy EFI (UEFI) partition to another partition when grub updates
## Use Case
Having multiple RAID partitions, the Debian installer (don't know about other installers) will only install the UEFI files on one partition. Syncing the files to other disks is your task. The script in this repository can be hooked into `grub`, and automate this task.
## Usage
Find out which partition(s) are used for UEFI:
```
# fdisk -l /dev/sda
Disk /dev/sda: 447,13 GiB, 480103981056 bytes, 937703088 sectors
Disk model: INTEL SSDSC2KB48
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 625E2045-9BED-4A0C-9759-262C3B6C94A4
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 1054719 1050624 513M EFI System
/dev/sda3 1054720 2031615 976896 477M Linux RAID
/dev/sda4 2031616 935624703 933593088 445,2G Linux RAID
/dev/sda5 935624704 937701375 2076672 1014M Linux RAID
# fdisk -l /dev/sdb
Disk /dev/sdb: 447,13 GiB, 480103981056 bytes, 937703088 sectors
Disk model: INTEL SSDSC2KB48
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: B548B9AC-CB03-4B0A-B358-AAC0AF4529BA
Device Start End Sectors Size Type
/dev/sdb1 2048 4095 2048 1M BIOS boot
/dev/sdb2 4096 1054719 1050624 513M EFI System
/dev/sdb3 1054720 2031615 976896 477M Linux RAID
/dev/sdb4 2031616 935624703 933593088 445,2G Linux RAID
/dev/sdb5 935624704 937701375 2076672 1014M Linux RAID
```
The partitions `/dev/sda2` and `/dev/sdb2` are the EFI partitions.
Copy the script in `templates/copy_to_boot_efi2.sh` to `/etc/grub.d/90_copy_to_boot_efi2`, add your partitions in line *9* and *10* and remove the `exit 1` in line *13* (safety measure). Then run `update-grub`. You can also run the script manually.
## Deploy using Ansible
I'm using an Ansible Playbook to deploy this script on my server:
```
- hosts: all
become: yes
any_errors_fatal: True
vars:
raid_disk_first: "sdb2"
raid_disk_second: "sda2"
tasks:
- name: rsync packages
ansible.builtin.apt:
name:
- rsync
state: present
- name: Upload copy_to_boot_efi2.sh
ansible.builtin.template:
src: "copy_to_boot_efi2.j2"
dest: "/etc/grub.d/90_copy_to_boot_efi2"
owner: "root"
group: "root"
mode: "0700"
```
This will replace the placeholders in `copy_to_boot_efi2.j2` and place the script in `/etc/grub.d/`. Run `update-grub` afterwards.
## More information
See this blog posting: [Debian Bookworm auf einem Software-RAID und EFI installieren](https://www.cooltux.net/doku.php?id=it-wiki:linux:install_debian_bookworm_on_a_software_raid_and_efi).

View File

@ -0,0 +1,84 @@
#!/bin/bash
set -e # abort on error
set -u # abort on variable not set
#set -x # trace execution
# one or both devices can already be mounted, potentially with a label and not with the device name
device_first="/dev/{{ raid_disk_first }}"
device_second="/dev/{{ raid_disk_second }}"
# the findmnt will fail when the device is not mounted, that is expected
set +e
mountpoint_first=`/usr/bin/findmnt --first-only --noheadings --output=TARGET ${device_first}`
mountpoint_second=`/usr/bin/findmnt --first-only --noheadings --output=TARGET ${device_second}`
set -e
if [ -z "${mountpoint_first}" ];
then
# not mounted, create the mount point
path_first="/efi-first"
/usr/bin/mkdir "${path_first}"
echo "No existing mount point found for ${device_first}"
echo " Mounting on ${path_first}"
# and mount the decive
/usr/bin/mount "${device_first}" "${path_first}"
else
# already mounted, use the existing mount point
path_first="${mountpoint_first}"
echo "Found existing mount point ${mountpoint_first} for device ${device_first}"
fi
if [ -z "${mountpoint_second}" ];
then
# not mounted, create the mount point
path_second="/efi-second"
/usr/bin/mkdir "${path_second}"
echo "No existing mount point found for ${device_second}"
echo " Mounting on ${path_second}"
# and mount the decive
/usr/bin/mount "${device_second}" "${path_second}"
else
# already mounted, use the existing mount point
path_second="${mountpoint_second}"
echo "Found existing mount point ${mountpoint_second} for device ${device_second}"
fi
if [ ! -d "${path_first}/EFI" -a -d "${path_second}/EFI" ];
then
# there's an "EFI" directory in the second mount point,
# but not in the first one - this is wrong, and will damage
# the installation once rsync runs
echo "There is no 'EFI' directory in the first (source) mount point!"
echo "But there is an 'EFI' directory in the second (destination) mount point!"
echo "This will not work, possibly switch the devices!"
echo "Source: ${device_first} (mounted on: ${path_first})"
echo "Destination: ${device_second} (mounted on: ${path_second})"
exit 1
fi
#echo "rsync --dry-run --verbose --times --recursive --delete \"${path_first}/\" \"${path_second}/\""
#rsync --dry-run --verbose --times --recursive --delete "${path_first}/" "${path_second}/"
rsync --verbose --times --recursive --delete "${path_first}/" "${path_second}/"
if [ -z "${mountpoint_first}" ];
then
# unmount the device
/usr/bin/umount "${path_first}"
# remove the directory
/usr/bin/rmdir "${path_first}"
fi
if [ -z "${mountpoint_second}" ];
then
# unmount the device
/usr/bin/umount "${path_second}"
# remove the directory
/usr/bin/rmdir "${path_second}"
fi
exit 0

View File

@ -0,0 +1,87 @@
#!/bin/bash
set -e # abort on error
set -u # abort on variable not set
#set -x # trace execution
# one or both devices can already be mounted, potentially with a label and not with the device name
device_first="/dev/sda2" # FIXME: replace with your partition name and number
device_second="/dev/sdb2" # FIXME: replace with your partition name and number
# FIXME: remove the following exit once you setup the above partitions
exit 1
# the findmnt will fail when the device is not mounted, that is expected
set +e
mountpoint_first=`/usr/bin/findmnt --first-only --noheadings --output=TARGET ${device_first}`
mountpoint_second=`/usr/bin/findmnt --first-only --noheadings --output=TARGET ${device_second}`
set -e
if [ -z "${mountpoint_first}" ];
then
# not mounted, create the mount point
path_first="/efi-first"
/usr/bin/mkdir "${path_first}"
echo "No existing mount point found for ${device_first}"
echo " Mounting on ${path_first}"
# and mount the decive
/usr/bin/mount "${device_first}" "${path_first}"
else
# already mounted, use the existing mount point
path_first="${mountpoint_first}"
echo "Found existing mount point ${mountpoint_first} for device ${device_first}"
fi
if [ -z "${mountpoint_second}" ];
then
# not mounted, create the mount point
path_second="/efi-second"
/usr/bin/mkdir "${path_second}"
echo "No existing mount point found for ${device_second}"
echo " Mounting on ${path_second}"
# and mount the decive
/usr/bin/mount "${device_second}" "${path_second}"
else
# already mounted, use the existing mount point
path_second="${mountpoint_second}"
echo "Found existing mount point ${mountpoint_second} for device ${device_second}"
fi
if [ ! -d "${path_first}/EFI" -a -d "${path_second}/EFI" ];
then
# there's an "EFI" directory in the second mount point,
# but not in the first one - this is wrong, and will damage
# the installation once rsync runs
echo "There is no 'EFI' directory in the first (source) mount point!"
echo "But there is an 'EFI' directory in the second (destination) mount point!"
echo "This will not work, possibly switch the devices!"
echo "Source: ${device_first} (mounted on: ${path_first})"
echo "Destination: ${device_second} (mounted on: ${path_second})"
exit 1
fi
#echo "rsync --dry-run --verbose --times --recursive --delete \"${path_first}/\" \"${path_second}/\""
#rsync --dry-run --verbose --times --recursive --delete "${path_first}/" "${path_second}/"
rsync --verbose --times --recursive --delete "${path_first}/" "${path_second}/"
if [ -z "${mountpoint_first}" ];
then
# unmount the device
/usr/bin/umount "${path_first}"
# remove the directory
/usr/bin/rmdir "${path_first}"
fi
if [ -z "${mountpoint_second}" ];
then
# unmount the device
/usr/bin/umount "${path_second}"
# remove the directory
/usr/bin/rmdir "${path_second}"
fi
exit 0