linuxmint / timeshift

System restore tool for Linux. Creates filesystem snapshots using rsync+hardlinks, or BTRFS snapshots. Supports scheduled snapshots, multiple backup levels, and exclude filters. Snapshots can be restored while system is running or from Live CD/USB.
2.39k stars 86 forks source link

Custom Timeshift post restore hooks to rebuild UKI not working (UKI not syncing with snapshots) + method to retrieve snapshot's directory in restore hook scripts #216

Open Rend0e opened 1 year ago

Rend0e commented 1 year ago

Describe the bug Since unified kernel image (UKI) is stored in ESP, it will not be snapshoted under @ which causes issues when restoring to BtrFs snapshots on older kernel versions. This ends up requring a chroot (rebuild UKI via mkinitcpio -P) to fix the boot every time snapshots are restored from different kernel versions. I believe this also affects some systemd-boot setup if ESP is not mounted to /boot in order to snapshot boot files within @, initrd and pacman hooks are used to sync /boot files to esp on initramfs rebuilds or kernel/ucode updates in that setup.

To address this issue, the ideal way would be to automatically rebuild the snapshot's UKI into ESP right after restoring the snapshot. _For systemd-boot setup, it would need to copy the @snapshotlocation/boot files to esp. The README page mentions Post Restore Hooks:

Scripts can be run at the end of a restore job for anything that may need to be done prior to rebooting. The location for these scripts is /etc/timeshift/restore-hooks.d. Note: the script(s) will be run from the restored filesystem.

I couldn't find any information on how to properly create these scripts so I checked timeshift/src/Core/Main.vala:

sh += "  run-parts --verbose /etc/timeshift/restore-hooks.d \n"; 

I checked the run-parts man page, then created this script based on its requirements: /etc/timeshift/restore-hooks.d/rebuild-uki

#!/bin/sh

echo test > ~/timeshift-restore-hook-ran #debug
# Rebuild UKI after restoring snapshot to sync snapshot's UKI to ESP
echo "Rebuilding UKI to sync snapshot's UKI to ESP..."
/usr/bin/mkinitcpio -P

sudo chmod +x /etc/timeshift/restore-hooks.d/rebuild-uki

The script runs fine when checking with run-parts --verbose /etc/timeshift/restore-hooks.d but it doesn't seem to work (no verbose output) in timeshift when restoring a snapshot.

For clarification, would this rebuild the UKI using the snapshot's files or would it create the UKI with kernel files prior to restoring (which will still cause UKI mismatch)? If this would not work, the 2nd idea would be to keep a copy of the UKI in /boot so when restoring snapshots, a post restore script will copy @_snapshot_location/boot/UKI.efi to ESP. But this would require a method to retrieve the snapshot's location in restore hook scripts which I'm unsure how to do.

Issues:

  1. Post restore-hook scripts are not working in Timeshift
  2. A method to rebuild the restored snapshot's UKI is needed to resolve UKI kernel mismatches. [Ideal fix for UKI]
  3. A way to retrieve restored BtrFs snapshot's location directory is needed in order to sync files to esp. [Fix for systemd-boot mismatched boot files + 2nd way to resolve UKI mismatch]

To Reproduce Steps to reproduce the behavior:

  1. Create an executable script with no filename extension in /etc/timeshift/restore-hooks.d/
  2. Restore a timeshift snapshot
  3. No verbose output of the script when restoring a snapshot, thus script is likely not being run

Expected behavior Scripts in /etc/timeshift/restore-hooks.d/ should run after restoring a snapshot.

System: