diff --git a/modules/nixos/hardware/bluetooth/default.nix b/modules/nixos/hardware/bluetooth/default.nix index 2d840f9..3dd44e6 100644 --- a/modules/nixos/hardware/bluetooth/default.nix +++ b/modules/nixos/hardware/bluetooth/default.nix @@ -18,6 +18,13 @@ in services.blueman.enable = true; } + # Persist bluetooth files + { + my.system.persist.directories = [ + "/var/lib/bluetooth" + ]; + } + # Support for additional bluetooth codecs (lib.mkIf cfg.loadExtraCodecs { hardware.pulseaudio = { diff --git a/modules/nixos/hardware/networking/default.nix b/modules/nixos/hardware/networking/default.nix index f0806fe..51dcfce 100644 --- a/modules/nixos/hardware/networking/default.nix +++ b/modules/nixos/hardware/networking/default.nix @@ -22,6 +22,11 @@ in config = lib.mkMerge [ (lib.mkIf cfg.wireless.enable { networking.networkmanager.enable = true; + + # Persist NetworkManager files + my.system.persist.directories = [ + "/etc/NetworkManager/system-connections" + ]; }) ]; } diff --git a/modules/nixos/services/blog/default.nix b/modules/nixos/services/blog/default.nix index 4b646c3..6752ac2 100644 --- a/modules/nixos/services/blog/default.nix +++ b/modules/nixos/services/blog/default.nix @@ -42,5 +42,12 @@ in # Those are all subdomains, no problem my.services.nginx.virtualHosts = hostsInfo; + + my.system.persist.directories = [ + "/var/www/blog" + "/var/www/cv" + "/var/www/dev" + "/var/www/key" + ]; }; } diff --git a/modules/nixos/services/calibre-web/default.nix b/modules/nixos/services/calibre-web/default.nix index 858851c..b6e70d8 100644 --- a/modules/nixos/services/calibre-web/default.nix +++ b/modules/nixos/services/calibre-web/default.nix @@ -54,6 +54,11 @@ in ]; }; + my.system.persist.directories = [ + "/var/lib/${config.services.calibre-web.dataDir}" + cfg.libraryPath + ]; + services.fail2ban.jails = { calibre-web = '' enabled = true diff --git a/modules/nixos/services/flood/default.nix b/modules/nixos/services/flood/default.nix index ff5d941..79b6c75 100644 --- a/modules/nixos/services/flood/default.nix +++ b/modules/nixos/services/flood/default.nix @@ -46,5 +46,9 @@ in inherit (cfg) port; } ]; + + my.system.persist.directories = [ + "/var/lib/${cfg.stateDir}" + ]; }; } diff --git a/modules/nixos/services/gitea/default.nix b/modules/nixos/services/gitea/default.nix index 28a448d..93edf57 100644 --- a/modules/nixos/services/gitea/default.nix +++ b/modules/nixos/services/gitea/default.nix @@ -135,6 +135,11 @@ in ]; }; + my.system.persist.directories = [ + config.services.gitea.lfs.contentDir + config.services.gitea.repositoryRoot + ]; + services.fail2ban.jails = { gitea = '' enabled = true diff --git a/modules/nixos/services/grocy/default.nix b/modules/nixos/services/grocy/default.nix index 87927d6..4a3183e 100644 --- a/modules/nixos/services/grocy/default.nix +++ b/modules/nixos/services/grocy/default.nix @@ -36,5 +36,8 @@ in forceSSL = true; useACMEHost = config.networking.domain; }; + + # FIXME: backup + # FIXME: persistence }; } diff --git a/modules/nixos/services/indexers/default.nix b/modules/nixos/services/indexers/default.nix index fb06a0b..28a7007 100644 --- a/modules/nixos/services/indexers/default.nix +++ b/modules/nixos/services/indexers/default.nix @@ -34,6 +34,10 @@ in port = jackettPort; } ]; + + my.system.persist.directories = [ + config.services.jackett.dataDir + ]; }) (lib.mkIf cfg.nzbhydra.enable { @@ -47,6 +51,10 @@ in port = nzbhydraPort; } ]; + + my.system.persist.directories = [ + config.services.nzbhydra2.dataDir + ]; }) (lib.mkIf cfg.prowlarr.enable { @@ -61,6 +69,10 @@ in } ]; + my.system.persist.directories = [ + "/var/lib/${config.systemd.services.prowlarr.serviceConfig.StateDirectory}" + ]; + services.fail2ban.jails = { prowlarr = '' enabled = true diff --git a/modules/nixos/services/jellyfin/default.nix b/modules/nixos/services/jellyfin/default.nix index 2fcf51e..0692dcc 100644 --- a/modules/nixos/services/jellyfin/default.nix +++ b/modules/nixos/services/jellyfin/default.nix @@ -35,5 +35,9 @@ in }; } ]; + + my.system.persist.directories = [ + "/var/lib/${config.systemd.services.jellyfin.serviceConfig.StateDirectory}" + ]; }; } diff --git a/modules/nixos/services/lohr/default.nix b/modules/nixos/services/lohr/default.nix index 245567c..7aac1ac 100644 --- a/modules/nixos/services/lohr/default.nix +++ b/modules/nixos/services/lohr/default.nix @@ -104,5 +104,9 @@ in inherit (cfg) port; } ]; + + my.system.persist.directories = [ + "/var/lib/${config.systemd.services.lohr.serviceConfig.StateDirectory}" + ]; }; } diff --git a/modules/nixos/services/matrix/default.nix b/modules/nixos/services/matrix/default.nix index 52b60c5..87494c9 100644 --- a/modules/nixos/services/matrix/default.nix +++ b/modules/nixos/services/matrix/default.nix @@ -257,5 +257,9 @@ in config.services.matrix-synapse.dataDir ]; }; + + my.system.persist.directories = [ + config.services.matrix-synapse.dataDir + ]; }; } diff --git a/modules/nixos/services/miniflux/default.nix b/modules/nixos/services/miniflux/default.nix index 6d9ffc8..4667912 100644 --- a/modules/nixos/services/miniflux/default.nix +++ b/modules/nixos/services/miniflux/default.nix @@ -49,5 +49,8 @@ in inherit (cfg) port; } ]; + + # FIXME: backup + # FIXME: persistence }; } diff --git a/modules/nixos/services/monitoring/default.nix b/modules/nixos/services/monitoring/default.nix index 829bfe0..c7489f4 100644 --- a/modules/nixos/services/monitoring/default.nix +++ b/modules/nixos/services/monitoring/default.nix @@ -131,5 +131,10 @@ in inherit (cfg.grafana) port; } ]; + + my.system.persist.directories = [ + config.services.grafana.dataDir + "/var/lib/${config.services.prometheus.stateDir}" + ]; }; } diff --git a/modules/nixos/services/navidrome/default.nix b/modules/nixos/services/navidrome/default.nix index 6c001fd..08c6a88 100644 --- a/modules/nixos/services/navidrome/default.nix +++ b/modules/nixos/services/navidrome/default.nix @@ -53,5 +53,9 @@ in inherit (cfg) port; } ]; + + my.system.persist.directories = [ + "/var/lib/${config.systemd.services.navidrome.serviceConfig.StateDirectory}" + ]; }; } diff --git a/modules/nixos/services/nextcloud/default.nix b/modules/nixos/services/nextcloud/default.nix index 260e73e..b9578f8 100644 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -82,5 +82,10 @@ in "${config.services.nextcloud.home}/data/appdata_*/preview" ]; }; + + my.system.persist.directories = [ + config.services.nextcloud.home + config.services.nextcloud.datadir + ]; }; } diff --git a/modules/nixos/services/nginx/default.nix b/modules/nixos/services/nginx/default.nix index 6ca2e42..a28c2be 100644 --- a/modules/nixos/services/nginx/default.nix +++ b/modules/nixos/services/nginx/default.nix @@ -467,5 +467,9 @@ in } ]; }; + + my.system.persist.directories = [ + config.users.user.acme.home + ]; }; } diff --git a/modules/nixos/services/paperless/default.nix b/modules/nixos/services/paperless/default.nix index 1ca1f66..702627d 100644 --- a/modules/nixos/services/paperless/default.nix +++ b/modules/nixos/services/paperless/default.nix @@ -164,5 +164,10 @@ in config.services.paperless.mediaDir ]; }; + + my.system.persist.directories = [ + config.services.paperless-ng.dataDir + config.services.paperless-ng.mediaDir + ]; }; } diff --git a/modules/nixos/services/pirate/default.nix b/modules/nixos/services/pirate/default.nix index 59f9794..cfabc90 100644 --- a/modules/nixos/services/pirate/default.nix +++ b/modules/nixos/services/pirate/default.nix @@ -18,6 +18,11 @@ let enable = true; group = "media"; }; + + # Thankfully those old style services all define users with homes + my.system.persist.directories = [ + config.users.user.${service}.home + ]; }; mkRedirection = service: { diff --git a/modules/nixos/services/podgrab/default.nix b/modules/nixos/services/podgrab/default.nix index 9793d60..2994fc8 100644 --- a/modules/nixos/services/podgrab/default.nix +++ b/modules/nixos/services/podgrab/default.nix @@ -37,5 +37,10 @@ in inherit (cfg) port; } ]; + + my.system.persist.directories = + builtins.map + (d: "/var/lib/${d}") + config.systemd.services.podgrab.serviceConfig.StateDirectory; }; } diff --git a/modules/nixos/services/postgresql-backup/default.nix b/modules/nixos/services/postgresql-backup/default.nix index dff5494..3d6c03b 100644 --- a/modules/nixos/services/postgresql-backup/default.nix +++ b/modules/nixos/services/postgresql-backup/default.nix @@ -24,5 +24,9 @@ in (config.services.postgresqlBackup.location + "/*.prev.sql.gz") ]; }; + + my.system.persist.directories = [ + config.services.postgresqlBackup.location + ]; }; } diff --git a/modules/nixos/services/postgresql/default.nix b/modules/nixos/services/postgresql/default.nix index 6f51f3e..175c1ce 100644 --- a/modules/nixos/services/postgresql/default.nix +++ b/modules/nixos/services/postgresql/default.nix @@ -18,6 +18,13 @@ in }; }) + # Only persist directory if the actual service is enabled + (lib.mkIf config.services.postgresql.enable { + my.system.persist.directories = [ + config.services.postgresql.dataDir + ]; + }) + # Taken from the manual (lib.mkIf cfg.upgradeScript { containers.temp-pg.config.services.postgresql = { diff --git a/modules/nixos/services/quassel/default.nix b/modules/nixos/services/quassel/default.nix index ec686e1..18d084a 100644 --- a/modules/nixos/services/quassel/default.nix +++ b/modules/nixos/services/quassel/default.nix @@ -46,5 +46,9 @@ in # Because Quassel does not use the socket, I simply trust its connection authentication = "host quassel quassel localhost trust"; }; + + my.system.persist.directories = [ + config.services.quassel.dataDir + ]; }; } diff --git a/modules/nixos/services/rss-bridge/default.nix b/modules/nixos/services/rss-bridge/default.nix index 85e37c2..66858dc 100644 --- a/modules/nixos/services/rss-bridge/default.nix +++ b/modules/nixos/services/rss-bridge/default.nix @@ -20,5 +20,9 @@ in forceSSL = true; useACMEHost = config.networking.domain; }; + + my.system.persist.directories = [ + config.services.rss-bridge.dataDir + ]; }; } diff --git a/modules/nixos/services/sabnzbd/default.nix b/modules/nixos/services/sabnzbd/default.nix index 7ab145f..ef13d4b 100644 --- a/modules/nixos/services/sabnzbd/default.nix +++ b/modules/nixos/services/sabnzbd/default.nix @@ -25,6 +25,10 @@ in } ]; + my.system.persist.files = [ + config.services.sabnzbd.configFile + ]; + services.fail2ban.jails = { sabnzbd = '' enabled = true diff --git a/modules/nixos/services/ssh-server/default.nix b/modules/nixos/services/ssh-server/default.nix index 9ae0fa8..0cabc6f 100644 --- a/modules/nixos/services/ssh-server/default.nix +++ b/modules/nixos/services/ssh-server/default.nix @@ -20,6 +20,14 @@ in }; }; + # Persist SSH keys + my.system.persist.files = [ + "/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" + ]; + # Opens the relevant UDP ports. programs.mosh.enable = true; }; diff --git a/modules/nixos/services/tandoor-recipes/default.nix b/modules/nixos/services/tandoor-recipes/default.nix index 83177c8..3688363 100644 --- a/modules/nixos/services/tandoor-recipes/default.nix +++ b/modules/nixos/services/tandoor-recipes/default.nix @@ -76,5 +76,8 @@ in inherit (cfg) port; } ]; + + # FIXME: backup + # FIXME: persistence }; } diff --git a/modules/nixos/services/transmission/default.nix b/modules/nixos/services/transmission/default.nix index 28df477..37e4f0f 100644 --- a/modules/nixos/services/transmission/default.nix +++ b/modules/nixos/services/transmission/default.nix @@ -91,5 +91,9 @@ in allowedTCPPorts = [ cfg.peerPort ]; allowedUDPPorts = [ cfg.peerPort ]; }; + + my.system.persist.directories = [ + config.services.transmission.home + ]; }; } diff --git a/modules/nixos/services/vikunja/default.nix b/modules/nixos/services/vikunja/default.nix index 1cdef5f..076dd4a 100644 --- a/modules/nixos/services/vikunja/default.nix +++ b/modules/nixos/services/vikunja/default.nix @@ -119,5 +119,7 @@ in config.services.vikunja.settings.files.basepath ]; }; + + # FIXME: persistence }; } diff --git a/modules/nixos/system/default.nix b/modules/nixos/system/default.nix index e7a4dd3..e317d96 100644 --- a/modules/nixos/system/default.nix +++ b/modules/nixos/system/default.nix @@ -9,6 +9,7 @@ ./language ./nix ./packages + ./persist ./podman ./printing ./users diff --git a/modules/nixos/system/persist/default.nix b/modules/nixos/system/persist/default.nix new file mode 100644 index 0000000..18302f3 --- /dev/null +++ b/modules/nixos/system/persist/default.nix @@ -0,0 +1,68 @@ +# Ephemeral root configuration +{ config, inputs, lib, ... }: +let + cfg = config.my.system.persist; +in +{ + imports = [ + inputs.impermanence.nixosModules.impermanence + ]; + + options.my.system.persist = with lib; { + enable = mkEnableOption "stateless system configuration"; + + mountPoint = lib.mkOption { + type = types.str; + default = "/persistent"; + example = "/etc/nix/persist"; + description = '' + Which mount point should be used to persist this system's files and + directories. + ''; + }; + + files = lib.mkOption { + type = with types; listOf str; + default = [ ]; + example = [ + "/etc/nix/id_rsa" + ]; + description = '' + Additional files in the root to link to persistent storage. + ''; + }; + + directories = lib.mkOption { + type = with types; listOf str; + default = [ ]; + example = [ + "/var/lib/libvirt" + ]; + description = '' + Additional directories in the root to link to persistent storage. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + environment.persistence."${cfg.mountPoint}" = { + files = [ + "/etc/machine-id" + ] + ++ cfg.files + ; + + directories = [ + "/etc/nixos" + "/var/log" + "/var/lib/systemd/coredump" + ] + ++ (lib.optionals config.virtualisation.docker.enable [ + "/var/lib/docker" + ]) + # FIXME: podman + ++ cfg.directories + ; + }; + }; +}