diff --git a/modules/nixos/disko/x86_64-linux/default.nix b/modules/nixos/disko/x86_64-linux/default.nix index 4daf1a6..ec6761e 100644 --- a/modules/nixos/disko/x86_64-linux/default.nix +++ b/modules/nixos/disko/x86_64-linux/default.nix @@ -11,14 +11,6 @@ in imports = [ ../options.nix ]; config = lib.mkIf (!isArm) { disko.devices = { - nodev."/" = { - fsType = "tmpfs"; - mountOptions = [ - "mode=755" - "defaults" - "size=2G" - ]; - }; disk = { main = { device = rootDisk; @@ -63,22 +55,20 @@ in "--compression=zstd" ]; subvolumes = { - "subvolumes/root" = { - mountpoint = "/root"; + "/root" = { + mountpoint = "/"; }; - "subvolumes/home" = { - mountpoint = "/home"; + "/persistent" = { + mountpoint = "/persistent"; }; - "subvolumes/nix" = { + "/nix" = { + mountOptions = [ + "noatime" + ]; mountpoint = "/nix"; }; - "subvolumes/etc" = { - mountpoint = "/etc"; - }; - "subvolumes/log" = { - mountpoint = "/var/log"; - }; }; + mountpoint = "/partition-root"; }; }; }; diff --git a/modules/nixos/impermanence/default.nix b/modules/nixos/impermanence/default.nix index fe54e7f..7bb45f0 100755 --- a/modules/nixos/impermanence/default.nix +++ b/modules/nixos/impermanence/default.nix @@ -1,73 +1,208 @@ -{ ... }: -{ - # Set up impernance configuration for things like bluetooth - # In this configuration with /etc and /var/log being persistent, only directories outside of that need to be done here. See hardware configuration for all mountpoints. +# { ... }: +# { +# # Set up impernance configuration for things like bluetooth +# # In this configuration with /etc and /var/log being persistent, only directories outside of that need to be done here. See hardware configuration for all mountpoints. - environment.persistence."/nix/persist/system" = { +# environment.persistence."/nix/persist/system" = { +# hideMounts = true; +# directories = [ +# "/var/lib/bluetooth" +# "/var/lib/iwd" +# "/var/lib/nixos" +# "/var/lib/libvirt" +# "/var/lib/waydroid" +# "/var/lib/systemd/coredump" +# "/etc/NetworkManager/system-connections" +# "/var/lib/tailscale" +# "/var/lib/homeassistant" +# "/var/lib/mosquitto" +# "/var/lib/music-assistant" +# "/var/lib/postgresql" +# "/var/lib/zigbee2mqtt" +# { +# directory = "/var/lib/colord"; +# user = "colord"; +# group = "colord"; +# mode = "u=rwx,g=rx,o="; +# } +# { +# directory = "/etc/nix"; +# user = "root"; +# group = "root"; +# mode = "u=rwx,g=rx,o=rx"; +# } +# { +# directory = "/var/lib/private/authentik/media"; +# user = "authentik"; +# group = "authentik"; +# mode = "u=rwx,g=,o="; +# } +# { +# directory = "/var/lib/private"; +# mode = "u=rwx,g=rx,o="; +# } +# { +# directory = "/media/nas"; +# user = "nas-apps"; +# group = "jallen-nas"; +# mode = "u=rwx,g=rx,o=rx"; +# } +# { +# directory = "/var/lib/crowdsec"; +# user = "crowdsec"; +# group = "crowdsec"; +# mode = "u=rwx,g=rwx,o=rx"; +# } +# { +# directory = "/plugins-storage"; +# user = "traefik"; +# group = "traefik"; +# mode = "u=rwx,g=rwx,o=rx"; +# } +# ]; +# files = [ +# "/etc/machine-id" +# ]; +# }; + +# security.sudo.extraConfig = '' +# # rollback results in sudo lectures after each reboot +# Defaults lecture = never +# ''; + +# } +{ + config, + lib, + ... +}: +with lib; +{ + system.activationScripts = { + "var-lib-private-permissions" = { + deps = [ "createPersistentStorageDirs" ]; + text = '' + mkdir -p /var/lib/private + chmod 0700 /var/lib/private + ''; + }; + }; + boot.initrd.systemd.services.rootfs-cleanup = { + description = "Clean file system root"; + wantedBy = [ + "initrd.target" + ]; + after = [ + "initrd-root-device.target" + ]; + before = [ + "sysroot.mount" + ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig.Type = "oneshot"; + script = + if config.fileSystems."/".fsType == "btrfs" then + '' + # workaround for machines without working rtc battery + # The time may not yet be correctly set, so wait until it is + if [[ $(date '+%s') -lt 1730469314 ]]; then + sleep 30 # this should hopefully be enough + fi + mkdir /btrfs_tmp + mount ${config.fileSystems."/".device} -t btrfs /btrfs_tmp + if [[ -e /btrfs_tmp/root ]]; then + mkdir -p /btrfs_tmp/old_roots + timestamp=$(date --date="@$(stat -c %X /btrfs_tmp/root)" "+%Y-%m-%d_%H:%M:%S") + mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp" + fi + + delete_subvolume_recursively() { + IFS=$'\n' + for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do + delete_subvolume_recursively "/btrfs_tmp/$i" + done + btrfs subvolume delete "$1" || rm -rf "$1" + } + + for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -atime +30); do + delete_subvolume_recursively "$i" + done + + btrfs subvolume create /btrfs_tmp/root + umount /btrfs_tmp + '' + else + '' + # workaround for machines without working rtc battery + # The time may not yet be correctly set, so wait until it is + if [[ $(date '+%s') -lt 1730469314 ]]; then + sleep 30 # this should hopefully be enough + fi + if [[ -e /root_tmp/root ]]; then + mkdir -p /root_tmp/old_roots + timestamp=$(date --date="@$(stat -c %X /root_tmp/root)" "+%Y-%m-%d_%H:%M:%S") + mv /root_tmp/root "/root_tmp/old_roots/$timestamp" + fi + + for i in $(find /root_tmp/old_roots/ -maxdepth 1 -atime +30); do + bcachefs subvolume delete $i + done + + bcachefs subvolume create /root_tmp/root + ''; + }; + assertions = [ + { + assertion = hasAttr "/" config.fileSystems; + message = "To use impermanence, you need to define a root volume"; + } + + { + assertion = + if hasAttr "/" config.fileSystems then + config.fileSystems."/".fsType == "btrfs" || config.fileSystems."/".fsType == "bcachefs" + else + false; + message = "rootfs must be btrfs or bcachefs"; + } + + { + assertion = + if hasAttr "/" config.fileSystems then + any ( + t: t == "subvol=root" || t == "subvol=/root" || t == "X-mount.subdir=root" + ) config.fileSystems."/".options + else + false; + message = "rootfs must mount subvolume root"; + } + { + assertion = !config.boot.isContainer; + message = "impermanence is not supported in containers"; + } + ]; + + fileSystems."/persistent" = { + neededForBoot = true; + }; + environment.persistence."/persistent" = { + enable = true; hideMounts = true; directories = [ - "/var/lib/bluetooth" - "/var/lib/iwd" + "/var/log" "/var/lib/nixos" - "/var/lib/libvirt" - "/var/lib/waydroid" - "/var/lib/systemd/coredump" - "/etc/NetworkManager/system-connections" - "/var/lib/tailscale" - "/var/lib/homeassistant" - "/var/lib/mosquitto" - "/var/lib/music-assistant" - "/var/lib/postgresql" - "/var/lib/zigbee2mqtt" - { - directory = "/var/lib/colord"; - user = "colord"; - group = "colord"; - mode = "u=rwx,g=rx,o="; - } - { - directory = "/etc/nix"; - user = "root"; - group = "root"; - mode = "u=rwx,g=rx,o=rx"; - } - { - directory = "/var/lib/private/authentik/media"; - user = "authentik"; - group = "authentik"; - mode = "u=rwx,g=,o="; - } - { - directory = "/var/lib/private"; - mode = "u=rwx,g=rx,o="; - } - { - directory = "/media/nas"; - user = "nas-apps"; - group = "jallen-nas"; - mode = "u=rwx,g=rx,o=rx"; - } - { - directory = "/var/lib/crowdsec"; - user = "crowdsec"; - group = "crowdsec"; - mode = "u=rwx,g=rwx,o=rx"; - } - { - directory = "/plugins-storage"; - user = "traefik"; - group = "traefik"; - mode = "u=rwx,g=rwx,o=rx"; - } + "/var/cache" ]; files = [ - "/etc/machine-id" + "/etc/ssh/ssh_host_ecdsa_key" + "/etc/ssh/ssh_host_ecdsa_key.pub" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + "/etc/ssh/ssh_host_rsa_key" + "/etc/ssh/ssh_host_rsa_key.pub" ]; }; - - security.sudo.extraConfig = '' - # rollback results in sudo lectures after each reboot - Defaults lecture = never - ''; - + systemd.tmpfiles.rules = [ + "d /persistent/var/cache 1777 root root 7d -" + ]; }