From 46285852d01b599cadb71841afc7ef66ae59e9a5 Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 2 Feb 2023 12:31:13 +0000 Subject: [PATCH] modules: add a `sane.programs` interface which i can use going forward in place of `sane.packages` --- hosts/common/default.nix | 2 +- hosts/common/programs.nix | 76 +++++++++++++++++++++++++ modules/default.nix | 1 + modules/packages.nix | 50 ----------------- modules/programs.nix | 115 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 51 deletions(-) create mode 100644 hosts/common/programs.nix create mode 100644 modules/programs.nix diff --git a/hosts/common/default.nix b/hosts/common/default.nix index 3b15c50d..f8612e95 100644 --- a/hosts/common/default.nix +++ b/hosts/common/default.nix @@ -11,6 +11,7 @@ ./machine-id.nix ./net.nix ./persist.nix + ./programs.nix ./secrets.nix ./ssh.nix ./users.nix @@ -19,7 +20,6 @@ sane.nixcache.enable-trusted-keys = true; sane.packages.enableConsolePkgs = true; - sane.packages.enableSystemPkgs = true; # some services which use private directories error if the parent (/var/lib/private) isn't 700. sane.fs."/var/lib/private".dir.acl.mode = "0700"; diff --git a/hosts/common/programs.nix b/hosts/common/programs.nix new file mode 100644 index 00000000..a677a322 --- /dev/null +++ b/hosts/common/programs.nix @@ -0,0 +1,76 @@ +{ lib, pkgs, sane-lib, ... }: + +let + inherit (builtins) concatLists; + inherit (lib) mapAttrsToList; + systemPkgs = { + inherit (pkgs // { + # XXX can't `inherit` a nested attr, so we move them to the toplevel + "cacert.unbundled" = pkgs.cacert.unbundled; + }) + btrfs-progs + "cacert.unbundled" # some services require unbundled /etc/ssl/certs + cryptsetup + dig + efibootmgr + fatresize + fd + file + gawk + git + gptfdisk + hdparm + htop + iftop + inetutils # for telnet + iotop + iptables + jq + killall + lsof + nano + netcat + nethogs + nmap + openssl + parted + pciutils + powertop + pstree + ripgrep + screen + smartmontools + socat + strace + tcpdump + tree + usbutils + wget + ; + }; + + enableSysPkg = pname: pkg: { + sane.programs."${pname}" = { + package = pkg; + enableFor.system = true; + }; + }; + + configs = concatLists [ + (mapAttrsToList enableSysPkg systemPkgs) + [{ + # XXX: this might not be necessary. try removing this and cacert.unbundled (servo)? + environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*"; + }] + ]; +in +{ + config = + let + take = f: { + sane.programs = f.sane.programs; + environment.etc = f.environment.etc; + }; + in + take (sane-lib.mkTypedMerge take configs); +} diff --git a/modules/default.nix b/modules/default.nix index 47785b95..05344db4 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -6,6 +6,7 @@ ./fs ./ids.nix ./packages.nix + ./programs.nix ./image.nix ./persist ./services diff --git a/modules/packages.nix b/modules/packages.nix index 5bfabc2f..622a2d56 100644 --- a/modules/packages.nix +++ b/modules/packages.nix @@ -197,48 +197,6 @@ let { pkg = zecwallet-lite; private = [ ".zcash" ]; } ] else []); - # general-purpose utilities that we want any user to be able to access - # (specifically: root, in case of rescue) - systemPkgs = [ - btrfs-progs - cacert.unbundled # some services require unbundled /etc/ssl/certs - cryptsetup - dig - efibootmgr - fatresize - fd - file - gawk - git - gptfdisk - hdparm - htop - iftop - inetutils # for telnet - iotop - iptables - jq - killall - lsof - nano - netcat - nethogs - nmap - openssl - parted - pciutils - powertop - pstree - ripgrep - screen - smartmontools - socat - strace - tcpdump - tree - usbutils - wget - ]; # useful devtools: devPkgs = [ @@ -304,11 +262,6 @@ in default = false; type = types.bool; }; - sane.packages.enableSystemPkgs = mkOption { - default = false; - type = types.bool; - description = "enable system-wide packages"; - }; sane.packages.enabledUserPkgs = mkOption { default = cfg.extraUserPkgs @@ -322,10 +275,7 @@ in }; config = { - environment.systemPackages = mkIf cfg.enableSystemPkgs systemPkgs; sane.user.persist.plaintext = concatLists (map (p: p.dir) cfg.enabledUserPkgs); sane.user.persist.private = concatLists (map (p: p.private) cfg.enabledUserPkgs); - # XXX: this might not be necessary. try removing this and cacert.unbundled? - environment.etc."ssl/certs".source = mkIf cfg.enableSystemPkgs "${pkgs.cacert.unbundled}/etc/ssl/certs/*"; }; } diff --git a/modules/programs.nix b/modules/programs.nix new file mode 100644 index 00000000..5654cb80 --- /dev/null +++ b/modules/programs.nix @@ -0,0 +1,115 @@ +{ config, lib, pkgs, sane-lib, ... }: +let + inherit (builtins) any elem map; + inherit (lib) + filterAttrs + hasAttrByPath + getAttrFromPath + mapAttrs + mapAttrsToList + mkDefault + mkIf + mkOption + optionalAttrs + splitString + types + ; + inherit (sane-lib) joinAttrsets; + cfg = config.sane.programs; + pkgSpec = types.submodule ({ name, ... }: { + options = { + package = mkOption { + type = types.package; + }; + enableFor.system = mkOption { + type = types.bool; + default = any (en: en) ( + mapAttrsToList + (otherName: otherPkg: + otherName != name && elem name otherPkg.suggestedPrograms && otherPkg.enableSuggested && otherPkg.enableFor.system + ) + cfg + ); + description = '' + place this program on the system PATH + ''; + }; + enableFor.user = mkOption { + type = types.attrsOf types.bool; + default = joinAttrsets (mapAttrsToList (otherName: otherPkg: + optionalAttrs + (otherName != name && elem name otherPkg.suggestedPrograms && otherPkg.enableSuggested) + (filterAttrs (user: en: en) otherPkg.enableFor.user) + ) cfg); + description = '' + place this program on the PATH for some specified user(s). + ''; + }; + suggestedPrograms = mkOption { + type = types.listOf types.str; + default = []; + description = '' + list of other programs a user may want to enable alongside this one. + for example, the gnome desktop environment would suggest things like its settings app. + ''; + }; + enableSuggested = mkOption { + type = types.bool; + default = true; + }; + dir = mkOption { + type = types.listOf types.str; + default = []; + description = "list of home-relative paths to persist for this package"; + }; + private = mkOption { + type = types.listOf types.str; + default = []; + description = "list of home-relative paths to persist (in encrypted format) for this package"; + }; + }; + + config = + let + pkgPath = splitString "." name; + in { + # package can be inferred by the attr name, allowing shorthand like + # `sane.packages.nano.enable = true;` + package = mkIf (hasAttrByPath pkgPath pkgs) (mkDefault (getAttrFromPath pkgPath pkgs)); + }; + + }); + toPkgSpec = types.coercedTo types.package (p: { package = p; }) pkgSpec; + + configs = mapAttrsToList (_name: p: { + # conditionally add to system PATH + environment.systemPackages = mkIf p.enableFor.system [ p.package ]; + # conditionally add to user(s) PATH + users.users = mapAttrs (user: en: optionalAttrs en { + packages = [ p.package ]; + }) p.enableFor.user; + # conditionally persist relevant user dirs + sane.users = mapAttrs (user: en: optionalAttrs en { + persist.plaintext = p.dir; + persist.private = p.private; + }) p.enableFor.user; + }) cfg; +in +{ + options = { + sane.programs = mkOption { + type = types.attrsOf toPkgSpec; + default = {}; + }; + }; + + config = + let + take = f: { + environment.systemPackages = f.environment.systemPackages; + users.users = f.users.users; + sane.users = f.sane.users; + }; + in + take (sane-lib.mkTypedMerge take configs); +}