diff options
Diffstat (limited to 'nixos/modules/config')
22 files changed, 439 insertions, 175 deletions
diff --git a/nixos/modules/config/console.nix b/nixos/modules/config/console.nix index f662ed62d31..c5150305bd8 100644 --- a/nixos/modules/config/console.nix +++ b/nixos/modules/config/console.nix @@ -43,13 +43,14 @@ in options.console = { font = mkOption { - type = types.str; + type = with types; either str path; default = "Lat2-Terminus16"; example = "LatArCyrHeb-16"; description = '' The font used for the virtual consoles. Leave empty to use whatever the <command>setfont</command> program considers the default font. + Can be either a font name or a path to a PSF font file. ''; }; @@ -82,28 +83,13 @@ in packages = mkOption { type = types.listOf types.package; - default = with pkgs.kbdKeymaps; [ dvp neo ]; - defaultText = ''with pkgs.kbdKeymaps; [ dvp neo ]''; + default = [ ]; description = '' List of additional packages that provide console fonts, keymaps and other resources for virtual consoles use. ''; }; - extraTTYs = mkOption { - default = []; - type = types.listOf types.str; - example = ["tty8" "tty9"]; - description = '' - TTY (virtual console) devices, in addition to the consoles on - which mingetty and syslogd run, that must be initialised. - Only useful if you have some program that you want to run on - some fixed console. For example, the NixOS installation CD - opens the manual in a web browser on console 7, so it sets - <option>console.extraTTYs</option> to <literal>["tty7"]</literal>. - ''; - }; - useXkbConfig = mkOption { type = types.bool; default = false; @@ -158,10 +144,16 @@ in ''} ''; - systemd.services.systemd-vconsole-setup = - { before = [ "display-manager.service" ]; - after = [ "systemd-udev-settle.service" ]; + systemd.services.reload-systemd-vconsole-setup = + { description = "Reset console on configuration changes"; + wantedBy = [ "multi-user.target" ]; restartTriggers = [ vconsoleConf consoleEnv ]; + reloadIfChanged = true; + serviceConfig = + { RemainAfterExit = true; + ExecStart = "${pkgs.coreutils}/bin/true"; + ExecReload = "/run/current-system/systemd/bin/systemctl restart systemd-vconsole-setup"; + }; }; } @@ -199,5 +191,9 @@ in (mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ]) (mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ]) (mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ]) + (mkRemovedOptionModule [ "console" "extraTTYs" ] '' + Since NixOS switched to systemd (circa 2012), TTYs have been spawned on + demand, so there is no need to configure them manually. + '') ]; } diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix index 1f1044bc5af..72827c5abaa 100644 --- a/nixos/modules/config/fonts/fontconfig.nix +++ b/nixos/modules/config/fonts/fontconfig.nix @@ -1,6 +1,6 @@ /* -Configuration files are linked to /etc/fonts/${pkgs.fontconfig.configVersion}/conf.d/ +Configuration files are linked to /etc/fonts/conf.d/ This module generates a package containing configuration files and link it in /etc/fonts. @@ -35,7 +35,7 @@ let in pkgs.writeText "fc-00-nixos-cache.conf" '' <?xml version='1.0'?> - <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> + <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'> <fontconfig> <!-- Font directories --> ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)} @@ -53,7 +53,7 @@ let # priority 10 renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" '' <?xml version='1.0'?> - <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> + <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'> <fontconfig> <!-- Default rendering settings --> @@ -110,7 +110,7 @@ let in pkgs.writeText "fc-52-nixos-default-fonts.conf" '' <?xml version='1.0'?> - <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> + <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'> <fontconfig> <!-- Default fonts --> @@ -129,7 +129,7 @@ let # priority 53 rejectBitmaps = pkgs.writeText "fc-53-no-bitmaps.conf" '' <?xml version="1.0"?> - <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> + <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> ${optionalString (!cfg.allowBitmaps) '' @@ -157,7 +157,7 @@ let # priority 53 rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" '' <?xml version="1.0"?> - <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> + <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> <fontconfig> <!-- Reject Type 1 fonts --> @@ -176,15 +176,16 @@ let confPkg = pkgs.runCommand "fontconfig-conf" { preferLocalBuild = true; } '' - dst=$out/etc/fonts/${pkg.configVersion}/conf.d + dst=$out/etc/fonts/conf.d mkdir -p $dst # fonts.conf ln -s ${pkg.out}/etc/fonts/fonts.conf \ $dst/../fonts.conf # TODO: remove this legacy symlink once people stop using packages built before #95358 was merged - ln -s /etc/fonts/${pkg.configVersion}/fonts.conf \ - $out/etc/fonts/fonts.conf + mkdir -p $out/etc/fonts/2.11 + ln -s /etc/fonts/fonts.conf \ + $out/etc/fonts/2.11/fonts.conf # fontconfig default config files ln -s ${pkg.out}/etc/fonts/conf.d/*.conf \ @@ -197,10 +198,8 @@ let ln -s ${renderConf} $dst/10-nixos-rendering.conf # 50-user.conf - # Since latest fontconfig looks for default files inside the package, - # we had to move this one elsewhere to be able to exclude it here. - ${optionalString cfg.includeUserConf '' - ln -s ${pkg.out}/etc/fonts/conf.d.bak/50-user.conf $dst/50-user.conf + ${optionalString (!cfg.includeUserConf) '' + rm $dst/50-user.conf ''} # local.conf (indirect priority 51) @@ -437,7 +436,7 @@ in useEmbeddedBitmaps = mkOption { type = types.bool; default = false; - description = ''Use embedded bitmaps in fonts like Calibri.''; + description = "Use embedded bitmaps in fonts like Calibri."; }; }; @@ -449,6 +448,40 @@ in (mkIf cfg.enable { environment.systemPackages = [ pkgs.fontconfig ]; environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/"; + security.apparmor.includes."abstractions/fonts" = '' + # fonts.conf + r ${pkg.out}/etc/fonts/fonts.conf, + + # fontconfig default config files + r ${pkg.out}/etc/fonts/conf.d/*.conf, + + # 00-nixos-cache.conf + r ${cacheConf}, + + # 10-nixos-rendering.conf + r ${renderConf}, + + # 50-user.conf + ${optionalString cfg.includeUserConf '' + r ${pkg.out}/etc/fonts/conf.d.bak/50-user.conf, + ''} + + # local.conf (indirect priority 51) + ${optionalString (cfg.localConf != "") '' + r ${localConf}, + ''} + + # 52-nixos-default-fonts.conf + r ${defaultFontsConf}, + + # 53-no-bitmaps.conf + r ${rejectBitmaps}, + + ${optionalString (!cfg.allowType1) '' + # 53-nixos-reject-type1.conf + r ${rejectType1}, + ''} + ''; }) (mkIf cfg.enable { fonts.fontconfig.confPackages = [ confPkg ]; diff --git a/nixos/modules/config/fonts/fontdir.nix b/nixos/modules/config/fonts/fontdir.nix index a6aa84ae822..c4bd3a077d3 100644 --- a/nixos/modules/config/fonts/fontdir.nix +++ b/nixos/modules/config/fonts/fontdir.nix @@ -4,15 +4,19 @@ with lib; let + cfg = config.fonts.fontDir; + x11Fonts = pkgs.runCommand "X11-fonts" { preferLocalBuild = true; } '' - mkdir -p "$out/share/X11-fonts" - find ${toString config.fonts.fonts} \ - \( -name fonts.dir -o -name '*.ttf' -o -name '*.otf' \) \ - -exec ln -sf -t "$out/share/X11-fonts" '{}' \; - cd "$out/share/X11-fonts" - rm -f fonts.dir fonts.scale fonts.alias - ${pkgs.xorg.mkfontdir}/bin/mkfontdir + mkdir -p "$out/share/X11/fonts" + font_regexp='.*\.\(ttf\|ttc\|otf\|pcf\|pfa\|pfb\|bdf\)\(\.gz\)?' + find ${toString config.fonts.fonts} -regex "$font_regexp" \ + -exec ln -sf -t "$out/share/X11/fonts" '{}' \; + cd "$out/share/X11/fonts" + ${optionalString cfg.decompressFonts '' + ${pkgs.gzip}/bin/gunzip -f *.gz + ''} ${pkgs.xorg.mkfontscale}/bin/mkfontscale + ${pkgs.xorg.mkfontdir}/bin/mkfontdir cat $(find ${pkgs.xorg.fontalias}/ -name fonts.alias) >fonts.alias ''; @@ -21,28 +25,43 @@ in { options = { + fonts.fontDir = { - fonts = { - - enableFontDir = mkOption { + enable = mkOption { type = types.bool; default = false; description = '' Whether to create a directory with links to all fonts in - <filename>/run/current-system/sw/share/X11-fonts</filename>. + <filename>/run/current-system/sw/share/X11/fonts</filename>. ''; }; - }; + decompressFonts = mkOption { + type = types.bool; + default = config.programs.xwayland.enable; + description = '' + Whether to decompress fonts in + <filename>/run/current-system/sw/share/X11/fonts</filename>. + ''; + }; + }; }; - config = mkIf config.fonts.enableFontDir { + config = mkIf cfg.enable { + # This is enough to make a symlink because the xserver + # module already links all /share/X11 paths. environment.systemPackages = [ x11Fonts ]; - environment.pathsToLink = [ "/share/X11-fonts" ]; + services.xserver.filesSection = '' + FontPath "${x11Fonts}/share/X11/fonts" + ''; }; + imports = [ + (mkRenamedOptionModule [ "fonts" "enableFontDir" ] [ "fonts" "fontDir" "enable" ]) + ]; + } diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix index b9bae44b2f9..3911196c101 100644 --- a/nixos/modules/config/fonts/fonts.nix +++ b/nixos/modules/config/fonts/fonts.nix @@ -35,19 +35,21 @@ with lib; config = { fonts.fonts = mkIf config.fonts.enableDefaultFonts - [ - pkgs.xorg.fontbhlucidatypewriter100dpi - pkgs.xorg.fontbhlucidatypewriter75dpi + ([ pkgs.dejavu_fonts pkgs.freefont_ttf pkgs.gyre-fonts # TrueType substitutes for standard PostScript fonts pkgs.liberation_ttf - pkgs.xorg.fontbh100dpi pkgs.xorg.fontmiscmisc pkgs.xorg.fontcursormisc pkgs.unifont pkgs.noto-fonts-emoji - ]; + ] ++ lib.optionals (config.nixpkgs.config.allowUnfree or false) [ + # these are unfree, and will make usage with xserver fail + pkgs.xorg.fontbhlucidatypewriter100dpi + pkgs.xorg.fontbhlucidatypewriter75dpi + pkgs.xorg.fontbh100dpi + ]); }; diff --git a/nixos/modules/config/gnu.nix b/nixos/modules/config/gnu.nix index 93d13097019..255d9741ba7 100644 --- a/nixos/modules/config/gnu.nix +++ b/nixos/modules/config/gnu.nix @@ -1,11 +1,9 @@ { config, lib, pkgs, ... }: -with lib; - { options = { - gnu = mkOption { - type = types.bool; + gnu = lib.mkOption { + type = lib.types.bool; default = false; description = '' When enabled, GNU software is chosen by default whenever a there is @@ -15,7 +13,7 @@ with lib; }; }; - config = mkIf config.gnu { + config = lib.mkIf config.gnu { environment.systemPackages = with pkgs; # TODO: Adjust `requiredPackages' from `system-path.nix'. @@ -26,7 +24,7 @@ with lib; nano zile texinfo # for the stand-alone Info reader ] - ++ stdenv.lib.optional (!stdenv.isAarch32) grub2; + ++ lib.optional (!stdenv.isAarch32) grub2; # GNU GRUB, where available. diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix index feb76581a72..991b449d80b 100644 --- a/nixos/modules/config/i18n.nix +++ b/nixos/modules/config/i18n.nix @@ -84,7 +84,7 @@ with lib; environment.etc."locale.conf".source = pkgs.writeText "locale.conf" '' LANG=${config.i18n.defaultLocale} - ${concatStringsSep "\n" (mapAttrsToList (n: v: ''${n}=${v}'') config.i18n.extraLocaleSettings)} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") config.i18n.extraLocaleSettings)} ''; }; diff --git a/nixos/modules/config/iproute2.nix b/nixos/modules/config/iproute2.nix index a1d9ebcec66..5f41f3d21e4 100644 --- a/nixos/modules/config/iproute2.nix +++ b/nixos/modules/config/iproute2.nix @@ -18,15 +18,15 @@ in }; config = mkIf cfg.enable { - environment.etc."iproute2/bpf_pinning" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/bpf_pinning"; }; - environment.etc."iproute2/ematch_map" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/ematch_map"; }; - environment.etc."iproute2/group" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/group"; }; - environment.etc."iproute2/nl_protos" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/nl_protos"; }; - environment.etc."iproute2/rt_dsfield" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/rt_dsfield"; }; - environment.etc."iproute2/rt_protos" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/rt_protos"; }; - environment.etc."iproute2/rt_realms" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/rt_realms"; }; - environment.etc."iproute2/rt_scopes" = { mode = "0644"; text = fileContents "${pkgs.iproute}/etc/iproute2/rt_scopes"; }; - environment.etc."iproute2/rt_tables" = { mode = "0644"; text = (fileContents "${pkgs.iproute}/etc/iproute2/rt_tables") + environment.etc."iproute2/bpf_pinning" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/bpf_pinning"; }; + environment.etc."iproute2/ematch_map" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/ematch_map"; }; + environment.etc."iproute2/group" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/group"; }; + environment.etc."iproute2/nl_protos" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/nl_protos"; }; + environment.etc."iproute2/rt_dsfield" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/rt_dsfield"; }; + environment.etc."iproute2/rt_protos" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/rt_protos"; }; + environment.etc."iproute2/rt_realms" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/rt_realms"; }; + environment.etc."iproute2/rt_scopes" = { mode = "0644"; text = fileContents "${pkgs.iproute2}/etc/iproute2/rt_scopes"; }; + environment.etc."iproute2/rt_tables" = { mode = "0644"; text = (fileContents "${pkgs.iproute2}/etc/iproute2/rt_tables") + (optionalString (cfg.rttablesExtraConfig != "") "\n\n${cfg.rttablesExtraConfig}"); }; }; } diff --git a/nixos/modules/config/krb5/default.nix b/nixos/modules/config/krb5/default.nix index ff16ffcf9c6..c2302451d70 100644 --- a/nixos/modules/config/krb5/default.nix +++ b/nixos/modules/config/krb5/default.nix @@ -41,31 +41,30 @@ let value) else value; - mkIndent = depth: concatStrings (builtins.genList (_: " ") (2 * depth)); + indent = " "; - mkRelation = name: value: "${name} = ${mkVal { inherit value; }}"; + mkRelation = name: value: + if (isList value) then + concatMapStringsSep "\n" (mkRelation name) value + else "${name} = ${mkVal value}"; - mkVal = { value, depth ? 0 }: + mkVal = value: if (value == true) then "true" else if (value == false) then "false" else if (isInt value) then (toString value) - else if (isList value) then - concatMapStringsSep " " mkVal { inherit value depth; } else if (isAttrs value) then - (concatStringsSep "\n${mkIndent (depth + 1)}" - ([ "{" ] ++ (mapAttrsToList - (attrName: attrValue: let - mappedAttrValue = mkVal { - value = attrValue; - depth = depth + 1; - }; - in "${attrName} = ${mappedAttrValue}") - value))) + "\n${mkIndent depth}}" + let configLines = concatLists + (map (splitString "\n") + (mapAttrsToList mkRelation value)); + in + (concatStringsSep "\n${indent}" + ([ "{" ] ++ configLines)) + + "\n}" else value; mkMappedAttrsOrString = value: concatMapStringsSep "\n" (line: if builtins.stringLength line > 0 - then "${mkIndent 1}${line}" + then "${indent}${line}" else line) (splitString "\n" (if isAttrs value then @@ -114,7 +113,10 @@ in { { "ATHENA.MIT.EDU" = { admin_server = "athena.mit.edu"; - kdc = "athena.mit.edu"; + kdc = [ + "athena01.mit.edu" + "athena02.mit.edu" + ]; }; }; ''; diff --git a/nixos/modules/config/ldap.nix b/nixos/modules/config/ldap.nix index 1a5dbcd4e26..35813c168fd 100644 --- a/nixos/modules/config/ldap.nix +++ b/nixos/modules/config/ldap.nix @@ -59,30 +59,28 @@ in users.ldap = { - enable = mkOption { - type = types.bool; - default = false; - description = "Whether to enable authentication against an LDAP server."; - }; + enable = mkEnableOption "authentication against an LDAP server"; loginPam = mkOption { type = types.bool; default = true; - description = "Whether to include authentication against LDAP in login PAM"; + description = "Whether to include authentication against LDAP in login PAM."; }; nsswitch = mkOption { type = types.bool; default = true; - description = "Whether to include lookup against LDAP in NSS"; + description = "Whether to include lookup against LDAP in NSS."; }; server = mkOption { + type = types.str; example = "ldap://ldap.example.org/"; description = "The URL of the LDAP server."; }; base = mkOption { + type = types.str; example = "dc=example,dc=org"; description = "The distinguished name of the search base."; }; @@ -129,7 +127,7 @@ in type = types.lines; description = '' Extra configuration options that will be added verbatim at - the end of the nslcd configuration file (nslcd.conf). + the end of the nslcd configuration file (<literal>nslcd.conf(5)</literal>). '' ; } ; @@ -180,7 +178,7 @@ in description = '' Specifies the time limit (in seconds) to use when connecting to the directory server. This is distinct from the time limit - specified in <literal>users.ldap.timeLimit</literal> and affects + specified in <option>users.ldap.timeLimit</option> and affects the initial server connection only. ''; }; @@ -197,7 +195,7 @@ in actually contact the directory server, and it is possible that a malformed configuration file will trigger reconnection. If <literal>soft</literal> is specified, then - <literal>nss_ldap</literal> will return immediately on server + <package>nss_ldap</package> will return immediately on server failure. All hard reconnect policies block with exponential backoff before retrying. ''; @@ -209,10 +207,10 @@ in type = types.lines; description = '' Extra configuration options that will be added verbatim at - the end of the ldap configuration file (ldap.conf). - If <literal>users.ldap.daemon</literal> is enabled, this + the end of the ldap configuration file (<literal>ldap.conf(5)</literal>). + If <option>users.ldap.daemon</option> is enabled, this configuration will not be used. In that case, use - <literal>users.ldap.daemon.extraConfig</literal> instead. + <option>users.ldap.daemon.extraConfig</option> instead. '' ; }; @@ -240,9 +238,9 @@ in ''; }; - system.nssModules = singleton ( + system.nssModules = mkIf cfg.nsswitch (singleton ( if cfg.daemon.enable then nss_pam_ldapd else nss_ldap - ); + )); system.nssDatabases.group = optional cfg.nsswitch "ldap"; system.nssDatabases.passwd = optional cfg.nsswitch "ldap"; @@ -276,7 +274,12 @@ in } >"$conf" mv -fT "$conf" /run/nslcd/nslcd.conf ''; - restartTriggers = [ "/run/nslcd/nslcd.conf" ]; + + restartTriggers = [ + nslcdConfig + cfg.bind.passwordFile + cfg.daemon.rootpwmodpwFile + ]; serviceConfig = { ExecStart = "${nslcdWrapped}/bin/nslcd"; diff --git a/nixos/modules/config/malloc.nix b/nixos/modules/config/malloc.nix index 31a659ee83f..fc35993b5a8 100644 --- a/nixos/modules/config/malloc.nix +++ b/nixos/modules/config/malloc.nix @@ -23,7 +23,7 @@ let }; scudo = { - libPath = "${pkgs.llvmPackages.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so"; + libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so"; description = '' A user-mode allocator based on LLVM Sanitizer’s CombinedAllocator, which aims at providing additional mitigations against heap based @@ -87,5 +87,12 @@ in environment.etc."ld-nix.so.preload".text = '' ${providerLibPath} ''; + security.apparmor.includes = { + "abstractions/base" = '' + r /etc/ld-nix.so.preload, + r ${config.environment.etc."ld-nix.so.preload".source}, + mr ${providerLibPath}, + ''; + }; }; } diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 4cb7d81c997..dba8977e482 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -58,6 +58,7 @@ in "2.nixos.pool.ntp.org" "3.nixos.pool.ntp.org" ]; + type = types.listOf types.str; description = '' The set of NTP servers from which to synchronise. ''; @@ -193,6 +194,9 @@ in cat ${escapeShellArgs cfg.hostFiles} > $out ''; + # /etc/netgroup: Network-wide groups. + netgroup.text = mkDefault ""; + # /etc/host.conf: resolver configuration file "host.conf".text = '' multi on diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix index 941ab78f863..14fe180d0bc 100644 --- a/nixos/modules/config/no-x-libs.nix +++ b/nixos/modules/config/no-x-libs.nix @@ -29,12 +29,14 @@ with lib; nixpkgs.overlays = singleton (const (super: { cairo = super.cairo.override { x11Support = false; }; dbus = super.dbus.override { x11Support = false; }; + beam = super.beam_nox; networkmanager-fortisslvpn = super.networkmanager-fortisslvpn.override { withGnome = false; }; + networkmanager-iodine = super.networkmanager-iodine.override { withGnome = false; }; networkmanager-l2tp = super.networkmanager-l2tp.override { withGnome = false; }; networkmanager-openconnect = super.networkmanager-openconnect.override { withGnome = false; }; networkmanager-openvpn = super.networkmanager-openvpn.override { withGnome = false; }; + networkmanager-sstp = super.networkmanager-vpnc.override { withGnome = false; }; networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; }; - networkmanager-iodine = super.networkmanager-iodine.override { withGnome = false; }; gobject-introspection = super.gobject-introspection.override { x11Support = false; }; qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; }; })); diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix index d19d35a4890..91a36cef10e 100644 --- a/nixos/modules/config/nsswitch.nix +++ b/nixos/modules/config/nsswitch.nix @@ -124,8 +124,8 @@ with lib; group = mkBefore [ "files" ]; shadow = mkBefore [ "files" ]; hosts = mkMerge [ - (mkBefore [ "files" ]) - (mkAfter [ "dns" ]) + (mkOrder 998 [ "files" ]) + (mkOrder 1499 [ "dns" ]) ]; services = mkBefore [ "files" ]; }; diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index 408d0a9c33f..3f7ae109e8c 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -17,9 +17,9 @@ let binary = "${getBin overriddenPackage}/bin/pulseaudio"; binaryNoDaemon = "${binary} --daemonize=no"; - # Forces 32bit pulseaudio and alsaPlugins to be built/supported for apps + # Forces 32bit pulseaudio and alsa-plugins to be built/supported for apps # using 32bit alsa on 64bit linux. - enable32BitAlsaPlugins = cfg.support32Bit && stdenv.isx86_64 && (pkgs.pkgsi686Linux.alsaLib != null && pkgs.pkgsi686Linux.libpulseaudio != null); + enable32BitAlsaPlugins = cfg.support32Bit && stdenv.isx86_64 && (pkgs.pkgsi686Linux.alsa-lib != null && pkgs.pkgsi686Linux.libpulseaudio != null); myConfigFile = @@ -36,6 +36,8 @@ let ${addModuleIf cfg.zeroconf.discovery.enable "module-zeroconf-discover"} ${addModuleIf cfg.tcp.enable (concatStringsSep " " ([ "module-native-protocol-tcp" ] ++ allAnon ++ ipAnon))} + ${addModuleIf config.services.jack.jackd.enable "module-jack-sink"} + ${addModuleIf config.services.jack.jackd.enable "module-jack-source"} ${cfg.extraConfig} ''; }; @@ -60,18 +62,18 @@ let # plugin. alsaConf = writeText "asound.conf" ('' pcm_type.pulse { - libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ; + libs.native = ${pkgs.alsa-plugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ; ${lib.optionalString enable32BitAlsaPlugins - "libs.32Bit = ${pkgs.pkgsi686Linux.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ;"} + "libs.32Bit = ${pkgs.pkgsi686Linux.alsa-plugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ;"} } pcm.!default { type pulse hint.description "Default Audio Device (via PulseAudio)" } ctl_type.pulse { - libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ; + libs.native = ${pkgs.alsa-plugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ; ${lib.optionalString enable32BitAlsaPlugins - "libs.32Bit = ${pkgs.pkgsi686Linux.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"} + "libs.32Bit = ${pkgs.pkgsi686Linux.alsa-plugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"} } ctl.!default { type pulse @@ -144,7 +146,9 @@ in { package = mkOption { type = types.package; - default = pkgs.pulseaudio; + default = if config.services.jack.jackd.enable + then pkgs.pulseaudioFull + else pkgs.pulseaudio; defaultText = "pkgs.pulseaudio"; example = literalExample "pkgs.pulseaudioFull"; description = '' @@ -179,7 +183,7 @@ in { config = mkOption { type = types.attrsOf types.unspecified; default = {}; - description = ''Config of the pulse daemon. See <literal>man pulse-daemon.conf</literal>.''; + description = "Config of the pulse daemon. See <literal>man pulse-daemon.conf</literal>."; example = literalExample ''{ realtime-scheduling = "yes"; }''; }; }; @@ -259,7 +263,7 @@ in { (drv: drv.override { pulseaudio = overriddenPackage; }) cfg.extraModules; modulePaths = builtins.map - (drv: "${drv}/lib/pulse-${overriddenPackage.version}/modules") + (drv: "${drv}/${overriddenPackage.pulseDir}/modules") # User-provided extra modules take precedence (overriddenModules ++ [ overriddenPackage ]); in lib.concatStringsSep ":" modulePaths; @@ -284,6 +288,8 @@ in { RestartSec = "500ms"; PassEnvironment = "DISPLAY"; }; + } // optionalAttrs config.services.jack.jackd.enable { + environment.JACK_PROMISCUOUS_SERVER = "jackaudio"; }; sockets.pulseaudio = { wantedBy = [ "sockets.target" ]; @@ -300,6 +306,7 @@ in { description = "PulseAudio system service user"; home = stateDir; createHome = true; + isSystemUser = true; }; users.groups.pulse.gid = gid; diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index a0a20228a74..34e558d8603 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -126,6 +126,14 @@ in type = types.bool; }; + environment.localBinInPath = mkOption { + description = '' + Add ~/.local/bin/ to $PATH + ''; + default = false; + type = types.bool; + }; + environment.binsh = mkOption { default = "${config.system.build.binsh}/bin/sh"; defaultText = "\${config.system.build.binsh}/bin/sh"; @@ -198,6 +206,10 @@ in # ~/bin if it exists overrides other bin directories. export PATH="$HOME/bin:$PATH" ''} + + ${optionalString cfg.localBinInPath '' + export PATH="$HOME/.local/bin:$PATH" + ''} ''; system.activationScripts.binsh = stringAfter [ "stdio" ] diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix index adb4e229421..ff2ae1da31b 100644 --- a/nixos/modules/config/swap.nix +++ b/nixos/modules/config/swap.nix @@ -114,6 +114,28 @@ let ''; }; + discardPolicy = mkOption { + default = null; + example = "once"; + type = types.nullOr (types.enum ["once" "pages" "both" ]); + description = '' + Specify the discard policy for the swap device. If "once", then the + whole swap space is discarded at swapon invocation. If "pages", + asynchronous discard on freed pages is performed, before returning to + the available pages pool. With "both", both policies are activated. + See swapon(8) for more information. + ''; + }; + + options = mkOption { + default = [ "defaults" ]; + example = [ "nofail" ]; + type = types.listOf types.nonEmptyStr; + description = '' + Options used to mount the swap. + ''; + }; + deviceName = mkOption { type = types.str; internal = true; @@ -185,9 +207,7 @@ in { description = "Initialisation of swap device ${sw.device}"; wantedBy = [ "${realDevice'}.swap" ]; before = [ "${realDevice'}.swap" ]; - # If swap is encrypted, depending on rngd resolves a possible entropy starvation during boot - after = mkIf (config.security.rngd.enable && sw.randomEncryption.enable) [ "rngd.service" ]; - path = [ pkgs.utillinux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup; + path = [ pkgs.util-linux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup; script = '' @@ -204,7 +224,7 @@ in fi ''} ${optionalString sw.randomEncryption.enable '' - cryptsetup plainOpen -c ${sw.randomEncryption.cipher} -d ${sw.randomEncryption.source} ${sw.device} ${sw.deviceName} + cryptsetup plainOpen -c ${sw.randomEncryption.cipher} -d ${sw.randomEncryption.source} ${optionalString (sw.discardPolicy != null) "--allow-discards"} ${sw.device} ${sw.deviceName} mkswap ${sw.realDevice} ''} ''; diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index b3c5c6f93f3..1292c3008c6 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -29,18 +29,25 @@ let pkgs.xz pkgs.less pkgs.libcap - pkgs.nano pkgs.ncurses pkgs.netcat config.programs.ssh.package + pkgs.mkpasswd pkgs.procps pkgs.su pkgs.time - pkgs.utillinux + pkgs.util-linux pkgs.which pkgs.zstd ]; + defaultPackages = map (pkg: setPrio ((pkg.meta.priority or 5) + 3) pkg) + [ pkgs.nano + pkgs.perl + pkgs.rsync + pkgs.strace + ]; + in { @@ -63,6 +70,29 @@ in ''; }; + defaultPackages = mkOption { + type = types.listOf types.package; + default = defaultPackages; + example = literalExample "[]"; + description = '' + Set of default packages that aren't strictly neccessary + for a running system, entries can be removed for a more + minimal NixOS installation. + + Note: If <package>pkgs.nano</package> is removed from this list, + make sure another editor is installed and the + <literal>EDITOR</literal> environment variable is set to it. + Environment variables can be set using + <option>environment.variables</option>. + + Like with systemPackages, packages are installed to + <filename>/run/current-system/sw</filename>. They are + automatically available to all users, and are + automatically updated every time you rebuild the system + configuration. + ''; + }; + pathsToLink = mkOption { type = types.listOf types.str; # Note: We need `/lib' to be among `pathsToLink' for NSS modules @@ -102,7 +132,7 @@ in config = { - environment.systemPackages = requiredPackages; + environment.systemPackages = requiredPackages ++ config.environment.defaultPackages; environment.pathsToLink = [ "/bin" @@ -121,6 +151,8 @@ in "/share/kservices5" "/share/kservicetypes5" "/share/kxmlgui5" + "/share/systemd" + "/share/thumbnailers" ]; system.path = pkgs.buildEnv { diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl index e1c7a46e430..bef08dc4020 100644 --- a/nixos/modules/config/update-users-groups.pl +++ b/nixos/modules/config/update-users-groups.pl @@ -16,8 +16,7 @@ my $gidMap = -e $gidMapFile ? decode_json(read_file($gidMapFile)) : {}; sub updateFile { my ($path, $contents, $perms) = @_; - write_file("$path.tmp", { binmode => ':utf8', perms => $perms // 0644 }, $contents); - rename("$path.tmp", $path) or die; + write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die; } @@ -98,7 +97,7 @@ sub parseGroup { return ($f[0], { name => $f[0], password => $f[1], gid => $gid, members => $f[3] }); } -my %groupsCur = -f "/etc/group" ? map { parseGroup } read_file("/etc/group") : (); +my %groupsCur = -f "/etc/group" ? map { parseGroup } read_file("/etc/group", { binmode => ":utf8" }) : (); # Read the current /etc/passwd. sub parseUser { @@ -109,20 +108,19 @@ sub parseUser { return ($f[0], { name => $f[0], fakePassword => $f[1], uid => $uid, gid => $f[3], description => $f[4], home => $f[5], shell => $f[6] }); } - -my %usersCur = -f "/etc/passwd" ? map { parseUser } read_file("/etc/passwd") : (); +my %usersCur = -f "/etc/passwd" ? map { parseUser } read_file("/etc/passwd", { binmode => ":utf8" }) : (); # Read the groups that were created declaratively (i.e. not by groups) # in the past. These must be removed if they are no longer in the # current spec. my $declGroupsFile = "/var/lib/nixos/declarative-groups"; my %declGroups; -$declGroups{$_} = 1 foreach split / /, -e $declGroupsFile ? read_file($declGroupsFile) : ""; +$declGroups{$_} = 1 foreach split / /, -e $declGroupsFile ? read_file($declGroupsFile, { binmode => ":utf8" }) : ""; # Idem for the users. my $declUsersFile = "/var/lib/nixos/declarative-users"; my %declUsers; -$declUsers{$_} = 1 foreach split / /, -e $declUsersFile ? read_file($declUsersFile) : ""; +$declUsers{$_} = 1 foreach split / /, -e $declUsersFile ? read_file($declUsersFile, { binmode => ":utf8" }) : ""; # Generate a new /etc/group containing the declared groups. @@ -175,7 +173,7 @@ foreach my $name (keys %groupsCur) { # Rewrite /etc/group. FIXME: acquire lock. my @lines = map { join(":", $_->{name}, $_->{password}, $_->{gid}, $_->{members}) . "\n" } (sort { $a->{gid} <=> $b->{gid} } values(%groupsOut)); -updateFile($gidMapFile, encode_json($gidMap)); +updateFile($gidMapFile, to_json($gidMap)); updateFile("/etc/group", \@lines); system("nscd --invalidate group"); @@ -211,10 +209,11 @@ foreach my $u (@{$spec->{users}}) { } } - # Create a home directory. + # Ensure home directory incl. ownership and permissions. if ($u->{createHome}) { make_path($u->{home}, { mode => 0700 }) if ! -e $u->{home}; chown $u->{uid}, $u->{gid}, $u->{home}; + chmod 0700, $u->{home}; } if (defined $u->{passwordFile}) { @@ -228,6 +227,15 @@ foreach my $u (@{$spec->{users}}) { $u->{hashedPassword} = hashPassword($u->{password}); } + if (!defined $u->{shell}) { + if (defined $existing) { + $u->{shell} = $existing->{shell}; + } else { + warn "warning: no declarative or previous shell for ‘$name’, setting shell to nologin\n"; + $u->{shell} = "/run/current-system/sw/bin/nologin"; + } + } + $u->{fakePassword} = $existing->{fakePassword} // "x"; $usersOut{$name} = $u; @@ -251,7 +259,7 @@ foreach my $name (keys %usersCur) { # Rewrite /etc/passwd. FIXME: acquire lock. @lines = map { join(":", $_->{name}, $_->{fakePassword}, $_->{uid}, $_->{gid}, $_->{description}, $_->{home}, $_->{shell}) . "\n" } (sort { $a->{uid} <=> $b->{uid} } (values %usersOut)); -updateFile($uidMapFile, encode_json($uidMap)); +updateFile($uidMapFile, to_json($uidMap)); updateFile("/etc/passwd", \@lines); system("nscd --invalidate passwd"); @@ -260,7 +268,7 @@ system("nscd --invalidate passwd"); my @shadowNew; my %shadowSeen; -foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow") : ()) { +foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) { chomp $line; my ($name, $hashedPassword, @rest) = split(':', $line, -9); my $u = $usersOut{$name};; @@ -280,7 +288,13 @@ foreach my $u (values %usersOut) { push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::::") . "\n"; } -updateFile("/etc/shadow", \@shadowNew, 0600); +updateFile("/etc/shadow", \@shadowNew, 0640); +{ + my $uid = getpwnam "root"; + my $gid = getgrnam "shadow"; + my $path = "/etc/shadow"; + chown($uid, $gid, $path) || die "Failed to change ownership of $path: $!"; +} # Rewrite /etc/subuid & /etc/subgid to include default container mappings diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 56b7af98b61..d5e7745c53f 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -6,6 +6,12 @@ let ids = config.ids; cfg = config.users; + isPasswdCompatible = str: !(hasInfix ":" str || hasInfix "\n" str); + passwdEntry = type: lib.types.addCheck type isPasswdCompatible // { + name = "passwdEntry ${type.name}"; + description = "${type.description}, not containing newlines or colons"; + }; + # Check whether a password hash will allow login. allowsLogin = hash: hash == "" # login without password @@ -35,8 +41,7 @@ let ''; hashedPasswordDescription = '' - To generate a hashed password install the <literal>mkpasswd</literal> - package and run <literal>mkpasswd -m sha-512</literal>. + To generate a hashed password run <literal>mkpasswd -m sha-512</literal>. If set to an empty string (<literal>""</literal>), this user will be able to log in without being asked for a password (but not via remote @@ -55,7 +60,7 @@ let options = { name = mkOption { - type = types.str; + type = passwdEntry types.str; apply = x: assert (builtins.stringLength x < 32 || abort "Username '${x}' is longer than 31 characters which is not allowed!"); x; description = '' The name of the user account. If undefined, the name of the @@ -64,7 +69,7 @@ let }; description = mkOption { - type = types.str; + type = passwdEntry types.str; default = ""; example = "Alice Q. User"; description = '' @@ -93,6 +98,8 @@ let the user's UID is allocated in the range for system users (below 500) or in the range for normal users (starting at 1000). + Exactly one of <literal>isNormalUser</literal> and + <literal>isSystemUser</literal> must be true. ''; }; @@ -108,6 +115,8 @@ let <option>useDefaultShell</option> to <literal>true</literal>, and <option>isSystemUser</option> to <literal>false</literal>. + Exactly one of <literal>isNormalUser</literal> and + <literal>isSystemUser</literal> must be true. ''; }; @@ -125,7 +134,7 @@ let }; home = mkOption { - type = types.path; + type = passwdEntry types.path; default = "/var/empty"; description = "The user's home directory."; }; @@ -139,8 +148,22 @@ let ''; }; + pamMount = mkOption { + type = with types; attrsOf str; + default = {}; + description = '' + Attributes for user's entry in + <filename>pam_mount.conf.xml</filename>. + Useful attributes might include <code>path</code>, + <code>options</code>, <code>fstype</code>, and <code>server</code>. + See <link + xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html" /> + for more information. + ''; + }; + shell = mkOption { - type = types.either types.shellPackage types.path; + type = types.nullOr (types.either types.shellPackage (passwdEntry types.path)); default = pkgs.shadow; defaultText = "pkgs.shadow"; example = literalExample "pkgs.bashInteractive"; @@ -185,10 +208,8 @@ let type = types.bool; default = false; description = '' - If true, the home directory will be created automatically. If this - option is true and the home directory already exists but is not - owned by the user, directory owner and group will be changed to - match the user. + Whether to create the home directory and ensure ownership as well as + permissions to match the user. ''; }; @@ -202,7 +223,7 @@ let }; hashedPassword = mkOption { - type = with types; nullOr str; + type = with types; nullOr (passwdEntry str); default = null; description = '' Specifies the hashed password for the user. @@ -236,7 +257,7 @@ let }; initialHashedPassword = mkOption { - type = with types; nullOr str; + type = with types; nullOr (passwdEntry str); default = null; description = '' Specifies the initial hashed password for the user, i.e. the @@ -308,7 +329,7 @@ let options = { name = mkOption { - type = types.str; + type = passwdEntry types.str; description = '' The name of the group. If undefined, the name of the attribute set will be used. @@ -325,7 +346,7 @@ let }; members = mkOption { - type = with types; listOf str; + type = with types; listOf (passwdEntry str); default = []; description = '' The user names of the group members, added to the @@ -353,7 +374,7 @@ let count = mkOption { type = types.int; default = 1; - description = ''Count of subordinate user ids''; + description = "Count of subordinate user ids"; }; }; }; @@ -370,12 +391,12 @@ let count = mkOption { type = types.int; default = 1; - description = ''Count of subordinate group ids''; + description = "Count of subordinate group ids"; }; }; }; - idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }: + idsAreUnique = set: idAttr: !(foldr (name: args@{ dup, acc }: let id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set)); exists = builtins.hasAttr id acc; @@ -463,7 +484,7 @@ in { users.users = mkOption { default = {}; - type = with types; loaOf (submodule userOpts); + type = with types; attrsOf (submodule userOpts); example = { alice = { uid = 1234; @@ -487,7 +508,7 @@ in { { students.gid = 1001; hackers = { }; }; - type = with types; loaOf (submodule groupOpts); + type = with types; attrsOf (submodule groupOpts); description = '' Additional groups to be created automatically by the system. ''; @@ -510,6 +531,7 @@ in { }; nobody = { uid = ids.uids.nobody; + isSystemUser = true; description = "Unprivileged account (don't use!)"; group = "nogroup"; }; @@ -537,6 +559,7 @@ in { input.gid = ids.gids.input; kvm.gid = ids.gids.kvm; render.gid = ids.gids.render; + shadow.gid = ids.gids.shadow; }; system.activationScripts.users = stringAfter [ "stdio" ] @@ -544,10 +567,8 @@ in { install -m 0700 -d /root install -m 0755 -d /home - ${pkgs.perl}/bin/perl -w \ - -I${pkgs.perlPackages.FileSlurp}/${pkgs.perl.libPrefix} \ - -I${pkgs.perlPackages.JSON}/${pkgs.perl.libPrefix} \ - ${./update-users-groups.pl} ${spec} + ${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON ])}/bin/perl \ + -w ${./update-users-groups.pl} ${spec} ''; # for backwards compatibility @@ -556,7 +577,7 @@ in { # Install all the user shells environment.systemPackages = systemShells; - environment.etc = (mapAttrs' (name: { packages, ... }: { + environment.etc = (mapAttrs' (_: { packages, name, ... }: { name = "profiles/per-user/${name}"; value.source = pkgs.buildEnv { name = "user-environment"; @@ -581,8 +602,8 @@ in { # password or an SSH authorized key. Privileged accounts are # root and users in the wheel group. assertion = !cfg.mutableUsers -> - any id ((mapAttrsToList (name: cfg: - (name == "root" + any id ((mapAttrsToList (_: cfg: + (cfg.name == "root" || cfg.group == "wheel" || elem "wheel" cfg.extraGroups) && @@ -598,21 +619,32 @@ in { Neither the root account nor any wheel user has a password or SSH authorized key. You must set one to prevent being locked out of your system.''; } - ] ++ flip mapAttrsToList cfg.users (name: user: - { + ] ++ flatten (flip mapAttrsToList cfg.users (name: user: + [ + { assertion = (user.hashedPassword != null) - -> (builtins.match ".*:.*" user.hashedPassword == null); + -> (builtins.match ".*:.*" user.hashedPassword == null); message = '' - The password hash of user "${name}" contains a ":" character. - This is invalid and would break the login system because the fields - of /etc/shadow (file where hashes are stored) are colon-separated. - Please check the value of option `users.users."${name}".hashedPassword`.''; - } - ); + The password hash of user "${user.name}" contains a ":" character. + This is invalid and would break the login system because the fields + of /etc/shadow (file where hashes are stored) are colon-separated. + Please check the value of option `users.users."${user.name}".hashedPassword`.''; + } + { + assertion = let + xor = a: b: a && !b || b && !a; + isEffectivelySystemUser = user.isSystemUser || (user.uid != null && user.uid < 500); + in xor isEffectivelySystemUser user.isNormalUser; + message = '' + Exactly one of users.users.${user.name}.isSystemUser and users.users.${user.name}.isNormalUser must be set. + ''; + } + ] + )); warnings = builtins.filter (x: x != null) ( - flip mapAttrsToList cfg.users (name: user: + flip mapAttrsToList cfg.users (_: user: # This regex matches a subset of the Modular Crypto Format (MCF)[1] # informal standard. Since this depends largely on the OS or the # specific implementation of crypt(3) we only support the (sane) @@ -635,9 +667,9 @@ in { && user.hashedPassword != "" # login without password && builtins.match mcf user.hashedPassword == null) then '' - The password hash of user "${name}" may be invalid. You must set a + The password hash of user "${user.name}" may be invalid. You must set a valid hash or the user will be locked out of their account. Please - check the value of option `users.users."${name}".hashedPassword`.'' + check the value of option `users.users."${user.name}".hashedPassword`.'' else null )); diff --git a/nixos/modules/config/xdg/portal.nix b/nixos/modules/config/xdg/portal.nix index 3c7cd729c60..80ec3126ca5 100644 --- a/nixos/modules/config/xdg/portal.nix +++ b/nixos/modules/config/xdg/portal.nix @@ -62,7 +62,7 @@ with lib; services.dbus.packages = packages; systemd.packages = packages; - environment.variables = { + environment.sessionVariables = { GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1"; XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals"; }; diff --git a/nixos/modules/config/xdg/portals/wlr.nix b/nixos/modules/config/xdg/portals/wlr.nix new file mode 100644 index 00000000000..55baab0026b --- /dev/null +++ b/nixos/modules/config/xdg/portals/wlr.nix @@ -0,0 +1,67 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.xdg.portal.wlr; + package = pkgs.xdg-desktop-portal-wlr; + settingsFormat = pkgs.formats.ini { }; + configFile = settingsFormat.generate "xdg-desktop-portal-wlr.ini" cfg.settings; +in +{ + meta = { + maintainers = with maintainers; [ minijackson ]; + }; + + options.xdg.portal.wlr = { + enable = mkEnableOption '' + desktop portal for wlroots-based desktops + + This will add the <package>xdg-desktop-portal-wlr</package> package into + the <option>xdg.portal.extraPortals</option> option, and provide the + configuration file + ''; + + settings = mkOption { + description = '' + Configuration for <package>xdg-desktop-portal-wlr</package>. + + See <literal>xdg-desktop-portal-wlr(5)</literal> for supported + values. + ''; + + type = types.submodule { + freeformType = settingsFormat.type; + }; + + default = { }; + + # Example taken from the manpage + example = literalExample '' + { + screencast = { + output_name = "HDMI-A-1"; + max_fps = 30; + exec_before = "disable_notifications.sh"; + exec_after = "enable_notifications.sh"; + chooser_type = "simple"; + chooser_cmd = "''${pkgs.slurp}/bin/slurp -f %o -or"; + }; + } + ''; + }; + }; + + config = mkIf cfg.enable { + xdg.portal = { + enable = true; + extraPortals = [ package ]; + }; + + systemd.user.services.xdg-desktop-portal-wlr.serviceConfig.ExecStart = [ + # Empty ExecStart value to override the field + "" + "${package}/libexec/xdg-desktop-portal-wlr --config=${configFile}" + ]; + }; +} diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix index 5e9870bf6b1..1f513b7e4da 100644 --- a/nixos/modules/config/zram.nix +++ b/nixos/modules/config/zram.nix @@ -80,6 +80,15 @@ in ''; }; + memoryMax = mkOption { + default = null; + type = with types; nullOr int; + description = '' + Maximum total amount of memory (in bytes) that can be used by the zram + swap devices. + ''; + }; + priority = mkOption { default = 5; type = types.int; @@ -146,11 +155,16 @@ in # Calculate memory to use for zram mem=$(${pkgs.gawk}/bin/awk '/MemTotal: / { - print int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024) + value=int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024); + ${lib.optionalString (cfg.memoryMax != null) '' + memory_max=int(${toString cfg.memoryMax}/${toString devicesCount}); + if (value > memory_max) { value = memory_max } + ''} + print value }' /proc/meminfo) - ${pkgs.utillinux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev} - ${pkgs.utillinux}/sbin/mkswap /dev/${dev} + ${pkgs.util-linux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev} + ${pkgs.util-linux}/sbin/mkswap /dev/${dev} ''; restartIfChanged = false; }; |