-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherasure.nix
executable file
·93 lines (84 loc) · 3.4 KB
/
erasure.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# TODO Switch to this eventually: https://github.com/nix-community/impermanence
{ config, lib, pkgs, modulesPath, ... }:
let
withoutNulls = l: builtins.filter (e: e != null) l;
check = condition: value: if condition then value else null;
persistOther = withoutNulls [
(check config.networking.wireless.iwd.enable "/var/lib/iwd")
(check config.services.upower.enable "/var/lib/upower")
(check config.virtualisation.docker.enable "/var/lib/docker")
(check config.services.fprintd.enable "/var/lib/fprint")
# (check config.hardware.bluetooth.enable "/var/lib/bluetooth")
];
persistInEtc = [ "machine-id" "adjtime" "NIXOS" "nixos" ];
in {
# systemd.tmpfiles.rules =
# [ "L /var/lib/bluetooth - - - - /persist/var/lib/bluetooth" ];
# Bind mount persisted folders onto the root partition at boot.
# Several services don't like their state folders to be symlinks, so bind
# mounts work better.
systemd.mounts = (map (path: {
what = "/persist${path}";
where = path;
type = "none";
options = "bind";
mountConfig.DirectoryMode = lib.mkIf (path == "/var/lib/bluetooth") "0755";
}) persistOther);
fileSystems."/var/lib/bluetooth" = {
device = "/persist/var/lib/bluetooth";
options = [ "bind" "noauto" "x-systemd.automount" ];
noCheck = true;
};
# Let NixOS handle the persistent /etc files.
environment.etc = lib.mkMerge
(map (name: { "${name}".source = "/persist/etc/${name}"; }) persistInEtc);
# Make sure any existing state is copied over to /persist before clobbering
# the root subvolume.
system.activationScripts.etc.deps = [ "cp-etc" ];
system.activationScripts.cp-etc = let
etcLinks = (map (name: ''
[ -e "/persist/etc/${name}" ] || cp -Trfp {,/persist}/etc/${name} || true
'') persistInEtc);
otherLinks = (map (path: ''
[ -e "/persist${path}" ] || cp -Trfp {,/persist}${path} || true
'') persistOther);
in ''
mkdir -p /persist/etc
mkdir -p /persist/var/lib
'' + (builtins.concatStringsSep "\n" (etcLinks ++ otherLinks));
# Erase all state files that weren't explicitly saved.
boot.initrd.postDeviceCommands = pkgs.lib.mkBefore ''
mkdir -p /mnt
# We first mount the btrfs root to /mnt
# so we can manipulate btrfs subvolumes.
mount -o subvol=/ ${config.fileSystems."/".device} /mnt
# While we're tempted to just delete /root and create
# a new snapshot from /root-blank, /root is already
# populated at this point with a number of subvolumes,
# which makes `btrfs subvolume delete` fail.
# So, we remove them first.
#
# /root contains subvolumes:
# - /root/var/lib/portables
# - /root/var/lib/machines
#
# I suspect these are related to systemd-nspawn, but
# since I don't use it I'm not 100% sure.
# Anyhow, deleting these subvolumes hasn't resulted
# in any issues so far, except for fairly
# benign-looking errors from systemd-tmpfiles.
btrfs subvolume list -o /mnt/root |
cut -f9 -d' ' |
while read subvolume; do
echo "deleting /$subvolume subvolume..."
btrfs subvolume delete "/mnt/$subvolume"
done &&
echo "deleting /root subvolume..." &&
btrfs subvolume delete /mnt/root
echo "restoring blank /root subvolume..."
btrfs subvolume snapshot /mnt/root-blank /mnt/root
# Once we're done rolling back to a blank snapshot,
# we can unmount /mnt and continue on the boot process.
umount /mnt
'';
}