1
0

impermanence.nix 2.7 KB

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