Skyler Grey | 40ae7a0 | 2024-06-06 21:22:25 +0000 | [diff] [blame] | 1 | # SPDX-FileCopyrightText: 2024 Clicks Codes |
| 2 | # SPDX-FileCopyrightText: 2020 Nix Community Projects |
| 3 | # |
| 4 | # SPDX-License-Identifier: MIT |
| 5 | # postDeviceCommands based of code from https://github.com/nix-community/impermanence/tree/d5f1ed7141fa407880ff5956ded2c88a307ca940?tab=readme-ov-file#btrfs-subvolumes |
| 6 | |
| 7 | { lib, config, ... }: |
| 8 | let |
| 9 | cfg = config.clicks.storage.impermanence; |
| 10 | in |
| 11 | { |
| 12 | options.clicks.storage.impermanence = { |
| 13 | enable = lib.mkEnableOption "Enable impermanent rootfs with btrfs subvolumes"; |
| 14 | device = lib.mkOption { |
| 15 | type = lib.types.str; |
| 16 | description = "Device Path"; |
| 17 | }; |
| 18 | volumes = { |
| 19 | mount = lib.mkOption { |
| 20 | type = lib.types.str; |
| 21 | description = "Path on device to the mounting subvolume, everything on here will be deleted"; |
| 22 | default = "@"; |
| 23 | }; |
| 24 | old_roots = lib.mkOption { |
| 25 | type = lib.types.str; |
| 26 | description = "Path on device to store old roots on"; |
| 27 | default = "old_roots"; |
| 28 | }; |
| 29 | }; |
| 30 | delete_days = lib.mkOption { |
| 31 | type = lib.types.int; |
| 32 | description = "How many days to wait before deleting an old root from cfg.old_roots"; |
| 33 | default = 7; |
| 34 | }; |
| 35 | }; |
| 36 | |
| 37 | config = lib.mkIf cfg.enable { |
| 38 | boot.initrd.postDeviceCommands = lib.mkAfter '' |
| 39 | mkdir /impermanent_fs |
| 40 | mount ${cfg.device} /impermanent_fs |
| 41 | |
| 42 | if [[ -e /impermanent_fs/${cfg.volumes.mount} ]]; then |
| 43 | mkdir -p /impermanent_fs/${cfg.volumes.old_roots} |
| 44 | timestamp=$(date --date="@$(stat -c %Y /impermanent_fs/${cfg.volumes.mount})" "+%Y-%m-%-d_%H:%M:%S") |
| 45 | mv /impermanent_fs/${cfg.volumes.mount} "/impermanent_fs/${cfg.volumes.old_roots}/$timestamp" |
| 46 | fi |
| 47 | |
| 48 | delete_subvolume_recursively() { |
| 49 | IFS=$'\n' |
| 50 | for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do |
| 51 | delete_subvolume_recursively "/impermanent_fs/$i" |
| 52 | done |
| 53 | btrfs subvolume delete "$1" |
| 54 | } |
| 55 | |
| 56 | for i in $(find /impermanent_fs/${cfg.volumes.old_roots}/ -maxdepth 1 -mtime +${builtins.toString cfg.delete_days}); do |
| 57 | delete_subvolume_recursively "$i" |
| 58 | done |
| 59 | |
| 60 | btrfs subvolume create /impermanent_fs/${cfg.volumes.mount} |
| 61 | umount /impermanent_fs |
| 62 | ''; |
| 63 | |
| 64 | fileSystems."/" = { |
| 65 | device = cfg.device; |
| 66 | fsType = "btrfs"; |
| 67 | options = [ "subvol=${cfg.volumes.mount}" ]; |
| 68 | }; |
| 69 | }; |
| 70 | } |