{ config, lib, libS, pkgs, ... }: let cfg = config.nix; in { options.nix = { deleteChannels = lib.mkEnableOption "" // { description = "Whether to delete all channels on a system switch."; }; deleteUserProfiles = lib.mkEnableOption "" // { description = "Whether to delete all user profiles on a system switch."; }; diffSystem = libS.mkOpinionatedOption "system closure diffing on updates"; recommendedDefaults = libS.mkOpinionatedOption "set recommended default settings"; remoteBuilder = { enable = lib.mkEnableOption "restricted nix remote builder"; sshPublicKeys = lib.mkOption { description = "SSH public keys accepted by the remote build user."; type = lib.types.listOf lib.types.str; }; name = lib.mkOption { description = "Name of the user used for remote building."; type = lib.types.str; readOnly = true; default = "nix-remote-builder"; }; }; }; config = { # based on https://github.com/numtide/srvos/blob/main/nixos/roles/nix-remote-builder.nix # and https://discourse.nixos.org/t/wrapper-to-restrict-builder-access-through-ssh-worth-upstreaming/25834 nix.settings = { builders-use-substitutes = lib.mkIf cfg.recommendedDefaults true; connect-timeout = lib.mkIf cfg.recommendedDefaults 20; experimental-features = lib.mkIf cfg.recommendedDefaults [ "nix-command" "flakes" ]; trusted-users = lib.mkIf cfg.remoteBuilder.enable [ cfg.remoteBuilder.name ]; }; users.users.${cfg.remoteBuilder.name} = lib.mkIf cfg.remoteBuilder.enable { group = "nogroup"; isNormalUser = true; openssh.authorizedKeys.keys = map (key: let wrapper-dispatch-ssh-nix = pkgs.writeShellScriptBin "wrapper-dispatch-ssh-nix" /* bash */ '' case $SSH_ORIGINAL_COMMAND in "nix-daemon --stdio") exec ${config.nix.package}/bin/nix-daemon --stdio ;; "nix-store --serve --write") exec ${config.nix.package}/bin/nix-store --serve --write ;; *) echo "Access is only allowed for the nix remote builder" 1>&2 exit 1 esac ''; in "restrict,pty,command=\"${wrapper-dispatch-ssh-nix}/bin/wrapper-dispatch-ssh-nix\" ${key}" ) config.nix.remoteBuilder.sshPublicKeys; }; system.activationScripts = { deleteChannels = lib.mkIf cfg.deleteChannels '' echo "Deleting all channels..." rm -rf /root/.nix-channels /home/*/.nix-channels /nix/var/nix/profiles/per-user/*/channels* || true ''; deleteUserProfiles = lib.mkIf cfg.deleteUserProfiles '' echo "Deleting all user profiles..." rm -rf /root/.nix-profile /home/*/.nix-profile /nix/var/nix/profiles/per-user/*/profile* || true ''; diff-system = lib.mkIf cfg.diffSystem { supportsDryActivation = true; text = '' if [[ -e /run/current-system && -e $systemConfig ]]; then echo System package diff: ${lib.getExe config.nix.package} --extra-experimental-features nix-command store diff-closures /run/current-system $systemConfig || true fi ''; }; }; }; }