nixos-installer/modules/base.nix.md
Niklas Gollenstede f56db19b5e improve installation, add support for:
ZFS, encryption (keys, keystore, LUKS), bootFS, ephemeral root (tmpfs, ZFS, F2FS, ...), testing in qemu, options & debugging, ... and many small things
2022-05-31 03:41:28 +02:00

4.7 KiB

/*

System Defaults

Things that really should be (more like) this by default.

Implementation

#*/# end of MarkDown, beginning of NixOS module:
dirname: inputs: specialArgs@{ config, pkgs, lib, ... }: let inherit (inputs.self) lib; in let
    prefix = inputs.config.prefix;
    cfg = config.${prefix}.base;
in {

    options.${prefix} = { base = {
        enable = lib.mkEnableOption "saner defaults";
        includeNixpkgs = lib.mkOption { description = "»nixpkgs« to include in the system build."; type = lib.types.nullOr lib.types.package; default = null; };
    }; };

    config = let
        hash = builtins.substring 0 8 (builtins.hashString "sha256" config.networking.hostName);
        implied = true; # some mount points are implied (and forced) to be »neededForBoot« in »specialArgs.utils.pathsNeededForBoot« (this marks those here)

    in lib.mkIf cfg.enable (lib.mkMerge [ ({

        users.mutableUsers = false; users.allowNoPasswordLogin = true; # Don't babysit. Can roll back or redeploy.
        networking.hostId = lib.mkDefault (builtins.substring 0 8 (builtins.hashString "sha256" config.networking.hostName));
        environment.etc."machine-id".text = lib.mkDefault (builtins.substring 0 32 (builtins.hashString "sha256" "${config.networking.hostName}:machine-id")); # this works, but it "should be considered "confidential", and must not be exposed in untrusted environments" (not sure _why_ though)
        documentation.man.enable = lib.mkDefault config.documentation.enable;


    }) ({
        # Robustness/debugging:

        boot.kernelParams = [ "panic=10" "boot.panic_on_fail" ]; # Reboot on kernel panic, panic if boot fails.
        # might additionally want to do this: https://stackoverflow.com/questions/62083796/automatic-reboot-on-systemd-emergency-mode
        systemd.extraConfig = "StatusUnitFormat=name"; # Show unit names instead of descriptions during boot.


    }) (lib.mkIf (cfg.includeNixpkgs != null) {

        nix.registry.nixpkgs.flake = cfg.includeNixpkgs;
        environment.etc."nix/channels/nixpkgs".source = cfg.includeNixpkgs.outPath;
        nix.nixPath = [ "nixpkgs=/etc/nix/channels/nixpkgs" "nixos-config=/etc/nixos" ];
        nix.extraOptions = "experimental-features = nix-command flakes"; # apparently, even nix 2.8 (in nixos-22.05) needs this
        environment.shellAliases = { "with" = ''nix-shell --run "bash --login" -p''; };
        system.extraSystemBuilderCmds = (if !specialArgs?inputs && !specialArgs.inputs?self then "" else ''
            ln -sT ${specialArgs.inputs.self.outPath} $out/config # (build input for reference)
        '');
        environment.systemPackages = [ pkgs.git ]; # necessary as external dependency when working with flakes


    }) ({
        # Free convenience:

        programs.bash.promptInit = lib.mkDefault ''
        # Provide a nice prompt if the terminal supports it.
        if [ "''${TERM:-}" != "dumb" ] ; then
            if [[ "$UID" == '0' ]] ; then if [[ ! "''${SUDO_USER:-}" ]] ; then # direct root: red username + green hostname
                PS1='\[\e[0m\]\[\e[48;5;234m\]\[\e[96m\]$(printf "%-+ 4d" $?)\[\e[93m\][\D{%Y-%m-%d %H:%M:%S}] \[\e[91m\]\u\[\e[97m\]@\[\e[92m\]\h\[\e[97m\]:\[\e[96m\]\w'"''${TERM_RECURSION_DEPTH:+\[\e[91m\]["$TERM_RECURSION_DEPTH"]}"'\[\e[24;97m\]\$ \[\e[0m\]'
            else # sudo root: red username + red hostname
                PS1='\[\e[0m\]\[\e[48;5;234m\]\[\e[96m\]$(printf "%-+ 4d" $?)\[\e[93m\][\D{%Y-%m-%d %H:%M:%S}] \[\e[91m\]\u\[\e[97m\]@\[\e[91m\]\h\[\e[97m\]:\[\e[96m\]\w'"''${TERM_RECURSION_DEPTH:+\[\e[91m\]["$TERM_RECURSION_DEPTH"]}"'\[\e[24;97m\]\$ \[\e[0m\]'
            fi ; else # other user: green username + green hostname
                PS1='\[\e[0m\]\[\e[48;5;234m\]\[\e[96m\]$(printf "%-+ 4d" $?)\[\e[93m\][\D{%Y-%m-%d %H:%M:%S}] \[\e[92m\]\u\[\e[97m\]@\[\e[92m\]\h\[\e[97m\]:\[\e[96m\]\w'"''${TERM_RECURSION_DEPTH:+\[\e[91m\]["$TERM_RECURSION_DEPTH"]}"'\[\e[24;97m\]\$ \[\e[0m\]'
            fi
            if test "$TERM" = "xterm" ; then
                PS1="\[\033]2;\h:\u:\w\007\]$PS1"
            fi
        fi
        export TERM_RECURSION_DEPTH=$(( 1 + ''${TERM_RECURSION_DEPTH:-0} ))
        ''; # The non-interactive version of bash does not remove »\[« and »\]« from PS1, but without those the terminal gets confused about the cursor position after the prompt once one types more than a bit of text there, at least via serial or SSH.

        environment.interactiveShellInit = lib.mkDefault ''
            if [[ "$(realpath /dev/stdin)" == /dev/ttyS* && $LINES == 24 && $COLUMNS == 80 ]] ; then
                stty rows 34 cols 145 # Fairly large font on 1080p. Definitely a better default than 24x80.
            fi
        '';

    }) ]);

}