diff options
Diffstat (limited to 'nixos/modules')
65 files changed, 942 insertions, 558 deletions
diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix index bdf90816740c..ce87f9e8be8a 100644 --- a/nixos/modules/hardware/all-firmware.nix +++ b/nixos/modules/hardware/all-firmware.nix @@ -83,7 +83,7 @@ in { b43Firmware_5_1_138 b43Firmware_6_30_163_46 b43FirmwareCutter - ] ++ optional (pkgs.stdenv.hostPlatform.isi686 || pkgs.stdenv.hostPlatform.isx86_64) facetimehd-firmware; + ] ++ optional pkgs.stdenv.hostPlatform.isx86 facetimehd-firmware; }) (mkIf cfg.wirelessRegulatoryDatabase { hardware.firmware = [ pkgs.wireless-regdb ]; diff --git a/nixos/modules/hardware/video/hidpi.nix b/nixos/modules/hardware/video/hidpi.nix index c480cc481dfc..ac72b652504e 100644 --- a/nixos/modules/hardware/video/hidpi.nix +++ b/nixos/modules/hardware/video/hidpi.nix @@ -12,6 +12,5 @@ with lib; boot.loader.systemd-boot.consoleMode = mkDefault "1"; # TODO Find reasonable defaults X11 & wayland - services.xserver.dpi = lib.mkDefault 192; }; } diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 5b379505608a..ff4225dc29ad 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -179,7 +179,7 @@ in in mkIf enabled { assertions = [ { - assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable; + assertion = with config.services.xserver.displayManager; (gdm.enable && gdm.nvidiaWayland) -> cfg.modesetting.enable; message = "You cannot use wayland with GDM without modesetting enabled for NVIDIA drivers, set `hardware.nvidia.modesetting.enable = true`"; } diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 4812cacabaf3..30610b4f4260 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -467,7 +467,7 @@ let throw "Unsupported architecture"; # Syslinux (and isolinux) only supports x86-based architectures. - canx86BiosBoot = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64; + canx86BiosBoot = pkgs.stdenv.hostPlatform.isx86; in diff --git a/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh index 2a6c3ab11497..490ede04e6bb 100644 --- a/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh +++ b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -1,4 +1,5 @@ #! @runtimeShell@ -e +# shellcheck shell=bash # Shows the usage of this command to the user @@ -29,12 +30,12 @@ while [ $# -gt 0 ]; do nixBuildArgs+=("--option" "$1" "$2"); shift ;; *) - if [ ! -z "$networkExpr" ]; then + if [ -n "$networkExpr" ]; then echo "Network expression already set!" showUsage exit 1 fi - networkExpr="$(readlink -f $1)" + networkExpr="$(readlink -f "$1")" ;; esac @@ -49,4 +50,4 @@ fi # Build a network of VMs nix-build '<nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix>' \ - --argstr networkExpr $networkExpr "${nixBuildArgs[@]}" + --argstr networkExpr "$networkExpr" "${nixBuildArgs[@]}" diff --git a/nixos/modules/installer/tools/nixos-enter.sh b/nixos/modules/installer/tools/nixos-enter.sh index 00883205e8b5..6469d9faa038 100644 --- a/nixos/modules/installer/tools/nixos-enter.sh +++ b/nixos/modules/installer/tools/nixos-enter.sh @@ -1,4 +1,5 @@ #! @runtimeShell@ +# shellcheck shell=bash set -e diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 7bc55e67134b..fe8c4fb1a6b5 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -91,6 +91,11 @@ sub hasCPUFeature { } +sub cpuManufacturer { + my $id = shift; + return $cpuinfo =~ /^vendor_id\s*:.* $id$/m; +} + # Determine CPU governor to use if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") { @@ -111,6 +116,9 @@ if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") { push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; +push @attrs, "hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "AuthenticAMD"; +push @attrs, "hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "GenuineIntel"; + # Look at the PCI devices and add necessary modules. Note that most # modules are auto-detected so we don't need to list them here. diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index ea9667995e13..fc4a69aa17d3 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -1,4 +1,5 @@ #! @runtimeShell@ +# shellcheck shell=bash set -e shopt -s nullglob @@ -58,7 +59,7 @@ while [ "$#" -gt 0 ]; do --no-channel-copy) noChannelCopy=1 ;; - --no-root-passwd) + --no-root-password|--no-root-passwd) noRootPasswd=1 ;; --no-bootloader) diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh index f5e3f32b3c63..59a9c572b418 100644 --- a/nixos/modules/installer/tools/nixos-version.sh +++ b/nixos/modules/installer/tools/nixos-version.sh @@ -1,4 +1,5 @@ #! @runtimeShell@ +# shellcheck shell=bash case "$1" in -h|--help) diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index c3ded4f1ea34..1f837f9efa22 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -80,6 +80,10 @@ let ]; }; + # list of man outputs currently active intended for use as default values + # for man-related options, thus "man" is included unconditionally. + activeManOutputs = [ "man" ] ++ lib.optionals cfg.dev.enable [ "devman" ]; + in { @@ -130,7 +134,7 @@ in name = "man-paths"; paths = config.environment.systemPackages; pathsToLink = [ "/share/man" ]; - extraOutputsToInstall = ["man"]; + extraOutputsToInstall = activeManOutputs; ignoreCollisions = true; }; defaultText = literalDocBook "all man pages in <option>config.environment.systemPackages</option>"; @@ -226,7 +230,7 @@ in (mkIf cfg.man.enable { environment.systemPackages = [ pkgs.man-db ]; environment.pathsToLink = [ "/share/man" ]; - environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman"; + environment.extraOutputsToInstall = activeManOutputs; environment.etc."man_db.conf".text = let manualCache = pkgs.runCommandLocal "man-cache" { } '' diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index f392ca52566f..273ed95e1bce 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -351,6 +351,7 @@ in hqplayer = 319; moonraker = 320; distcc = 321; + webdav = 322; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -656,6 +657,7 @@ in hqplayer = 319; moonraker = 320; distcc = 321; + webdav = 322; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/misc/locate.nix b/nixos/modules/misc/locate.nix index 2f0f676a0ba3..461a2aa5a946 100644 --- a/nixos/modules/misc/locate.nix +++ b/nixos/modules/misc/locate.nix @@ -163,7 +163,7 @@ in { prunePaths = mkOption { type = listOf path; - default = ["/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store"]; + default = [ "/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store" "/nix/var/log/nix" ]; description = '' Which paths to exclude from indexing ''; @@ -171,7 +171,7 @@ in { pruneNames = mkOption { type = listOf str; - default = []; + default = [ ".bzr" ".cache" ".git" ".hg" ".svn" ]; description = '' Directory components which should exclude paths containing them from indexing ''; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4ee79b439602..1d51fca02fbf 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -611,6 +611,7 @@ ./services/misc/uhub.nix ./services/misc/weechat.nix ./services/misc/xmr-stak.nix + ./services/misc/xmrig.nix ./services/misc/zigbee2mqtt.nix ./services/misc/zoneminder.nix ./services/misc/zookeeper.nix @@ -683,6 +684,8 @@ ./services/network-filesystems/tahoe.nix ./services/network-filesystems/diod.nix ./services/network-filesystems/u9fs.nix + ./services/network-filesystems/webdav.nix + ./services/network-filesystems/webdav-server-rs.nix ./services/network-filesystems/yandex-disk.nix ./services/network-filesystems/xtreemfs.nix ./services/network-filesystems/ceph.nix diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index 3b67d628f9fd..33dd80d7c5ab 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -40,6 +40,7 @@ # Tools to create / manipulate filesystems. pkgs.ntfsprogs # for resizing NTFS partitions pkgs.dosfstools + pkgs.mtools pkgs.xfsprogs.bin pkgs.jfsutils pkgs.f2fs-tools diff --git a/nixos/modules/programs/sway.nix b/nixos/modules/programs/sway.nix index caf329c2536a..c64e01a20cb3 100644 --- a/nixos/modules/programs/sway.nix +++ b/nixos/modules/programs/sway.nix @@ -123,6 +123,8 @@ in { ]; environment = { systemPackages = [ swayPackage ] ++ cfg.extraPackages; + # Needed for the default wallpaper: + pathsToLink = [ "/share/backgrounds/sway" ]; etc = { "sway/config".source = mkOptionDefault "${swayPackage}/etc/sway/config"; "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" '' diff --git a/nixos/modules/programs/zsh/zsh-autosuggestions.nix b/nixos/modules/programs/zsh/zsh-autosuggestions.nix index a8fcfff95e59..fee324cc7326 100644 --- a/nixos/modules/programs/zsh/zsh-autosuggestions.nix +++ b/nixos/modules/programs/zsh/zsh-autosuggestions.nix @@ -36,6 +36,13 @@ in ''; }; + async = mkOption { + type = types.bool; + default = true; + description = "Whether to fetch suggestions asynchronously"; + example = false; + }; + extraConfig = mkOption { type = with types; attrsOf str; default = {}; @@ -56,6 +63,7 @@ in export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.highlightStyle}" export ZSH_AUTOSUGGEST_STRATEGY=("${cfg.strategy}") + ${optionalString (!cfg.async) "unset ZSH_AUTOSUGGEST_USE_ASYNC"} ${concatStringsSep "\n" (mapAttrsToList (key: value: ''export ${key}="${value}"'') cfg.extraConfig)} ''; diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index cfbc8e91903e..2815e2593b23 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -77,6 +77,7 @@ let unitConfig = { ConditionPathExists = "!/var/lib/acme/.minica/key.pem"; + StartLimitIntervalSec = 0; }; serviceConfig = commonServiceConfig // { @@ -235,6 +236,7 @@ let unitConfig = { ConditionPathExists = "!/var/lib/acme/${cert}/key.pem"; + StartLimitIntervalSec = 0; }; serviceConfig = commonServiceConfig // { @@ -314,6 +316,9 @@ let if [ -e renewed ]; then rm renewed ${data.postRun} + ${optionalString (data.reloadServices != []) + "systemctl --no-block try-reload-or-restart ${escapeShellArgs data.reloadServices}" + } fi ''); }; @@ -474,6 +479,15 @@ let description = "Group running the ACME client."; }; + reloadServices = mkOption { + type = types.listOf types.str; + default = []; + description = '' + The list of systemd services to call <code>systemctl try-reload-or-restart</code> + on. + ''; + }; + postRun = mkOption { type = types.lines; default = ""; diff --git a/nixos/modules/security/acme.xml b/nixos/modules/security/acme.xml index 8249da948c6d..bf93800a0af4 100644 --- a/nixos/modules/security/acme.xml +++ b/nixos/modules/security/acme.xml @@ -253,7 +253,7 @@ chmod 400 /var/lib/secrets/certs.secret </programlisting> <para> - Now you're all set to generate certs! You should monitor the first invokation + Now you're all set to generate certs! You should monitor the first invocation by running <literal>systemctl start acme-example.com.service & journalctl -fu acme-example.com.service</literal> and watching its log output. </para> diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 40df6c67ef84..b03bf290fd23 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -401,6 +401,9 @@ let }; + # The resulting /etc/pam.d/* file contents are verified in + # nixos/tests/pam/pam-file-contents.nix. Please update tests there when + # changing the derivation. config = { name = mkDefault name; setLoginUid = mkDefault cfg.startSession; @@ -410,46 +413,64 @@ let # Samba stuff to the Samba module. This requires that the PAM # module provides the right hooks. text = mkDefault - ('' - # Account management. - account required pam_unix.so - ${optionalString use_ldap - "account sufficient ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false) - "account sufficient ${pkgs.sssd}/lib/security/pam_sss.so"} - ${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess) - "account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so"} - ${optionalString config.krb5.enable - "account sufficient ${pam_krb5}/lib/security/pam_krb5.so"} - ${optionalString cfg.googleOsLoginAccountVerification '' + ( + '' + # Account management. + account required pam_unix.so + '' + + optionalString use_ldap '' + account sufficient ${pam_ldap}/lib/security/pam_ldap.so + '' + + optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false) '' + account sufficient ${pkgs.sssd}/lib/security/pam_sss.so + '' + + optionalString (config.services.sssd.enable && cfg.sssdStrictAccess) '' + account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so + '' + + optionalString config.krb5.enable '' + account sufficient ${pam_krb5}/lib/security/pam_krb5.so + '' + + optionalString cfg.googleOsLoginAccountVerification '' account [success=ok ignore=ignore default=die] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so account [success=ok default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so - ''} - - # Authentication management. - ${optionalString cfg.googleOsLoginAuthentication - "auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so"} - ${optionalString cfg.rootOK - "auth sufficient pam_rootok.so"} - ${optionalString cfg.requireWheel - "auth required pam_wheel.so use_uid"} - ${optionalString cfg.logFailures - "auth required pam_faillock.so"} - ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) - "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles}"} - ${let p11 = config.security.pam.p11; in optionalString cfg.p11Auth - "auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so"} - ${let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth - "auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"}"} - ${optionalString cfg.usbAuth - "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"} - ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth - "auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"} - ${let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth - "auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"}"} - ${optionalString cfg.fprintAuth - "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"} - '' + + '' + + '' + + # Authentication management. + '' + + optionalString cfg.googleOsLoginAuthentication '' + auth [success=done perm_denied=bad default=ignore] ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so + '' + + optionalString cfg.rootOK '' + auth sufficient pam_rootok.so + '' + + optionalString cfg.requireWheel '' + auth required pam_wheel.so use_uid + '' + + optionalString cfg.logFailures '' + auth required pam_faillock.so + '' + + optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) '' + auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles} + '' + + (let p11 = config.security.pam.p11; in optionalString cfg.p11Auth '' + auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so + '') + + (let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth '' + auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"} + '') + + optionalString cfg.usbAuth '' + auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so + '' + + (let oath = config.security.pam.oath; in optionalString cfg.oathAuth '' + auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits} + '') + + (let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth '' + auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"} + '') + + optionalString cfg.fprintAuth '' + auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so + '' + # Modules in this block require having the password set in PAM_AUTHTOK. # pam_unix is marked as 'sufficient' on NixOS which means nothing will run # after it succeeds. Certain modules need to run after pam_unix @@ -457,115 +478,151 @@ let # earlier point and it will run again with 'sufficient' further down. # We use try_first_pass the second time to avoid prompting password twice (optionalString (cfg.unixAuth && - (config.security.pam.enableEcryptfs - || cfg.pamMount - || cfg.enableKwallet - || cfg.enableGnomeKeyring - || cfg.googleAuthenticator.enable - || cfg.gnupg.enable - || cfg.duoSecurity.enable)) '' - auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth - ${optionalString config.security.pam.enableEcryptfs - "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"} - ${optionalString cfg.pamMount - "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive"} - ${optionalString cfg.enableKwallet - ("auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" + - " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")} - ${optionalString cfg.enableGnomeKeyring - "auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"} - ${optionalString cfg.gnupg.enable - "auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so" - + optionalString cfg.gnupg.storeOnly " store-only" - } - ${optionalString cfg.googleAuthenticator.enable - "auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp"} - ${optionalString cfg.duoSecurity.enable - "auth required ${pkgs.duo-unix}/lib/security/pam_duo.so"} - '') + '' - ${optionalString cfg.unixAuth - "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass"} - ${optionalString cfg.otpwAuth - "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"} - ${optionalString use_ldap - "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"} - ${optionalString config.services.sssd.enable - "auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass"} - ${optionalString config.krb5.enable '' + (config.security.pam.enableEcryptfs + || cfg.pamMount + || cfg.enableKwallet + || cfg.enableGnomeKeyring + || cfg.googleAuthenticator.enable + || cfg.gnupg.enable + || cfg.duoSecurity.enable)) + ( + '' + auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth + '' + + optionalString config.security.pam.enableEcryptfs '' + auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap + '' + + optionalString cfg.pamMount '' + auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive + '' + + optionalString cfg.enableKwallet '' + auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 + '' + + optionalString cfg.enableGnomeKeyring '' + auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so + '' + + optionalString cfg.gnupg.enable '' + auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.storeOnly " store-only"} + '' + + optionalString cfg.googleAuthenticator.enable '' + auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp + '' + + optionalString cfg.duoSecurity.enable '' + auth required ${pkgs.duo-unix}/lib/security/pam_duo.so + '' + )) + + optionalString cfg.unixAuth '' + auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass + '' + + optionalString cfg.otpwAuth '' + auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so + '' + + optionalString use_ldap '' + auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass + '' + + optionalString config.services.sssd.enable '' + auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass + '' + + optionalString config.krb5.enable '' auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass - ''} - auth required pam_deny.so - - # Password management. - password sufficient pam_unix.so nullok sha512 - ${optionalString config.security.pam.enableEcryptfs - "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"} - ${optionalString cfg.pamMount - "password optional ${pkgs.pam_mount}/lib/security/pam_mount.so"} - ${optionalString use_ldap - "password sufficient ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString config.services.sssd.enable - "password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok"} - ${optionalString config.krb5.enable - "password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"} - ${optionalString cfg.enableGnomeKeyring - "password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok"} - - # Session management. - ${optionalString cfg.setEnvironment '' + '' + + '' + auth required pam_deny.so + + # Password management. + password sufficient pam_unix.so nullok sha512 + '' + + optionalString config.security.pam.enableEcryptfs '' + password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so + '' + + optionalString cfg.pamMount '' + password optional ${pkgs.pam_mount}/lib/security/pam_mount.so + '' + + optionalString use_ldap '' + password sufficient ${pam_ldap}/lib/security/pam_ldap.so + '' + + optionalString config.services.sssd.enable '' + password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok + '' + + optionalString config.krb5.enable '' + password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass + '' + + optionalString cfg.enableGnomeKeyring '' + password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok + '' + + '' + + # Session management. + '' + + optionalString cfg.setEnvironment '' session required pam_env.so conffile=/etc/pam/environment readenv=0 - ''} - session required pam_unix.so - ${optionalString cfg.setLoginUid - "session ${ - if config.boot.isContainer then "optional" else "required" - } pam_loginuid.so"} - ${optionalString cfg.ttyAudit.enable - "session required ${pkgs.pam}/lib/security/pam_tty_audit.so + '' + + '' + session required pam_unix.so + '' + + optionalString cfg.setLoginUid '' + session ${if config.boot.isContainer then "optional" else "required"} pam_loginuid.so + '' + + optionalString cfg.ttyAudit.enable '' + session required ${pkgs.pam}/lib/security/pam_tty_audit.so open_only=${toString cfg.ttyAudit.openOnly} ${optionalString (cfg.ttyAudit.enablePattern != null) "enable=${cfg.ttyAudit.enablePattern}"} ${optionalString (cfg.ttyAudit.disablePattern != null) "disable=${cfg.ttyAudit.disablePattern}"} - "} - ${optionalString cfg.makeHomeDir - "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077"} - ${optionalString cfg.updateWtmp - "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"} - ${optionalString config.security.pam.enableEcryptfs - "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"} - ${optionalString cfg.pamMount - "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive"} - ${optionalString use_ldap - "session optional ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString config.services.sssd.enable - "session optional ${pkgs.sssd}/lib/security/pam_sss.so"} - ${optionalString config.krb5.enable - "session optional ${pam_krb5}/lib/security/pam_krb5.so"} - ${optionalString cfg.otpwAuth - "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"} - ${optionalString cfg.startSession - "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"} - ${optionalString cfg.forwardXAuth - "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"} - ${optionalString (cfg.limits != []) - "session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"} - ${optionalString (cfg.showMotd && config.users.motd != null) - "session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"} - ${optionalString (cfg.enableAppArmor && config.security.apparmor.enable) - "session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"} - ${optionalString (cfg.enableKwallet) - ("session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" + - " kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")} - ${optionalString (cfg.enableGnomeKeyring) - "session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start"} - ${optionalString cfg.gnupg.enable - "session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so" - + optionalString cfg.gnupg.noAutostart " no-autostart" - } - ${optionalString (config.virtualisation.lxc.lxcfs.enable) - "session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all"} - ''); + '' + + optionalString cfg.makeHomeDir '' + session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077 + '' + + optionalString cfg.updateWtmp '' + session required ${pkgs.pam}/lib/security/pam_lastlog.so silent + '' + + optionalString config.security.pam.enableEcryptfs '' + session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so + '' + + optionalString cfg.pamMount '' + session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive + '' + + optionalString use_ldap '' + session optional ${pam_ldap}/lib/security/pam_ldap.so + '' + + optionalString config.services.sssd.enable '' + session optional ${pkgs.sssd}/lib/security/pam_sss.so + '' + + optionalString config.krb5.enable '' + session optional ${pam_krb5}/lib/security/pam_krb5.so + '' + + optionalString cfg.otpwAuth '' + session optional ${pkgs.otpw}/lib/security/pam_otpw.so + '' + + optionalString cfg.startSession '' + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + '' + + optionalString cfg.forwardXAuth '' + session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99 + '' + + optionalString (cfg.limits != []) '' + session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits} + '' + + optionalString (cfg.showMotd && config.users.motd != null) '' + session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd} + '' + + optionalString (cfg.enableAppArmor && config.security.apparmor.enable) '' + session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug + '' + + optionalString (cfg.enableKwallet) '' + session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 + '' + + optionalString (cfg.enableGnomeKeyring) '' + session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start + '' + + optionalString cfg.gnupg.enable '' + session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.noAutostart " no-autostart"} + '' + + optionalString (config.virtualisation.lxc.lxcfs.enable) '' + session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all + '' + ); }; }; diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix index 220c571b927e..b2147c1bbfc9 100644 --- a/nixos/modules/services/backup/borgbackup.nix +++ b/nixos/modules/services/backup/borgbackup.nix @@ -152,6 +152,7 @@ let serviceConfig = { # The service's only task is to ensure that the specified path exists Type = "oneshot"; + WorkingDirectory = cfg.path; }; wantedBy = [ "multi-user.target" ]; }; diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix index d53d68bdcf97..80c88714bfc1 100644 --- a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix +++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix @@ -1,10 +1,10 @@ /* -This file is for options that NixOS and nix-darwin have in common. + This file is for options that NixOS and nix-darwin have in common. -Platform-specific code is in the respective default.nix files. + Platform-specific code is in the respective default.nix files. - */ +*/ { config, lib, options, pkgs, ... }: let @@ -27,6 +27,16 @@ let settingsModule = { config, ... }: { freeformType = format.type; options = { + apiBaseUrl = mkOption { + description = '' + API base URL that the agent will connect to. + + When using Hercules CI Enterprise, set this to the URL where your + Hercules CI server is reachable. + ''; + type = types.str; + default = "https://hercules-ci.com"; + }; baseDirectory = mkOption { type = types.path; default = "/var/lib/hercules-ci-agent"; @@ -55,6 +65,25 @@ let type = types.either types.ints.positive (types.enum [ "auto" ]); default = "auto"; }; + labels = mkOption { + description = '' + A key-value map of user data. + + This data will be available to organization members in the dashboard and API. + + The values can be of any TOML type that corresponds to a JSON type, but arrays + can not contain tables/objects due to limitations of the TOML library. Values + involving arrays of non-primitive types may not be representable currently. + ''; + type = format.type; + defaultText = literalExpression '' + { + agent.source = "..."; # One of "nixpkgs", "flake", "override" + lib.version = "..."; + pkgs.version = "..."; + } + ''; + }; workDirectory = mkOption { description = '' The directory in which temporary subdirectories are created for task state. This includes sources for Nix evaluation. @@ -66,6 +95,8 @@ let staticSecretsDirectory = mkOption { description = '' This is the default directory to look for statically configured secrets like <literal>cluster-join-token.key</literal>. + + See also <literal>clusterJoinTokenPath</literal> and <literal>binaryCachesPath</literal> for fine-grained configuration. ''; type = types.path; default = config.baseDirectory + "/secrets"; @@ -74,24 +105,48 @@ let clusterJoinTokenPath = mkOption { description = '' Location of the cluster-join-token.key file. + + You can retrieve the contents of the file when creating a new agent via + <link xlink:href="https://hercules-ci.com/dashboard">https://hercules-ci.com/dashboard</link>. + + As this value is confidential, it should not be in the store, but + installed using other means, such as agenix, NixOps + <literal>deployment.keys</literal>, or manual installation. + + The contents of the file are used for authentication between the agent and the API. ''; type = types.path; default = config.staticSecretsDirectory + "/cluster-join-token.key"; defaultText = literalExpression ''staticSecretsDirectory + "/cluster-join-token.key"''; - # internal: It's a bit too detailed to show by default in the docs, - # but useful to define explicitly to allow reuse by other modules. - internal = true; }; binaryCachesPath = mkOption { description = '' - Location of the binary-caches.json file. + Path to a JSON file containing binary cache secret keys. + + As these values are confidential, they should not be in the store, but + copied over using other means, such as agenix, NixOps + <literal>deployment.keys</literal>, or manual installation. + + The format is described on <link xlink:href="https://docs.hercules-ci.com/hercules-ci-agent/binary-caches-json/">https://docs.hercules-ci.com/hercules-ci-agent/binary-caches-json/</link>. ''; type = types.path; default = config.staticSecretsDirectory + "/binary-caches.json"; defaultText = literalExpression ''staticSecretsDirectory + "/binary-caches.json"''; - # internal: It's a bit too detailed to show by default in the docs, - # but useful to define explicitly to allow reuse by other modules. - internal = true; + }; + secretsJsonPath = mkOption { + description = '' + Path to a JSON file containing secrets for effects. + + As these values are confidential, they should not be in the store, but + copied over using other means, such as agenix, NixOps + <literal>deployment.keys</literal>, or manual installation. + + The format is described on <link xlink:href="https://docs.hercules-ci.com/hercules-ci-agent/secrets-json/">https://docs.hercules-ci.com/hercules-ci-agent/secrets-json/</link>. + + ''; + type = types.path; + default = config.staticSecretsDirectory + "/secrets.json"; + defaultText = literalExpression ''staticSecretsDirectory + "/secrets.json"''; }; }; }; @@ -177,7 +232,7 @@ in These are written as options instead of let binding to allow sharing with default.nix on both NixOS and nix-darwin. - */ + */ tomlFile = mkOption { type = types.path; internal = true; diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix index 06c174e7d376..968bc8f1e54e 100644 --- a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix +++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix @@ -1,10 +1,10 @@ /* -This file is for NixOS-specific options and configs. + This file is for NixOS-specific options and configs. -Code that is shared with nix-darwin goes in common.nix. + Code that is shared with nix-darwin goes in common.nix. - */ +*/ { pkgs, config, lib, ... }: let diff --git a/nixos/modules/services/databases/clickhouse.nix b/nixos/modules/services/databases/clickhouse.nix index f2f4e9d25542..3a161d56107e 100644 --- a/nixos/modules/services/databases/clickhouse.nix +++ b/nixos/modules/services/databases/clickhouse.nix @@ -13,6 +13,15 @@ with lib; enable = mkEnableOption "ClickHouse database server"; + package = mkOption { + type = types.package; + default = pkgs.clickhouse; + defaultText = "pkgs.clickhouse"; + description = '' + ClickHouse package to use. + ''; + }; + }; }; @@ -45,21 +54,21 @@ with lib; AmbientCapabilities = "CAP_SYS_NICE"; StateDirectory = "clickhouse"; LogsDirectory = "clickhouse"; - ExecStart = "${pkgs.clickhouse}/bin/clickhouse-server --config-file=${pkgs.clickhouse}/etc/clickhouse-server/config.xml"; + ExecStart = "${cfg.package}/bin/clickhouse-server --config-file=${cfg.package}/etc/clickhouse-server/config.xml"; }; }; environment.etc = { "clickhouse-server/config.xml" = { - source = "${pkgs.clickhouse}/etc/clickhouse-server/config.xml"; + source = "${cfg.package}/etc/clickhouse-server/config.xml"; }; "clickhouse-server/users.xml" = { - source = "${pkgs.clickhouse}/etc/clickhouse-server/users.xml"; + source = "${cfg.package}/etc/clickhouse-server/users.xml"; }; }; - environment.systemPackages = [ pkgs.clickhouse ]; + environment.systemPackages = [ cfg.package ]; # startup requires a `/etc/localtime` which only if exists if `time.timeZone != null` time.timeZone = mkDefault "UTC"; diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix index ff01a1bcd98b..181be2d6b0b8 100644 --- a/nixos/modules/services/databases/hbase.nix +++ b/nixos/modules/services/databases/hbase.nix @@ -5,18 +5,27 @@ with lib; let cfg = config.services.hbase; - configFile = pkgs.writeText "hbase-site.xml" '' - <configuration> - <property> - <name>hbase.rootdir</name> - <value>file://${cfg.dataDir}/hbase</value> - </property> - <property> - <name>hbase.zookeeper.property.dataDir</name> - <value>${cfg.dataDir}/zookeeper</value> - </property> - </configuration> - ''; + defaultConfig = { + "hbase.rootdir" = "file://${cfg.dataDir}/hbase"; + "hbase.zookeeper.property.dataDir" = "${cfg.dataDir}/zookeeper"; + }; + + buildProperty = configAttr: + (builtins.concatStringsSep "\n" + (lib.mapAttrsToList + (name: value: '' + <property> + <name>${name}</name> + <value>${builtins.toString value}</value> + </property> + '') + configAttr)); + + configFile = pkgs.writeText "hbase-site.xml" + ''<configuration> + ${buildProperty (defaultConfig // cfg.settings)} + </configuration> + ''; configDir = pkgs.runCommand "hbase-config-dir" { preferLocalBuild = true; } '' mkdir -p $out @@ -85,6 +94,14 @@ in { ''; }; + settings = mkOption { + type = with lib.types; attrsOf (oneOf [ str int bool ]); + default = defaultConfig; + description = '' + configurations in hbase-site.xml, see <link xlink:href="https://github.com/apache/hbase/blob/master/hbase-server/src/test/resources/hbase-site.xml"/> for details. + ''; + }; + }; }; diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix index 7f75ac272d40..69a66723e76c 100644 --- a/nixos/modules/services/hardware/bluetooth.nix +++ b/nixos/modules/services/hardware/bluetooth.nix @@ -11,12 +11,8 @@ let cfgFmt = pkgs.formats.ini { }; - # bluez will complain if some of the sections are not found, so just make them - # empty (but present in the file) for now defaults = { General.ControllerMode = "dual"; - Controller = { }; - GATT = { }; Policy.AutoEnable = cfg.powerOnBoot; }; diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix index 624b6cfb1215..ba5d6e29d0bd 100644 --- a/nixos/modules/services/logging/logrotate.nix +++ b/nixos/modules/services/logging/logrotate.nix @@ -40,7 +40,7 @@ let }; frequency = mkOption { - type = types.enum [ "daily" "weekly" "monthly" "yearly" ]; + type = types.enum [ "hourly" "daily" "weekly" "monthly" "yearly" ]; default = "daily"; description = '' How often to rotate the logs. @@ -155,7 +155,7 @@ in systemd.services.logrotate = { description = "Logrotate Service"; wantedBy = [ "multi-user.target" ]; - startAt = "*-*-* *:05:00"; + startAt = "hourly"; script = '' exec ${pkgs.logrotate}/sbin/logrotate ${configFile} ''; diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index 044d5330231e..a08203dffe78 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -23,12 +23,16 @@ let logstashSettingsYml = pkgs.writeText "logstash.yml" cfg.extraSettings; + logstashJvmOptionsFile = pkgs.writeText "jvm.options" cfg.extraJvmOptions; + logstashSettingsDir = pkgs.runCommand "logstash-settings" { + inherit logstashJvmOptionsFile; inherit logstashSettingsYml; preferLocalBuild = true; } '' mkdir -p $out ln -s $logstashSettingsYml $out/logstash.yml + ln -s $logstashJvmOptionsFile $out/jvm.options ''; in @@ -152,6 +156,15 @@ in ''; }; + extraJvmOptions = mkOption { + type = types.lines; + default = ""; + description = "Extra JVM options, one per line (jvm.options format)."; + example = '' + -Xms2g + -Xmx2g + ''; + }; }; }; diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 223f3bef77db..c39827c5b867 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -103,11 +103,12 @@ let plugin { quota_rule = *:storage=${cfg.quotaGlobalPerUser} - quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working + quota = count:User quota # per virtual mail user quota quota_status_success = DUNNO quota_status_nouser = DUNNO quota_status_overquota = "552 5.2.2 Mailbox is full" quota_grace = 10%% + quota_vsizes = yes } '' ) diff --git a/nixos/modules/services/matrix/mjolnir.nix b/nixos/modules/services/matrix/mjolnir.nix index 8a54f93d98d8..278924b05cf2 100644 --- a/nixos/modules/services/matrix/mjolnir.nix +++ b/nixos/modules/services/matrix/mjolnir.nix @@ -14,6 +14,8 @@ let else cfg.homeserverUrl; + rawHomeserverUrl = cfg.homeserverUrl; + pantalaimon = { inherit (cfg.pantalaimon) username; diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix index 4053afa69be5..cad73a871ba6 100644 --- a/nixos/modules/services/misc/gollum.nix +++ b/nixos/modules/services/misc/gollum.nix @@ -100,6 +100,7 @@ in serviceConfig = { User = config.users.users.gollum.name; Group = config.users.groups.gollum.name; + WorkingDirectory = cfg.stateDir; ExecStart = '' ${pkgs.gollum}/bin/gollum \ --port ${toString cfg.port} \ diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 4ea45888e5fc..fb643e7a66e1 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -74,6 +74,8 @@ in imports = [ (mkRenamedOptionModule [ "nix" "useChroot" ] [ "nix" "useSandbox" ]) (mkRenamedOptionModule [ "nix" "chrootDirs" ] [ "nix" "sandboxPaths" ]) + (mkRenamedOptionModule [ "nix" "daemonIONiceLevel" ] [ "nix" "daemonIOSchedPriority" ]) + (mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] "Consider nix.daemonCPUSchedPolicy instead.") ]; ###### interface @@ -546,7 +548,7 @@ in [ nix pkgs.nix-info ] - ++ optional (config.programs.bash.enableCompletion && !versionAtLeast nixVersion "2.4pre") pkgs.nix-bash-completions; + ++ optional (config.programs.bash.enableCompletion) pkgs.nix-bash-completions; environment.etc."nix/nix.conf".source = nixConf; diff --git a/nixos/modules/services/misc/xmrig.nix b/nixos/modules/services/misc/xmrig.nix index 15c7d2a7b14c..cf01bb119e89 100644 --- a/nixos/modules/services/misc/xmrig.nix +++ b/nixos/modules/services/misc/xmrig.nix @@ -51,6 +51,8 @@ with lib; }; config = mkIf cfg.enable { + boot.kernelModules = [ "msr" ]; + systemd.services.xmrig = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; @@ -58,14 +60,16 @@ with lib; serviceConfig = { ExecStartPre = "${cfg.package}/bin/xmrig --config=${configFile} --dry-run"; ExecStart = "${cfg.package}/bin/xmrig --config=${configFile}"; - DynamicUser = true; + # https://xmrig.com/docs/miner/randomx-optimization-guide/msr + # If you use recent XMRig with root privileges (Linux) or admin + # privileges (Windows) the miner configure all MSR registers + # automatically. + DynamicUser = lib.mkDefault false; }; }; }; meta = with lib; { - description = "XMRig Mining Software Service"; - license = licenses.gpl3Only; maintainers = with maintainers; [ ratsclub ]; }; } diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix index da051dbe4655..dfbf07efcaea 100644 --- a/nixos/modules/services/monitoring/cadvisor.nix +++ b/nixos/modules/services/monitoring/cadvisor.nix @@ -111,6 +111,8 @@ in { wantedBy = [ "multi-user.target" ]; after = [ "network.target" "docker.service" "influxdb.service" ]; + path = optionals config.boot.zfs.enabled [ pkgs.zfs ]; + postStart = mkBefore '' until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/containers/'; do sleep 1; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix index 5ee8c346be1d..3cdd7866bd4d 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix @@ -47,7 +47,7 @@ in ExecStart = '' ${pkgs.prometheus-nginx-exporter}/bin/nginx-prometheus-exporter \ --nginx.scrape-uri '${cfg.scrapeUri}' \ - --nginx.ssl-verify ${toString cfg.sslVerify} \ + --nginx.ssl-verify ${boolToString cfg.sslVerify} \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ --web.telemetry-path ${cfg.telemetryPath} \ --prometheus.const-labels ${concatStringsSep "," cfg.constLabels} \ diff --git a/nixos/modules/services/monitoring/zabbix-server.nix b/nixos/modules/services/monitoring/zabbix-server.nix index 9b0fd9dbff13..0141c073da25 100644 --- a/nixos/modules/services/monitoring/zabbix-server.nix +++ b/nixos/modules/services/monitoring/zabbix-server.nix @@ -250,7 +250,12 @@ in }; security.wrappers = { - fping.source = "${pkgs.fping}/bin/fping"; + fping = + { setuid = true; + owner = "root"; + group = "root"; + source = "${pkgs.fping}/bin/fping"; + }; }; systemd.services.zabbix-server = { diff --git a/nixos/modules/services/network-filesystems/webdav-server-rs.nix b/nixos/modules/services/network-filesystems/webdav-server-rs.nix new file mode 100644 index 000000000000..1c5c299cb673 --- /dev/null +++ b/nixos/modules/services/network-filesystems/webdav-server-rs.nix @@ -0,0 +1,144 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.webdav-server-rs; + format = pkgs.formats.toml { }; + settings = recursiveUpdate + { + server.uid = config.users.users."${cfg.user}".uid; + server.gid = config.users.groups."${cfg.group}".gid; + } + cfg.settings; +in +{ + options = { + services.webdav-server-rs = { + enable = mkEnableOption "WebDAV server"; + + user = mkOption { + type = types.str; + default = "webdav"; + description = "User to run under when setuid is not enabled."; + }; + + group = mkOption { + type = types.str; + default = "webdav"; + description = "Group to run under when setuid is not enabled."; + }; + + settings = mkOption { + type = format.type; + default = { }; + description = '' + Attrset that is converted and passed as config file. Available + options can be found at + <link xlink:href="https://github.com/miquels/webdav-server-rs/blob/master/webdav-server.toml">here</link>. + ''; + example = literalExpression '' + { + server.listen = [ "0.0.0.0:4918" "[::]:4918" ]; + accounts = { + auth-type = "htpasswd.default"; + acct-type = "unix"; + }; + htpasswd.default = { + htpasswd = "/etc/htpasswd"; + }; + location = [ + { + route = [ "/public/*path" ]; + directory = "/srv/public"; + handler = "filesystem"; + methods = [ "webdav-ro" ]; + autoindex = true; + auth = "false"; + } + { + route = [ "/user/:user/*path" ]; + directory = "~"; + handler = "filesystem"; + methods = [ "webdav-rw" ]; + autoindex = true; + auth = "true"; + setuid = true; + } + ]; + } + ''; + }; + + configFile = mkOption { + type = types.path; + default = format.generate "webdav-server.toml" settings; + defaultText = "Config file generated from services.webdav-server-rs.settings"; + description = '' + Path to config file. If this option is set, it will override any + configuration done in services.webdav-server-rs.settings. + ''; + example = "/etc/webdav-server.toml"; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = hasAttr cfg.user config.users.users && config.users.users."${cfg.user}".uid != null; + message = "users.users.${cfg.user} and users.users.${cfg.user}.uid must be defined."; + } + { + assertion = hasAttr cfg.group config.users.groups && config.users.groups."${cfg.group}".gid != null; + message = "users.groups.${cfg.group} and users.groups.${cfg.group}.gid must be defined."; + } + ]; + + users.users = optionalAttrs (cfg.user == "webdav") { + webdav = { + description = "WebDAV user"; + group = cfg.group; + uid = config.ids.uids.webdav; + }; + }; + + users.groups = optionalAttrs (cfg.group == "webdav") { + webdav.gid = config.ids.gids.webdav; + }; + + systemd.services.webdav-server-rs = { + description = "WebDAV server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.webdav-server-rs}/bin/webdav-server -c ${cfg.configFile}"; + + CapabilityBoundingSet = [ + "CAP_SETUID" + "CAP_SETGID" + ]; + + NoExecPaths = [ "/" ]; + ExecPaths = [ "/nix/store" ]; + + # This program actively detects if it is running in root user account + # when it starts and uses root privilege to switch process uid to + # respective unix user when a user logs in. Maybe we can enable + # DynamicUser in the future when it's able to detect CAP_SETUID and + # CAP_SETGID capabilities. + + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = true; + }; + }; + }; + + meta.maintainers = with maintainers; [ pmy ]; +} diff --git a/nixos/modules/services/network-filesystems/webdav.nix b/nixos/modules/services/network-filesystems/webdav.nix new file mode 100644 index 000000000000..a810af40fd47 --- /dev/null +++ b/nixos/modules/services/network-filesystems/webdav.nix @@ -0,0 +1,107 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.webdav; + format = pkgs.formats.yaml { }; +in +{ + options = { + services.webdav = { + enable = mkEnableOption "WebDAV server"; + + user = mkOption { + type = types.str; + default = "webdav"; + description = "User account under which WebDAV runs."; + }; + + group = mkOption { + type = types.str; + default = "webdav"; + description = "Group under which WebDAV runs."; + }; + + settings = mkOption { + type = format.type; + default = { }; + description = '' + Attrset that is converted and passed as config file. Available options + can be found at + <link xlink:href="https://github.com/hacdias/webdav">here</link>. + + This program supports reading username and password configuration + from environment variables, so it's strongly recommended to store + username and password in a separate + <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=">EnvironmentFile</link>. + This prevents adding secrets to the world-readable Nix store. + ''; + example = literalExpression '' + { + address = "0.0.0.0"; + port = 8080; + scope = "/srv/public"; + modify = true; + auth = true; + users = [ + { + username = "{env}ENV_USERNAME"; + password = "{env}ENV_PASSWORD"; + } + ]; + } + ''; + }; + + configFile = mkOption { + type = types.path; + default = format.generate "webdav.yaml" cfg.settings; + defaultText = "Config file generated from services.webdav.settings"; + description = '' + Path to config file. If this option is set, it will override any + configuration done in options.services.webdav.settings. + ''; + example = "/etc/webdav/config.yaml"; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Environment file as defined in <citerefentry> + <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.users = mkIf (cfg.user == "webdav") { + webdav = { + description = "WebDAV daemon user"; + group = cfg.group; + uid = config.ids.uids.webdav; + }; + }; + + users.groups = mkIf (cfg.group == "webdav") { + webdav.gid = config.ids.gids.webdav; + }; + + systemd.services.webdav = { + description = "WebDAV server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.webdav}/bin/webdav -c ${cfg.configFile}"; + Restart = "on-failure"; + User = cfg.user; + Group = cfg.group; + EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ]; + }; + }; + }; + + meta.maintainers = with maintainers; [ pmy ]; +} diff --git a/nixos/modules/services/networking/monero.nix b/nixos/modules/services/networking/monero.nix index 9a9084e4ce1a..8bed89917c85 100644 --- a/nixos/modules/services/networking/monero.nix +++ b/nixos/modules/services/networking/monero.nix @@ -222,7 +222,7 @@ in serviceConfig = { User = "monero"; Group = "monero"; - ExecStart = "${pkgs.monero}/bin/monerod --config-file=${configFile} --non-interactive"; + ExecStart = "${pkgs.monero-cli}/bin/monerod --config-file=${configFile} --non-interactive"; Restart = "always"; SuccessExitStatus = [ 0 1 ]; }; diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 74daf0ae9faf..73e63e2ee99b 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -527,7 +527,6 @@ in { { networkmanager.connectionConfig = { - "ipv6.ip6-privacy" = 2; "ethernet.cloned-mac-address" = cfg.ethernet.macAddress; "wifi.cloned-mac-address" = cfg.wifi.macAddress; "wifi.powersave" = diff --git a/nixos/modules/services/networking/nomad.nix b/nixos/modules/services/networking/nomad.nix index 3bd15bd5c808..43333af5e2fe 100644 --- a/nixos/modules/services/networking/nomad.nix +++ b/nixos/modules/services/networking/nomad.nix @@ -51,7 +51,7 @@ in extraSettingsPaths = mkOption { type = types.listOf types.path; - default = []; + default = [ ]; description = '' Additional settings paths used to configure nomad. These can be files or directories. ''; @@ -60,9 +60,21 @@ in ''; }; + extraSettingsPlugins = mkOption { + type = types.listOf (types.either types.package types.path); + default = [ ]; + description = '' + Additional plugins dir used to configure nomad. + ''; + example = literalExpression '' + [ "<pluginDir>" "pkgs.<plugins-name>"] + ''; + }; + + settings = mkOption { type = format.type; - default = {}; + default = { }; description = '' Configuration for Nomad. See the <link xlink:href="https://www.nomadproject.io/docs/configuration">documentation</link> for supported values. @@ -128,7 +140,8 @@ in DynamicUser = cfg.dropPrivileges; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecStart = "${cfg.package}/bin/nomad agent -config=/etc/nomad.json" + - concatMapStrings (path: " -config=${path}") cfg.extraSettingsPaths; + concatMapStrings (path: " -config=${path}") cfg.extraSettingsPaths + + concatMapStrings (path: " -plugin-dir=${path}/bin") cfg.extraSettingsPlugins; KillMode = "process"; KillSignal = "SIGINT"; LimitNOFILE = 65536; diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix index c121008d5294..c6c40777ed7c 100644 --- a/nixos/modules/services/networking/radicale.nix +++ b/nixos/modules/services/networking/radicale.nix @@ -195,6 +195,7 @@ in { SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; UMask = "0027"; + WorkingDirectory = "/var/lib/radicale"; }; }; }; diff --git a/nixos/modules/services/networking/sabnzbd.nix b/nixos/modules/services/networking/sabnzbd.nix index 43566dfd25c5..54eeba1a9ec1 100644 --- a/nixos/modules/services/networking/sabnzbd.nix +++ b/nixos/modules/services/networking/sabnzbd.nix @@ -17,6 +17,13 @@ in services.sabnzbd = { enable = mkEnableOption "the sabnzbd server"; + package = mkOption { + type = types.package; + default = pkgs.sabnzbd; + defaultText = "pkgs.sabnzbd"; + description = "The sabnzbd executable package run by the service."; + }; + configFile = mkOption { type = types.path; default = "/var/lib/sabnzbd/sabnzbd.ini"; @@ -63,7 +70,7 @@ in GuessMainPID = "no"; User = "${cfg.user}"; Group = "${cfg.group}"; - ExecStart = "${sabnzbd}/bin/sabnzbd -d -f ${cfg.configFile}"; + ExecStart = "${lib.getBin cfg.package}/bin/sabnzbd -d -f ${cfg.configFile}"; }; }; }; diff --git a/nixos/modules/services/ttys/getty.nix b/nixos/modules/services/ttys/getty.nix index 8c5b6e5e0cbc..7021a2c80f85 100644 --- a/nixos/modules/services/ttys/getty.nix +++ b/nixos/modules/services/ttys/getty.nix @@ -24,6 +24,7 @@ in imports = [ (mkRenamedOptionModule [ "services" "mingetty" ] [ "services" "getty" ]) + (mkRemovedOptionModule [ "services" "getty" "serialSpeed" ] ''set non-standard baudrates with `boot.kernelParams` i.e. boot.kernelParams = ["console=ttyS2,1500000"];'') ]; options = { @@ -92,17 +93,6 @@ in ''; }; - serialSpeed = mkOption { - type = types.listOf types.int; - default = [ 115200 57600 38400 9600 ]; - example = [ 38400 9600 ]; - description = '' - Bitrates to allow for agetty's listening on serial ports. Listing more - bitrates gives more interoperability but at the cost of long delays - for getting a sync on the line. - ''; - }; - }; }; @@ -124,10 +114,9 @@ in }; systemd.services."serial-getty@" = - let speeds = concatStringsSep "," (map toString config.services.getty.serialSpeed); in { serviceConfig.ExecStart = [ "" # override upstream default with an empty ExecStart - (gettyCmd "%I --keep-baud ${speeds} $TERM") + (gettyCmd "%I --keep-baud $TERM") ]; restartIfChanged = false; }; diff --git a/nixos/modules/services/web-apps/moodle.nix b/nixos/modules/services/web-apps/moodle.nix index 6f5cfa2e3481..19f3e754691e 100644 --- a/nixos/modules/services/web-apps/moodle.nix +++ b/nixos/modules/services/web-apps/moodle.nix @@ -57,7 +57,7 @@ let pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql"; phpExt = pkgs.php74.withExtensions - ({ enabled, all }: with all; [ iconv mbstring curl openssl tokenizer xmlrpc soap ctype zip gd simplexml dom intl json sqlite3 pgsql pdo_sqlite pdo_pgsql pdo_odbc pdo_mysql pdo mysqli session zlib xmlreader fileinfo filter ]); + ({ enabled, all }: with all; [ iconv mbstring curl openssl tokenizer xmlrpc soap ctype zip gd simplexml dom intl json sqlite3 pgsql pdo_sqlite pdo_pgsql pdo_odbc pdo_mysql pdo mysqli session zlib xmlreader fileinfo filter opcache ]); in { # interface diff --git a/nixos/modules/services/web-servers/caddy/default.nix b/nixos/modules/services/web-servers/caddy/default.nix index cef27e2e59f3..ed27dd375c86 100644 --- a/nixos/modules/services/web-servers/caddy/default.nix +++ b/nixos/modules/services/web-servers/caddy/default.nix @@ -171,34 +171,27 @@ in }; config = mkIf cfg.enable { + systemd.packages = [ cfg.package ]; systemd.services.caddy = { - description = "Caddy web server"; - # upstream unit: https://github.com/caddyserver/dist/blob/master/init/caddy.service - after = [ "network-online.target" ]; - wants = [ "network-online.target" ]; # systemd-networkd-wait-online.service wantedBy = [ "multi-user.target" ]; startLimitIntervalSec = 14400; startLimitBurst = 10; + serviceConfig = { - ExecStart = "${cfg.package}/bin/caddy run ${optionalString cfg.resume "--resume"} --config ${configJSON}"; - ExecReload = "${cfg.package}/bin/caddy reload --config ${configJSON}"; - Type = "simple"; + # https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= + # If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect. + ExecStart = [ "" "${cfg.package}/bin/caddy run ${optionalString cfg.resume "--resume"} --config ${configJSON}" ]; + ExecReload = [ "" "${cfg.package}/bin/caddy reload --config ${configJSON}" ]; + User = cfg.user; Group = cfg.group; + ReadWriteDirectories = cfg.dataDir; Restart = "on-abnormal"; - AmbientCapabilities = "cap_net_bind_service"; - CapabilityBoundingSet = "cap_net_bind_service"; + + # TODO: attempt to upstream these options NoNewPrivileges = true; - LimitNPROC = 512; - LimitNOFILE = 1048576; - PrivateTmp = true; PrivateDevices = true; ProtectHome = true; - ProtectSystem = "full"; - ReadWriteDirectories = cfg.dataDir; - KillMode = "mixed"; - KillSignal = "SIGQUIT"; - TimeoutStopSec = "5s"; }; }; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index be589e42ddd6..5717b86b3bea 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -896,7 +896,7 @@ in PrivateMounts = true; # System Call Filtering SystemCallArchitectures = "native"; - SystemCallFilter = "~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid"; + SystemCallFilter = "~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid @mincore"; }; }; diff --git a/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixos/modules/services/x11/desktop-managers/cinnamon.nix index a0a5873f72fe..82b07206a8b6 100644 --- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix +++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix @@ -202,6 +202,13 @@ in blueberry warpinator + # cinnamon xapps + xviewer + xreader + xed + xplayer + pix + # external apps shipped with linux-mint hexchat gnome-calculator diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index e036c684c886..6f0d645725e9 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -83,14 +83,14 @@ in default = true; description = '' Allow GDM to run on Wayland instead of Xserver. - Note to enable Wayland with Nvidia you need to - enable the <option>nvidiaWayland</option>. + Note to enable Wayland with Nvidia the <option>nvidiaWayland</option> + must not be disabled. ''; }; nvidiaWayland = mkOption { type = types.bool; - default = false; + default = true; description = '' Whether to allow wayland to be used with the proprietary NVidia graphics driver. diff --git a/nixos/modules/services/x11/display-managers/startx.nix b/nixos/modules/services/x11/display-managers/startx.nix index 6cd46cdf9649..a48566ae0684 100644 --- a/nixos/modules/services/x11/display-managers/startx.nix +++ b/nixos/modules/services/x11/display-managers/startx.nix @@ -35,10 +35,7 @@ in config = mkIf cfg.enable { services.xserver = { exportConfiguration = true; - displayManager.job.execCmd = ""; - displayManager.lightdm.enable = lib.mkForce false; }; - systemd.services.display-manager.enable = false; # Other displayManagers log to /dev/null because they're services and put # Xorg's stdout in the journal diff --git a/nixos/modules/services/x11/display-managers/sx.nix b/nixos/modules/services/x11/display-managers/sx.nix index 73d27390a580..e30977364300 100644 --- a/nixos/modules/services/x11/display-managers/sx.nix +++ b/nixos/modules/services/x11/display-managers/sx.nix @@ -26,13 +26,8 @@ in { environment.systemPackages = [ pkgs.sx ]; services.xserver = { exportConfiguration = true; - displayManager = { - job.execCmd = ""; - lightdm.enable = mkForce false; - }; logFile = mkDefault null; }; - systemd.services.display-manager.enable = false; }; meta.maintainers = with maintainers; [ figsoda ]; diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/x11/hardware/libinput.nix index e2fb7d0918e3..efdb7c61dfae 100644 --- a/nixos/modules/services/x11/hardware/libinput.nix +++ b/nixos/modules/services/x11/hardware/libinput.nix @@ -13,7 +13,7 @@ let cfg = config.services.xserver.libinput; example = "/dev/input/event0"; description = '' - Path for ${deviceType} device. Set to null to apply to any + Path for ${deviceType} device. Set to <literal>null</literal> to apply to any auto-detected ${deviceType}. ''; }; @@ -24,8 +24,8 @@ let cfg = config.services.xserver.libinput; example = "flat"; description = '' - Sets the pointer acceleration profile to the given profile. - Permitted values are adaptive, flat. + Sets the pointer acceleration profile to the given profile. + Permitted values are <literal>adaptive</literal>, <literal>flat</literal>. Not all devices support this option or all profiles. If a profile is unsupported, the default profile for this is used. <literal>flat</literal>: Pointer motion is accelerated by a constant @@ -38,12 +38,14 @@ let cfg = config.services.xserver.libinput; accelSpeed = mkOption { type = types.nullOr types.str; default = null; + example = "-0.5"; description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed)."; }; buttonMapping = mkOption { type = types.nullOr types.str; default = null; + example = "1 6 3 4 5 0 7"; description = '' Sets the logical button mapping for this device, see XSetPointerMapping(3). The string must @@ -58,9 +60,10 @@ let cfg = config.services.xserver.libinput; calibrationMatrix = mkOption { type = types.nullOr types.str; default = null; + example = "0.5 0 0 0 0.8 0.1 0 0 1"; description = '' - A string of 9 space-separated floating point numbers. Sets the calibration matrix to the + A string of 9 space-separated floating point numbers. Sets the calibration matrix to the 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi). ''; }; @@ -68,6 +71,7 @@ let cfg = config.services.xserver.libinput; clickMethod = mkOption { type = types.nullOr (types.enum [ "none" "buttonareas" "clickfinger" ]); default = null; + example = "buttonareas"; description = '' Enables a click method. Permitted values are <literal>none</literal>, @@ -166,8 +170,9 @@ let cfg = config.services.xserver.libinput; transformationMatrix = mkOption { type = types.nullOr types.str; default = null; + example = "0.5 0 0 0 0.8 0.1 0 0 1"; description = '' - A string of 9 space-separated floating point numbers. Sets the transformation matrix to + A string of 9 space-separated floating point numbers. Sets the transformation matrix to the 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi). ''; }; diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix index 6aa0d5f76f26..a8f38046137a 100644 --- a/nixos/modules/services/x11/window-managers/xmonad.nix +++ b/nixos/modules/services/x11/window-managers/xmonad.nix @@ -29,7 +29,6 @@ let } '' install -D ${xmonadEnv}/share/man/man1/xmonad.1.gz $out/share/man/man1/xmonad.1.gz makeWrapper ${configured}/bin/xmonad $out/bin/xmonad \ - --set NIX_GHC "${xmonadEnv}/bin/ghc" \ --set XMONAD_XMESSAGE "${pkgs.xorg.xmessage}/bin/xmessage" ''; @@ -93,6 +92,8 @@ in { <literal>(restart "xmonad" True)</literal> instead, which will just restart xmonad from PATH. This allows e.g. switching to the new xmonad binary after rebuilding your system with nixos-rebuild. + For the same reason, ghc is not added to the environment when this + option is set. If you actually want to run xmonad with a config specified here, but also be able to recompile and restart it from a copy of that source in diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index cb620f10b13f..24d925734423 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -588,11 +588,22 @@ in config = mkIf cfg.enable { services.xserver.displayManager.lightdm.enable = - let dmconf = cfg.displayManager; - default = !(dmconf.gdm.enable - || dmconf.sddm.enable - || dmconf.xpra.enable ); - in mkIf (default) true; + let dmConf = cfg.displayManager; + default = !(dmConf.gdm.enable + || dmConf.sddm.enable + || dmConf.xpra.enable + || dmConf.sx.enable + || dmConf.startx.enable); + in mkIf (default) (mkDefault true); + + # so that the service won't be enabled when only startx is used + systemd.services.display-manager.enable = + let dmConf = cfg.displayManager; + noDmUsed = !(dmConf.gdm.enable + || dmConf.sddm.enable + || dmConf.xpra.enable + || dmConf.lightdm.enable); + in mkIf (noDmUsed) (mkDefault false); hardware.opengl.enable = mkDefault true; @@ -702,7 +713,8 @@ in rm -f /tmp/.X0-lock ''; - script = "${cfg.displayManager.job.execCmd}"; + # TODO: move declaring the systemd service to its own mkIf + script = mkIf (config.systemd.services.display-manager.enable == true) "${cfg.displayManager.job.execCmd}"; # Stop restarting if the display manager stops (crashes) 2 times # in one minute. Starting X typically takes 3-4s. diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index e105502cf3a4..053496441d81 100644 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -11,6 +11,7 @@ use Cwd 'abs_path'; my $out = "@out@"; +# FIXME: maybe we should use /proc/1/exe to get the current systemd. my $curSystemd = abs_path("/run/current-system/sw/bin"); # To be robust against interruption, record what units need to be started etc. @@ -18,16 +19,13 @@ my $startListFile = "/run/nixos/start-list"; my $restartListFile = "/run/nixos/restart-list"; my $reloadListFile = "/run/nixos/reload-list"; -# Parse restart/reload requests by the activation script. -# Activation scripts may write newline-separated units to this -# file and switch-to-configuration will handle them. While -# `stopIfChanged = true` is ignored, switch-to-configuration will -# handle `restartIfChanged = false` and `reloadIfChanged = true`. -# This also works for socket-activated units. +# Parse restart/reload requests by the activation script my $restartByActivationFile = "/run/nixos/activation-restart-list"; +my $reloadByActivationFile = "/run/nixos/activation-reload-list"; my $dryRestartByActivationFile = "/run/nixos/dry-activation-restart-list"; +my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list"; -make_path("/run/nixos", { mode => oct(755) }); +make_path("/run/nixos", { mode => 0755 }); my $action = shift @ARGV; @@ -149,92 +147,6 @@ sub fingerprintUnit { return abs_path($s) . (-f "${s}.d/overrides.conf" ? " " . abs_path "${s}.d/overrides.conf" : ""); } -sub handleModifiedUnit { - my ($unit, $baseName, $newUnitFile, $activePrev, $unitsToStop, $unitsToStart, $unitsToReload, $unitsToRestart, $unitsToSkip) = @_; - - if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.slice$/ || $unit =~ /\.path$/) { - # Do nothing. These cannot be restarted directly. - # Slices and Paths don't have to be restarted since - # properties (resource limits and inotify watches) - # seem to get applied on daemon-reload. - } elsif ($unit =~ /\.mount$/) { - # Reload the changed mount unit to force a remount. - $unitsToReload->{$unit} = 1; - recordUnit($reloadListFile, $unit); - } else { - my $unitInfo = parseUnit($newUnitFile); - if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) { - $unitsToReload->{$unit} = 1; - recordUnit($reloadListFile, $unit); - } - elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) { - $unitsToSkip->{$unit} = 1; - } else { - # If this unit is socket-activated, then stop it instead - # of restarting it to make sure the new version of it is - # socket-activated. - my $socketActivated = 0; - if ($unit =~ /\.service$/) { - my @sockets = split / /, ($unitInfo->{Sockets} // ""); - if (scalar @sockets == 0) { - @sockets = ("$baseName.socket"); - } - foreach my $socket (@sockets) { - if (-e "$out/etc/systemd/system/$socket") { - $socketActivated = 1; - $unitsToStop->{$unit} = 1; - # If the socket was not running previously, - # start it now. - if (not defined $activePrev->{$socket}) { - $unitsToStart->{$socket} = 1; - } - } - } - } - - # Don't do the rest of this for socket-activated units - # because we handled these above where we stop the unit. - # Since only services can be socket-activated, the - # following condition always evaluates to `true` for - # non-service units. - if ($socketActivated) { - return; - } - - # If we are restarting a socket, also stop the corresponding - # service. This is required because restarting a socket - # when the service is already activated fails. - if ($unit =~ /\.socket$/) { - my $service = $unitInfo->{Service} // ""; - if ($service eq "") { - $service = "$baseName.service"; - } - if (defined $activePrev->{$service}) { - $unitsToStop->{$service} = 1; - } - $unitsToRestart->{$unit} = 1; - recordUnit($restartListFile, $unit); - } else { - # Always restart non-services instead of stopping and starting them - # because it doesn't make sense to stop them with a config from - # the old evaluation. - if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes") || $unit !~ /\.service$/) { - # This unit should be restarted instead of - # stopped and started. - $unitsToRestart->{$unit} = 1; - recordUnit($restartListFile, $unit); - } else { - # We write to a file to ensure that the - # service gets restarted if we're interrupted. - $unitsToStart->{$unit} = 1; - recordUnit($startListFile, $unit); - $unitsToStop->{$unit} = 1; - } - } - } - } -} - # Figure out what units need to be stopped, started, restarted or reloaded. my (%unitsToStop, %unitsToSkip, %unitsToStart, %unitsToRestart, %unitsToReload); @@ -307,7 +219,65 @@ while (my ($unit, $state) = each %{$activePrev}) { } elsif (fingerprintUnit($prevUnitFile) ne fingerprintUnit($newUnitFile)) { - handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToSkip); + if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target") { + # Do nothing. These cannot be restarted directly. + } elsif ($unit =~ /\.mount$/) { + # Reload the changed mount unit to force a remount. + $unitsToReload{$unit} = 1; + recordUnit($reloadListFile, $unit); + } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/ || $unit =~ /\.slice$/) { + # FIXME: do something? + } else { + my $unitInfo = parseUnit($newUnitFile); + if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) { + $unitsToReload{$unit} = 1; + recordUnit($reloadListFile, $unit); + } + elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) { + $unitsToSkip{$unit} = 1; + } else { + if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) { + # This unit should be restarted instead of + # stopped and started. + $unitsToRestart{$unit} = 1; + recordUnit($restartListFile, $unit); + } else { + # If this unit is socket-activated, then stop the + # socket unit(s) as well, and restart the + # socket(s) instead of the service. + my $socketActivated = 0; + if ($unit =~ /\.service$/) { + my @sockets = split / /, ($unitInfo->{Sockets} // ""); + if (scalar @sockets == 0) { + @sockets = ("$baseName.socket"); + } + foreach my $socket (@sockets) { + if (defined $activePrev->{$socket}) { + $unitsToStop{$socket} = 1; + # Only restart sockets that actually + # exist in new configuration: + if (-e "$out/etc/systemd/system/$socket") { + $unitsToStart{$socket} = 1; + recordUnit($startListFile, $socket); + $socketActivated = 1; + } + } + } + } + + # If the unit is not socket-activated, record + # that this unit needs to be started below. + # We write this to a file to ensure that the + # service gets restarted if we're interrupted. + if (!$socketActivated) { + $unitsToStart{$unit} = 1; + recordUnit($startListFile, $unit); + } + + $unitsToStop{$unit} = 1; + } + } + } } } } @@ -392,6 +362,8 @@ sub filterUnits { } my @unitsToStopFiltered = filterUnits(\%unitsToStop); +my @unitsToStartFiltered = filterUnits(\%unitsToStart); + # Show dry-run actions. if ($action eq "dry-activate") { @@ -403,44 +375,21 @@ if ($action eq "dry-activate") { print STDERR "would activate the configuration...\n"; system("$out/dry-activate", "$out"); - # Handle the activation script requesting the restart or reload of a unit. - my %unitsToAlsoStop; - my %unitsToAlsoSkip; - foreach (split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // "")) { - my $unit = $_; - my $baseUnit = $unit; - my $newUnitFile = "$out/etc/systemd/system/$baseUnit"; - - # Detect template instances. - if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) { - $baseUnit = "$1\@.$2"; - $newUnitFile = "$out/etc/systemd/system/$baseUnit"; - } - - my $baseName = $baseUnit; - $baseName =~ s/\.[a-z]*$//; + $unitsToRestart{$_} = 1 foreach + split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // ""); - handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToAlsoStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToAlsoSkip); - } - unlink($dryRestartByActivationFile); - - my @unitsToAlsoStopFiltered = filterUnits(\%unitsToAlsoStop); - if (scalar(keys %unitsToAlsoStop) > 0) { - print STDERR "would stop the following units as well: ", join(", ", @unitsToAlsoStopFiltered), "\n" - if scalar @unitsToAlsoStopFiltered; - } - - print STDERR "would NOT restart the following changed units as well: ", join(", ", sort(keys %unitsToAlsoSkip)), "\n" - if scalar(keys %unitsToAlsoSkip) > 0; + $unitsToReload{$_} = 1 foreach + split('\n', read_file($dryReloadByActivationFile, err_mode => 'quiet') // ""); print STDERR "would restart systemd\n" if $restartSystemd; - print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n" - if scalar(keys %unitsToReload) > 0; print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n" if scalar(keys %unitsToRestart) > 0; - my @unitsToStartFiltered = filterUnits(\%unitsToStart); print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n" if scalar @unitsToStartFiltered; + print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n" + if scalar(keys %unitsToReload) > 0; + unlink($dryRestartByActivationFile); + unlink($dryReloadByActivationFile); exit 0; } @@ -451,7 +400,7 @@ if (scalar (keys %unitsToStop) > 0) { print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n" if scalar @unitsToStopFiltered; # Use current version of systemctl binary before daemon is reexeced. - system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop)); + system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop)); # FIXME: ignore errors? } print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n" @@ -465,38 +414,12 @@ system("$out/activate", "$out") == 0 or $res = 2; # Handle the activation script requesting the restart or reload of a unit. # We can only restart and reload (not stop/start) because the units to be -# stopped are already stopped before the activation script is run. We do however -# make an exception for services that are socket-activated and that have to be stopped -# instead of being restarted. -my %unitsToAlsoStop; -my %unitsToAlsoSkip; -foreach (split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // "")) { - my $unit = $_; - my $baseUnit = $unit; - my $newUnitFile = "$out/etc/systemd/system/$baseUnit"; - - # Detect template instances. - if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) { - $baseUnit = "$1\@.$2"; - $newUnitFile = "$out/etc/systemd/system/$baseUnit"; - } - - my $baseName = $baseUnit; - $baseName =~ s/\.[a-z]*$//; - - handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToAlsoStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToAlsoSkip); -} -unlink($restartByActivationFile); - -my @unitsToAlsoStopFiltered = filterUnits(\%unitsToAlsoStop); -if (scalar(keys %unitsToAlsoStop) > 0) { - print STDERR "stopping the following units as well: ", join(", ", @unitsToAlsoStopFiltered), "\n" - if scalar @unitsToAlsoStopFiltered; - system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToAlsoStop)); -} +# stopped are already stopped before the activation script is run. +$unitsToRestart{$_} = 1 foreach + split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // ""); -print STDERR "NOT restarting the following changed units as well: ", join(", ", sort(keys %unitsToAlsoSkip)), "\n" - if scalar(keys %unitsToAlsoSkip) > 0; +$unitsToReload{$_} = 1 foreach + split('\n', read_file($reloadByActivationFile, err_mode => 'quiet') // ""); # Restart systemd if necessary. Note that this is done using the # current version of systemd, just in case the new one has trouble @@ -537,40 +460,14 @@ if (scalar(keys %unitsToReload) > 0) { print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n"; system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4; unlink($reloadListFile); + unlink($reloadByActivationFile); } # Restart changed services (those that have to be restarted rather # than stopped and started). if (scalar(keys %unitsToRestart) > 0) { print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"; - - # We split the units to be restarted into sockets and non-sockets. - # This is because restarting sockets may fail which is not bad by - # itself but which will prevent changes on the sockets. We usually - # restart the socket and stop the service before that. Restarting - # the socket will fail however when the service was re-activated - # in the meantime. There is no proper way to prevent that from happening. - my @unitsWithErrorHandling = grep { $_ !~ /\.socket$/ } sort(keys %unitsToRestart); - my @unitsWithoutErrorHandling = grep { $_ =~ /\.socket$/ } sort(keys %unitsToRestart); - - if (scalar(@unitsWithErrorHandling) > 0) { - system("@systemd@/bin/systemctl", "restart", "--", @unitsWithErrorHandling) == 0 or $res = 4; - } - if (scalar(@unitsWithoutErrorHandling) > 0) { - # Don't print warnings from systemctl - no warnings 'once'; - open(OLDERR, ">&", \*STDERR); - close(STDERR); - - my $ret = system("@systemd@/bin/systemctl", "restart", "--", @unitsWithoutErrorHandling); - - # Print stderr again - open(STDERR, ">&OLDERR"); - - if ($ret ne 0) { - print STDERR "warning: some sockets failed to restart. Please check your journal (journalctl -eb) and act accordingly.\n"; - } - } + system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4; unlink($restartListFile); unlink($restartByActivationFile); } @@ -581,7 +478,6 @@ if (scalar(keys %unitsToRestart) > 0) { # that are symlinks to other units. We shouldn't start both at the # same time because we'll get a "Failed to add path to set" error from # systemd. -my @unitsToStartFiltered = filterUnits(\%unitsToStart); print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n" if scalar @unitsToStartFiltered; system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4; @@ -589,7 +485,7 @@ unlink($startListFile); # Print failed and new units. -my (@failed, @new); +my (@failed, @new, @restarting); my $activeNew = getActiveUnits; while (my ($unit, $state) = each %{$activeNew}) { if ($state->{state} eq "failed") { @@ -605,9 +501,7 @@ while (my ($unit, $state) = each %{$activeNew}) { push @failed, $unit; } } - # Ignore scopes since they are not managed by this script but rather - # created and managed by third-party services via the systemd dbus API. - elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit} && $unit !~ /\.scope$/) { + elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit}) { push @new, $unit; } } diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 68da910d29cc..026fd1791d33 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -84,13 +84,6 @@ let export localeArchive="${config.i18n.glibcLocales}/lib/locale/locale-archive" substituteAll ${./switch-to-configuration.pl} $out/bin/switch-to-configuration chmod +x $out/bin/switch-to-configuration - ${optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) '' - if ! output=$($perl/bin/perl -c $out/bin/switch-to-configuration 2>&1); then - echo "switch-to-configuration syntax is not valid:" - echo "$output" - exit 1 - fi - ''} echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix index 4a9da9394519..d147155d796c 100644 --- a/nixos/modules/system/boot/kernel.nix +++ b/nixos/modules/system/boot/kernel.nix @@ -243,7 +243,7 @@ in "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" - ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ + ] ++ optionals pkgs.stdenv.hostPlatform.isx86 [ # Misc. x86 keyboard stuff. "pcips2" "atkbd" "i8042" diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 4d8537d4c327..0c93b288fc65 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -103,10 +103,10 @@ if (stat($bootPath)->dev != stat("/nix/store")->dev) { # Discover information about the location of the bootPath struct(Fs => { - device => '$', - type => '$', - mount => '$', - }); + device => '$', + type => '$', + mount => '$', +}); sub PathInMount { my ($path, $mount) = @_; my @splitMount = split /\//, $mount; @@ -155,9 +155,9 @@ sub GetFs { return $bestFs; } struct (Grub => { - path => '$', - search => '$', - }); + path => '$', + search => '$', +}); my $driveid = 1; sub GrubFs { my ($dir) = @_; @@ -254,8 +254,8 @@ if ($grubVersion == 1) { # $defaultEntry might be "saved", indicating that we want to use the last selected configuration as default. # Incidentally this is already the correct value for the grub 1 config to achieve this behaviour. $conf .= " - default $defaultEntry - timeout $timeout + default $defaultEntry + timeout $timeout "; if ($splashImage) { copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n"; @@ -305,7 +305,7 @@ else { if ($copyKernels == 0) { $conf .= " - " . $grubStore->search; + " . $grubStore->search; } # FIXME: should use grub-mkconfig. my $defaultEntryText = $defaultEntry; @@ -313,55 +313,55 @@ else { $defaultEntryText = "\"\${saved_entry}\""; } $conf .= " - " . $grubBoot->search . " - if [ -s \$prefix/grubenv ]; then - load_env - fi - - # ‘grub-reboot’ sets a one-time saved entry, which we process here and - # then delete. - if [ \"\${next_entry}\" ]; then - set default=\"\${next_entry}\" - set next_entry= - save_env next_entry - set timeout=1 - set boot_once=true - else - set default=$defaultEntryText - set timeout=$timeout - fi - - function savedefault { - if [ -z \"\${boot_once}\"]; then - saved_entry=\"\${chosen}\" - save_env saved_entry + " . $grubBoot->search . " + if [ -s \$prefix/grubenv ]; then + load_env fi - } - # Setup the graphics stack for bios and efi systems - if [ \"\${grub_platform}\" = \"efi\" ]; then - insmod efi_gop - insmod efi_uga - else - insmod vbe - fi + # ‘grub-reboot’ sets a one-time saved entry, which we process here and + # then delete. + if [ \"\${next_entry}\" ]; then + set default=\"\${next_entry}\" + set next_entry= + save_env next_entry + set timeout=1 + set boot_once=true + else + set default=$defaultEntryText + set timeout=$timeout + fi + + function savedefault { + if [ -z \"\${boot_once}\"]; then + saved_entry=\"\${chosen}\" + save_env saved_entry + fi + } + + # Setup the graphics stack for bios and efi systems + if [ \"\${grub_platform}\" = \"efi\" ]; then + insmod efi_gop + insmod efi_uga + else + insmod vbe + fi "; if ($font) { copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n"; $conf .= " - insmod font - if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then - insmod gfxterm - if [ \"\${grub_platform}\" = \"efi\" ]; then - set gfxmode=$gfxmodeEfi - set gfxpayload=$gfxpayloadEfi - else - set gfxmode=$gfxmodeBios - set gfxpayload=$gfxpayloadBios - fi - terminal_output gfxterm - fi + insmod font + if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then + insmod gfxterm + if [ \"\${grub_platform}\" = \"efi\" ]; then + set gfxmode=$gfxmodeEfi + set gfxpayload=$gfxpayloadEfi + else + set gfxmode=$gfxmodeBios + set gfxpayload=$gfxpayloadBios + fi + terminal_output gfxterm + fi "; } if ($splashImage) { @@ -378,14 +378,14 @@ else { } copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n"; $conf .= " - insmod " . substr($suffix, 1) . " - if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then - set color_normal=white/black - set color_highlight=black/white - else - set menu_color_normal=cyan/blue - set menu_color_highlight=white/blue - fi + insmod " . substr($suffix, 1) . " + if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then + set color_normal=white/black + set color_highlight=black/white + else + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi "; } @@ -395,20 +395,20 @@ else { # Copy theme rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n"; $conf .= " - # Sets theme. - set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt - export theme - # Load theme fonts, if any + # Sets theme. + set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt + export theme + # Load theme fonts, if any "; find( { wanted => sub { - if ($_ =~ /\.pf2$/i) { - $font = File::Spec->abs2rel($File::Find::name, $theme); - $conf .= " - loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font - "; - } - }, no_chdir => 1 }, $theme ); + if ($_ =~ /\.pf2$/i) { + $font = File::Spec->abs2rel($File::Find::name, $theme); + $conf .= " + loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font + "; + } + }, no_chdir => 1 }, $theme ); } } @@ -474,8 +474,8 @@ sub addEntry { # FIXME: $confName my $kernelParams = - "init=" . Cwd::abs_path("$path/init") . " " . - readFile("$path/kernel-params"); + "init=" . Cwd::abs_path("$path/init") . " " . + readFile("$path/kernel-params"); my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; if ($grubVersion == 1) { @@ -524,9 +524,9 @@ foreach my $link (@links) { my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = - -e "$link/nixos-version" - ? readFile("$link/nixos-version") - : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); if ($cfgName) { $entryName = $cfgName; @@ -551,8 +551,8 @@ sub addProfile { sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; } my @links = sort - { nrFromGen($b) <=> nrFromGen($a) } - (glob "$profile-*-link"); + { nrFromGen($b) <=> nrFromGen($a) } + (glob "$profile-*-link"); my $curEntry = 0; foreach my $link (@links) { @@ -563,9 +563,9 @@ sub addProfile { } my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = - -e "$link/nixos-version" - ? readFile("$link/nixos-version") - : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); } @@ -653,13 +653,13 @@ foreach my $fn (glob "$bootPath/kernels/*") { # struct(GrubState => { - name => '$', - version => '$', - efi => '$', - devices => '$', - efiMountPoint => '$', - extraGrubInstallArgs => '@', - }); + name => '$', + version => '$', + efi => '$', + devices => '$', + efiMountPoint => '$', + extraGrubInstallArgs => '@', +}); # If you add something to the state file, only add it to the end # because it is read line-by-line. sub readGrubState { diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index c38bef9d6d4b..e9697b5f0e64 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -244,19 +244,27 @@ def main() -> None: subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"]) else: # Update bootloader to latest if needed - systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[1] + systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2] sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True) # See status_binaries() in systemd bootctl.c for code which generates this - m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot (\d+)\)$", + m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$", sdboot_status, re.IGNORECASE | re.MULTILINE) + + needs_install = False + if m is None: - print("could not find any previously installed systemd-boot") + print("could not find any previously installed systemd-boot, installing.") + # Let systemd-boot attempt an installation if a previous one wasn't found + needs_install = True else: - sdboot_version = m.group(2) - if systemd_version > sdboot_version: + sdboot_version = f'({m.group(2)})' + if systemd_version != sdboot_version: print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version)) - subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) + needs_install = True + + if needs_install: + subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"]) mkdir_p("@efiSysMountPoint@/efi/nixos") mkdir_p("@efiSysMountPoint@/loader/entries") diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 8fcf62d7fbff..6e0ee437d915 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -67,6 +67,7 @@ let "systemd-user-sessions.service" "dbus-org.freedesktop.import1.service" "dbus-org.freedesktop.machine1.service" + "dbus-org.freedesktop.login1.service" "user@.service" "user-runtime-dir@.service" diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix index b19b688a1fb8..b931b27ad817 100644 --- a/nixos/modules/tasks/auto-upgrade.nix +++ b/nixos/modules/tasks/auto-upgrade.nix @@ -139,6 +139,7 @@ in { gzip gitMinimal config.nix.package.out + config.programs.ssh.package ]; script = let diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 4e20ec118464..49901cda848d 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -417,7 +417,11 @@ in network node hostname (uname --nodename) the option boot.kernel.sysctl."kernel.hostname" can be used as a workaround (but the 64 character limit still applies). + + WARNING: Do not use underscores (_) or you may run into unexpected issues. ''; + # warning until the issues in https://github.com/NixOS/nixpkgs/pull/138978 + # are resolved }; networking.fqdn = mkOption { @@ -1233,6 +1237,8 @@ in "net.ipv4.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces); "net.ipv6.conf.all.disable_ipv6" = mkDefault (!cfg.enableIPv6); "net.ipv6.conf.default.disable_ipv6" = mkDefault (!cfg.enableIPv6); + # networkmanager falls back to "/proc/sys/net/ipv6/conf/default/use_tempaddr" + "net.ipv6.conf.default.use_tempaddr" = tempaddrValues.${cfg.tempAddresses}.sysctl; } // listToAttrs (flip concatMap (filter (i: i.proxyARP) interfaces) (i: [(nameValuePair "net.ipv4.conf.${replaceChars ["."] ["/"] i.name}.proxy_arp" true)])) // listToAttrs (forEach interfaces diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix index 41f3fa0e6642..bd8c7f8c1eea 100644 --- a/nixos/modules/virtualisation/azure-agent.nix +++ b/nixos/modules/virtualisation/azure-agent.nix @@ -76,7 +76,7 @@ in config = mkIf cfg.enable { assertions = [ { - assertion = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64; + assertion = pkgs.stdenv.hostPlatform.isx86; message = "Azure not currently supported on ${pkgs.stdenv.hostPlatform.system}"; } { assertion = config.networking.networkmanager.enable == false; diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 6ce4461babc7..91356ac1d984 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -97,7 +97,7 @@ let imap1 (idx: drive: drive // { device = driveDeviceName idx; }); efiPrefix = - if (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then "${pkgs.OVMF.fd}/FV/OVMF" + if pkgs.stdenv.hostPlatform.isx86 then "${pkgs.OVMF.fd}/FV/OVMF" else if pkgs.stdenv.isAarch64 then "${pkgs.OVMF.fd}/FV/AAVMF" else throw "No EFI firmware available for platform"; efiFirmware = "${efiPrefix}_CODE.fd"; @@ -296,7 +296,7 @@ in virtualisation.memorySize = mkOption { type = types.ints.positive; - default = 384; + default = 1024; description = '' The memory size in megabytes of the virtual machine. @@ -833,7 +833,7 @@ in # FIXME: Consolidate this one day. virtualisation.qemu.options = mkMerge [ - (mkIf (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ + (mkIf pkgs.stdenv.hostPlatform.isx86 [ "-usb" "-device usb-tablet,bus=usb-bus.0" ]) (mkIf (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [ @@ -845,7 +845,7 @@ in ''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"'' ]) (mkIf cfg.useEFIBoot [ - "-drive if=pflash,format=raw,unit=0,readonly,file=${efiFirmware}" + "-drive if=pflash,format=raw,unit=0,readonly=on,file=${efiFirmware}" "-drive if=pflash,format=raw,unit=1,file=$NIX_EFI_VARS" ]) (mkIf (cfg.bios != null) [ diff --git a/nixos/modules/virtualisation/virtualbox-guest.nix b/nixos/modules/virtualisation/virtualbox-guest.nix index 486951983d30..f702fb4e525c 100644 --- a/nixos/modules/virtualisation/virtualbox-guest.nix +++ b/nixos/modules/virtualisation/virtualbox-guest.nix @@ -33,7 +33,7 @@ in config = mkIf cfg.enable (mkMerge [{ assertions = [{ - assertion = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64; + assertion = pkgs.stdenv.hostPlatform.isx86; message = "Virtualbox not currently supported on ${pkgs.stdenv.hostPlatform.system}"; }]; diff --git a/nixos/modules/virtualisation/vmware-guest.nix b/nixos/modules/virtualisation/vmware-guest.nix index 480a9703cef3..481dedf84054 100644 --- a/nixos/modules/virtualisation/vmware-guest.nix +++ b/nixos/modules/virtualisation/vmware-guest.nix @@ -23,7 +23,7 @@ in config = mkIf cfg.enable { assertions = [ { - assertion = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64; + assertion = pkgs.stdenv.hostPlatform.isx86; message = "VMWare guest is not currently supported on ${pkgs.stdenv.hostPlatform.system}"; } ]; @@ -34,6 +34,8 @@ in systemd.services.vmware = { description = "VMWare Guest Service"; wantedBy = [ "multi-user.target" ]; + after = [ "display-manager.service" ]; + unitConfig.ConditionVirtualization = "vmware"; serviceConfig.ExecStart = "${open-vm-tools}/bin/vmtoolsd"; }; @@ -42,8 +44,7 @@ in { description = "VMware vmblock fuse mount"; documentation = [ "https://github.com/vmware/open-vm-tools/blob/master/open-vm-tools/vmblock-fuse/design.txt" ]; - before = [ "vmware.service" ]; - wants = [ "vmware.service" ]; + unitConfig.ConditionVirtualization = "vmware"; what = "${open-vm-tools}/bin/vmware-vmblock-fuse"; where = "/run/vmblock-fuse"; type = "fuse"; |