1
0

impermanence.nix 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. { config, inputs, lib, ... }:
  2. {
  3. imports = [
  4. inputs.impermanence.nixosModules.impermanence
  5. ];
  6. boot.initrd.postDeviceCommands = lib.mkAfter ''
  7. #!/bin/sh
  8. DEVICE=${config.disko.devices.disk.main.device}-part2
  9. # Mount Btrfs root
  10. mkdir -p /mnt
  11. if ! mount -o subvol=/ $DEVICE /mnt; then
  12. echo "Failed to mount $DEVICE at /mnt"
  13. exit 1
  14. fi
  15. # Create directory for old roots
  16. mkdir -p /mnt/old-roots
  17. # Move current root to old-roots with current timestamp
  18. if [[ -e /mnt/@root && ! -e /mnt/@root-blank ]]; then
  19. timestamp=$(date +%Y-%m-%d_%H:%M:%S)
  20. if ! mv /mnt/@root "/mnt/old-roots/@root-$timestamp"; then
  21. echo "Failed to move /mnt/@root to old-roots"
  22. umount /mnt
  23. exit 1
  24. fi
  25. fi
  26. # Function to recursively delete subvolumes
  27. delete_subvolume_recursively() {
  28. for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
  29. delete_subvolume_recursively "/mnt/$i"
  30. done
  31. if ! btrfs subvolume delete "$1"; then
  32. echo "Failed to delete subvolume $1"
  33. fi
  34. }
  35. # Delete old roots older than 30 days
  36. for i in $(btrfs subvolume list /mnt | grep 'old-roots/@root-' | cut -f 9- -d ' '); do
  37. subvol_time=$(echo "$i" | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}')
  38. if [[ -n "$subvol_time" ]]; then
  39. subvol_secs=$(date -d "$subvol_time" +%s 2>/dev/null || continue)
  40. thirty_days_ago=$(date -d "30 days ago" +%s)
  41. if [[ $subvol_secs -lt $thirty_days_ago ]]; then
  42. delete_subvolume_recursively "/mnt/$i"
  43. fi
  44. fi
  45. done
  46. # Create or restore fresh root
  47. if [[ -e /mnt/@root-blank ]]; then
  48. btrfs subvolume delete /mnt/@root || true
  49. if ! btrfs subvolume snapshot /mnt/@root-blank /mnt/@root; then
  50. echo "Failed to snapshot @root-blank to @root"
  51. umount /mnt
  52. exit 1
  53. fi
  54. else
  55. if ! btrfs subvolume create /mnt/@root-blank; then
  56. echo "Failed to create @root-blank"
  57. umount /mnt
  58. exit 1
  59. fi
  60. if ! btrfs subvolume create /mnt/@root; then
  61. echo "Failed to create @root"
  62. umount /mnt
  63. exit 1
  64. fi
  65. fi
  66. # Unmount
  67. if ! umount /mnt; then
  68. echo "Failed to unmount /mnt"
  69. exit 1
  70. fi
  71. '';
  72. # Persistent directories for impermanence
  73. fileSystems."/persist".neededForBoot = true;
  74. fileSystems."/var/lib".neededForBoot = true;
  75. environment.persistence."/persist" = {
  76. hideMounts = true;
  77. directories = [
  78. "/etc/ssh"
  79. "/srv"
  80. ];
  81. files = [
  82. "/etc/machine-id"
  83. ];
  84. users.thomas.directories = [
  85. ".ssh"
  86. ".local/share"
  87. ];
  88. };
  89. }