blob: ac797a666fb4d938901d3de523db804838a7c7e0 [file] [log] [blame]
Skyler Grey40ae7a02024-06-06 21:22:25 +00001# 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, ... }:
8let
9 cfg = config.clicks.storage.impermanence;
10in
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}