From 4ce902b536758a6d5e93da7a56b93e95363d6646 Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Tue, 8 Jun 2021 19:35:21 +0300 Subject: [PATCH] tmpfs root for x2100-laptop --- flake.lock | 16 +++ flake.nix | 1 + machines/X2100-Laptop/default.nix | 22 ++- .../X2100-Laptop/hardware-configuration.nix | 3 +- modules/applications/emacs/default.nix | 9 +- modules/applications/emacs/init.el | 6 - modules/applications/firefox.nix | 3 + modules/applications/geary.nix | 3 + modules/applications/nheko.nix | 8 ++ modules/applications/packages.nix | 3 +- modules/boot.nix | 1 + modules/default.nix | 2 + modules/ezwg.nix | 1 + modules/hardware.nix | 2 + modules/network.nix | 3 + modules/nix.nix | 3 + modules/persist.nix | 133 ++++++++++++++++++ modules/secrets.nix | 3 + modules/workspace/gnome3/default.nix | 10 ++ modules/workspace/gpg.nix | 2 + modules/workspace/misc.nix | 2 + modules/workspace/ssh.nix | 7 + modules/workspace/zsh.nix | 3 + profiles/base.nix | 15 +- profiles/desktop.nix | 1 + 25 files changed, 234 insertions(+), 28 deletions(-) create mode 100644 modules/applications/nheko.nix create mode 100644 modules/persist.nix diff --git a/flake.lock b/flake.lock index c326063..4ad5245 100644 --- a/flake.lock +++ b/flake.lock @@ -237,6 +237,21 @@ "type": "github" } }, + "impermanence": { + "locked": { + "lastModified": 1611747548, + "narHash": "sha256-2z5wmWda1uI4IkTZrW52jiHq3bzhYLc+GgjvaSd544M=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "58558845bc68dcf2bb32caa80564f7fe3f6cbc61", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, "lambda-launcher": { "inputs": { "nixpkgs": "nixpkgs_5" @@ -523,6 +538,7 @@ "flake-compat": "flake-compat_2", "himalaya": "himalaya", "home-manager": "home-manager", + "impermanence": "impermanence", "lambda-launcher": "lambda-launcher", "materia-theme": "materia-theme", "nix": "nix", diff --git a/flake.nix b/flake.nix index 252d931..40d2202 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ flake = false; }; himalaya.url = "github:soywod/himalaya"; + impermanence.url = "github:nix-community/impermanence"; }; outputs = { nixpkgs, nix, self, deploy-rs, ... }@inputs: { diff --git a/machines/X2100-Laptop/default.nix b/machines/X2100-Laptop/default.nix index d1418c5..0dc271a 100644 --- a/machines/X2100-Laptop/default.nix +++ b/machines/X2100-Laptop/default.nix @@ -1,5 +1,8 @@ { inputs, lib, config, pkgs, ... }: { - imports = [ ./hardware-configuration.nix inputs.self.nixosProfiles.desktop ]; + imports = [ + ./hardware-configuration.nix + inputs.self.nixosProfiles.desktop + ]; deviceSpecific.devInfo = { cpu = { vendor = "intel"; @@ -13,12 +16,19 @@ }; ram = 16; }; - home-manager.users.balsoft.xdg.configFile."simple-osd/brightness".text = pkgs.my-lib.genIni { - default = { - "backlight backend" = "/sys/class/backlight/intel_backlight"; - "refresh interval" = 100; - }; + + persist = { + enable = true; + cache.clean.enable = true; }; + + home-manager.users.balsoft.xdg.configFile."simple-osd/brightness".text = + pkgs.my-lib.genIni { + default = { + "backlight backend" = "/sys/class/backlight/intel_backlight"; + "refresh interval" = 100; + }; + }; boot.extraModprobeConfig = '' options iwlwifi bt_coex_active=0 ''; diff --git a/machines/X2100-Laptop/hardware-configuration.nix b/machines/X2100-Laptop/hardware-configuration.nix index be19894..cbd468f 100755 --- a/machines/X2100-Laptop/hardware-configuration.nix +++ b/machines/X2100-Laptop/hardware-configuration.nix @@ -13,9 +13,10 @@ boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = { + fileSystems."/persist" = { device = "/dev/disk/by-uuid/e50bd1d6-3613-465e-895a-9dde6ffaad46"; fsType = "ext4"; + neededForBoot = true; }; fileSystems."/boot" = { diff --git a/modules/applications/emacs/default.nix b/modules/applications/emacs/default.nix index ae9c36b..e707027 100644 --- a/modules/applications/emacs/default.nix +++ b/modules/applications/emacs/default.nix @@ -15,6 +15,8 @@ in { # directory = "emacs"; # }; + persist.state.homeFiles = [ ".config/emacs/custom" ".config/emacs/eshell/history" ]; + home-manager.users.balsoft = { programs.emacs = { enable = true; @@ -78,11 +80,6 @@ in { systemd.user.services.emacs.Service.Environment = "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/balsoft/bin"; - home.file.".emacs.d/init.el".source = ./init.el; - home.activation.emacs = { - before = [ ]; - after = [ ]; - data = "$DRY_RUN_CMD mkdir -p ~/.emacs.d/autosave"; - }; + xdg.configFile."emacs/init.el".source = ./init.el; }; } diff --git a/modules/applications/emacs/init.el b/modules/applications/emacs/init.el index b09e4f5..110126d 100755 --- a/modules/applications/emacs/init.el +++ b/modules/applications/emacs/init.el @@ -23,12 +23,6 @@ (line-number-mode) (column-number-mode) -;; backup in one place. flat, no tree structure -(setq backup-directory-alist '(("" . "~/.emacs.d/backup"))) - -(setq auto-save-file-name-transforms - `((".*" "~/.emacs.d/autosave/" t))) - (setq-default indent-tabs-mode nil) (setq-default tab-always-indent 't) diff --git a/modules/applications/firefox.nix b/modules/applications/firefox.nix index 3c2d376..1b54ef4 100644 --- a/modules/applications/firefox.nix +++ b/modules/applications/firefox.nix @@ -6,6 +6,9 @@ in { MOZ_DBUS_REMOTE = "1"; }; programs.browserpass.enable = true; + + persist.state.directories = [ "/home/balsoft/.mozilla/firefox/default" ]; + home-manager.users.balsoft = lib.mkIf (config.deviceSpecific.goodMachine) { programs.browserpass = { enable = true; diff --git a/modules/applications/geary.nix b/modules/applications/geary.nix index 9808b2c..1ca58c6 100644 --- a/modules/applications/geary.nix +++ b/modules/applications/geary.nix @@ -54,6 +54,9 @@ let }; in { programs.geary.enable = true; + + persist.cache.directories = [ "/home/balsoft/.local/share/geary" ]; + home-manager.users.balsoft = { xdg.configFile."geary/user-style.css".text = '' *, html, body, body.plain div, body.plain a, body.plain p, body.plain span { diff --git a/modules/applications/nheko.nix b/modules/applications/nheko.nix new file mode 100644 index 0000000..c00884a --- /dev/null +++ b/modules/applications/nheko.nix @@ -0,0 +1,8 @@ +{ config, pkgs, lib, ... }: +{ + home-manager.users.balsoft.home.packages = [ pkgs.nheko ]; + persist.state.directories = [ + "/home/balsoft/.local/share/nheko" + "/home/balsoft/.config/nheko" + ]; +} diff --git a/modules/applications/packages.nix b/modules/applications/packages.nix index 4e10530..13c814d 100644 --- a/modules/applications/packages.nix +++ b/modules/applications/packages.nix @@ -17,7 +17,6 @@ github-cli # Messaging libnotify - nheko # Audio/Video vlc pavucontrol @@ -32,7 +31,7 @@ gnumeric gcalcli xdg_utils - inputs.yt-utilities.defaultPackage.x86_64-linux + # inputs.yt-utilities.defaultPackage.x86_64-linux lambda-launcher nix-patch pass-wayland diff --git a/modules/boot.nix b/modules/boot.nix index 3640f73..f112f96 100644 --- a/modules/boot.nix +++ b/modules/boot.nix @@ -19,4 +19,5 @@ kernel.sysctl."vm.swappiness" = 0; kernel.sysctl."kernel/sysrq" = 1; }; + persist.state.etcFiles = [ "machine-id" ]; } diff --git a/modules/default.nix b/modules/default.nix index 9251350..63f0b98 100755 --- a/modules/default.nix +++ b/modules/default.nix @@ -11,6 +11,7 @@ builtins.listToAttrs (builtins.map (path: { ./applications/firefox.nix ./applications/geary.nix ./applications/himalaya.nix + ./applications/nheko.nix ./applications/okular.nix ./applications/packages.nix ./applications/yt-utilities.nix @@ -21,6 +22,7 @@ builtins.listToAttrs (builtins.map (path: { ./network.nix ./nix.nix ./overlay.nix + ./persist.nix ./power.nix ./secrets-envsubst.nix ./secrets.nix diff --git a/modules/ezwg.nix b/modules/ezwg.nix index ca521d2..07107a5 100644 --- a/modules/ezwg.nix +++ b/modules/ezwg.nix @@ -51,6 +51,7 @@ in { "\\x3d" ] cfg.serverKey }".wantedBy = lib.mkForce [ ]; + networking.wireguard.interfaces.wg0 = let generateRangesScript = builtins.toFile "exclusionary-wildcard-ranges-generator.py" '' diff --git a/modules/hardware.nix b/modules/hardware.nix index fab8470..4b7bd25 100644 --- a/modules/hardware.nix +++ b/modules/hardware.nix @@ -12,6 +12,8 @@ with deviceSpecific; { hardware.bluetooth.enable = true; hardware.bluetooth.package = pkgs.bluezFull; + persist.state.directories = [ "/var/lib/bluetooth" ]; + systemd.services.systemd-udev-settle.enable = false; diff --git a/modules/network.nix b/modules/network.nix index 0f4ee9e..be9b307 100644 --- a/modules/network.nix +++ b/modules/network.nix @@ -24,6 +24,9 @@ in { usePredictableInterfaceNames = false; hostName = config.device; }; + + persist.state.directories = [ "/etc/NetworkManager/system-connections" ]; + networking.firewall.trustedInterfaces = [ "eth0" ]; systemd.services.ModemManager.wantedBy = lib.optional (config.device == "T490s-Laptop") "network.target"; diff --git a/modules/nix.nix b/modules/nix.nix index 408a7e2..f9e8928 100644 --- a/modules/nix.nix +++ b/modules/nix.nix @@ -22,6 +22,9 @@ ''; requireSignedBinaryCaches = true; }; + + persist.state.homeFiles = [ ".local/share/nix/repl-history" ]; + environment.etc.nixpkgs.source = inputs.nixpkgs; environment.etc.self.source = inputs.self; } diff --git a/modules/persist.nix b/modules/persist.nix new file mode 100644 index 0000000..d813010 --- /dev/null +++ b/modules/persist.nix @@ -0,0 +1,133 @@ +{ config, pkgs, lib, inputs, ... }: +let + cfg = config.persist; + + takeAll = what: builtins.concatMap (x: x.${what}); + + persists = with cfg; [ state derivative cache ]; + + absoluteHomeFiles = map (x: "${cfg.homeDir}/${x}"); + + allHomeFiles = takeAll "homeFiles" persists; + + absoluteEtcFiles = map (x: "/etc/${x}"); + + allEtcFiles = absoluteEtcFiles (takeAll "etcFiles" persists); + + allDirectories = takeAll "directories" persists; +in { + options = with lib; + with types; + let + common = { + directories = mkOption { + type = listOf path; + default = [ ]; + }; + etcFiles = mkOption { + type = listOf str; + default = [ ]; + }; + homeFiles = mkOption { + type = listOf str; + default = [ ]; + }; + }; + in { + persist = { + + enable = mkEnableOption "a tmpfs root with explicit opt-in state"; + + persistRoot = mkOption { + type = path; + default = "/persist"; + }; + + homeDir = mkOption { + type = path; + default = "/home/balsoft"; + }; + + # Stuff that matters + # TODO backups of this stuff + state = { + # backup = {...}; + } // common; + + # Stuff that can be computed from declarative+state, but is never invalidated (so shouldn't be cleaned up) + derivative = common; + + # Stuff that's just there to speed up the system + # It's cleaned up regularly, to solve the cache invalidation problem once and for all + cache = { + clean = { + enable = mkEnableOption "cleaning the cache files and directories"; + dates = mkOption { + type = str; + default = "weekly"; + description = + "A systemd.time calendar description of when to clean the cache files"; + }; + }; + } // common; + + }; + }; + + imports = [ + inputs.impermanence.nixosModules.impermanence + # Eugh + (let + module = (import "${inputs.impermanence}/home-manager.nix" { + inherit pkgs lib; + config = lib.recursiveUpdate config.home-manager.users.balsoft { + home.persistence."${cfg.persistRoot}${cfg.homeDir}" = { + directories = [ ]; + files = allHomeFiles; + allowOther = false; + removePrefixDirectory = false; + }; + }; + }); + in { + config.home-manager.users.balsoft = lib.mkIf cfg.enable module.config; + }) + ]; + + config = lib.mkIf cfg.enable { + environment.persistence.${cfg.persistRoot} = { + directories = allDirectories; + files = allEtcFiles; + }; + + fileSystems."/" = { + device = "none"; + options = [ "defaults" "size=4G" "mode=755" ]; + fsType = "tmpfs"; + }; + + boot.initrd.postMountCommands = assert + config.fileSystems ? ${cfg.persistRoot} + && config.fileSystems.${cfg.persistRoot}.neededForBoot; + '' + mkdir -p /mnt-root/nix + mount --bind /mnt-root${cfg.persistRoot}/nix /mnt-root/nix + chmod 755 /mnt-root + ''; + + # Euuuugh + systemd.services.persist-cache-cleanup = lib.mkIf cfg.cache.clean.enable { + description = "Cleaning up cache files and directories"; + script = '' + ${builtins.concatStringsSep "\n" (map (x: "rm ${lib.escapeShellArg x}") + (absoluteEtcFiles cfg.cache.etcFiles + ++ absoluteHomeFiles cfg.cache.homeFiles))} + + ${builtins.concatStringsSep "\n" + (map (x: "rm -rf ${lib.escapeShellArg x}") cfg.cache.directories)} + ''; + startAt = cfg.cache.clean.dates; + }; + + }; +} diff --git a/modules/secrets.nix b/modules/secrets.nix index 0b21a7d..db30040 100755 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -124,6 +124,9 @@ in { }]; }]; + config.persist.derivative.directories = + [ "/var/secrets" "/home/balsoft/.password-store" ]; + config.home-manager.users.balsoft = { wayland.windowManager.sway = { config.startup = [{ command = "activate-secrets"; }]; diff --git a/modules/workspace/gnome3/default.nix b/modules/workspace/gnome3/default.nix index f46be20..4a88499 100644 --- a/modules/workspace/gnome3/default.nix +++ b/modules/workspace/gnome3/default.nix @@ -15,11 +15,21 @@ environment.sessionVariables.XDG_CURRENT_DESKTOP = "X-Generic"; + persist.state.directories = map (x: "/home/balsoft/${x}") [ + "Pictures" + "Documents" + "Downloads" + "Music" + "projects" + "Videos" + ]; services.gvfs.enable = true; services.geoclue2.enable = true; home-manager.users.balsoft = { xdg.userDirs.enable = true; + + home.activation.gnome = '' $DRY_RUN_CMD mkdir -p "$XDG_DATA_HOME/keyrings" $DRY_RUN_CMD ln -sf ${config.secrets-envsubst.gnome-keyring} "$XDG_DATA_HOME/keyrings/Default_keyring.keyring" diff --git a/modules/workspace/gpg.nix b/modules/workspace/gpg.nix index 91d3adf..10fb590 100644 --- a/modules/workspace/gpg.nix +++ b/modules/workspace/gpg.nix @@ -2,6 +2,8 @@ services.pcscd.enable = true; services.udev.packages = [ pkgs.yubikey-personalization ]; + persist.derivative.directories = [ "/home/balsoft/.local/share/gnupg" ]; + home-manager.users.balsoft = { services.gpg-agent = { enable = true; diff --git a/modules/workspace/misc.nix b/modules/workspace/misc.nix index 8f96a78..64547e6 100644 --- a/modules/workspace/misc.nix +++ b/modules/workspace/misc.nix @@ -29,6 +29,8 @@ home.stateVersion = "20.09"; }; + + services.avahi.enable = true; system.stateVersion = "18.03"; diff --git a/modules/workspace/ssh.nix b/modules/workspace/ssh.nix index f5ec6d0..f94a189 100644 --- a/modules/workspace/ssh.nix +++ b/modules/workspace/ssh.nix @@ -8,6 +8,13 @@ ports = [ 22 ]; }; + persist.state.etcFiles = [ + "ssh/ssh_host_ed25519_key" + "ssh/ssh_host_ed25519_key.pub" + "ssh/ssh_host_rsa_key" + "ssh/ssh_host_rsa_key.pub" + ]; + users.users.balsoft.openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDd2OdcSHUsgezuV+cpFqk9+Svtup6PxIolv1zokVZdqvS8qxLsA/rwYmQgTnuq4/zK/GIxcUCH4OxYlW6Or4M4G7qrDKcLAUrRPWkectqEooWRflZXkfHduMJhzeOAsBdMfYZQ9024GwKr/4yriw2BGa8GbbAnQxiSeTipzvXHoXuRME+/2GsMFAfHFvxzXRG7dNOiLtLaXEjUPUTcw/fffKy55kHtWxMkEvvcdyR53/24fmO3kLVpEuoI+Mp1XFtX3DvRM9ulgfwZUn8/CLhwSLwWX4Xf9iuzVi5vJOJtMOktQj/MwGk4tY/NPe+sIk+nAUKSdVf0y9k9JrJT98S/ comment"]; diff --git a/modules/workspace/zsh.nix b/modules/workspace/zsh.nix index d269fc8..4e24393 100755 --- a/modules/workspace/zsh.nix +++ b/modules/workspace/zsh.nix @@ -2,6 +2,9 @@ environment.pathsToLink = [ "/share/zsh" ]; environment.sessionVariables.SHELL = "zsh"; + + persist.state.homeFiles = [ ".zsh_history" ]; + home-manager.users.balsoft.programs.zsh = { enable = true; enableAutosuggestions = true; diff --git a/profiles/base.nix b/profiles/base.nix index 479db5c..561596f 100644 --- a/profiles/base.nix +++ b/profiles/base.nix @@ -6,16 +6,17 @@ secrets secrets-envsubst - locale - network - overlay devices - nix - security - ssh git gpg - zsh + locale misc + network + nix + overlay + persist + security + ssh + zsh ]; } diff --git a/profiles/desktop.nix b/profiles/desktop.nix index e162718..ba439c7 100644 --- a/profiles/desktop.nix +++ b/profiles/desktop.nix @@ -14,6 +14,7 @@ firefox geary himalaya + nheko packages yt-utilities