diff options
Diffstat (limited to 'nixpkgs/nixos/modules')
75 files changed, 1614 insertions, 797 deletions
diff --git a/nixpkgs/nixos/modules/config/krb5/default.nix b/nixpkgs/nixos/modules/config/krb5/default.nix deleted file mode 100644 index df7a3f48236f..000000000000 --- a/nixpkgs/nixos/modules/config/krb5/default.nix +++ /dev/null @@ -1,369 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - - cfg = config.krb5; - - # This is to provide support for old configuration options (as much as is - # reasonable). This can be removed after 18.03 was released. - defaultConfig = { - libdefaults = optionalAttrs (cfg.defaultRealm != null) - { default_realm = cfg.defaultRealm; }; - - realms = optionalAttrs (lib.all (value: value != null) [ - cfg.defaultRealm cfg.kdc cfg.kerberosAdminServer - ]) { - ${cfg.defaultRealm} = { - kdc = cfg.kdc; - admin_server = cfg.kerberosAdminServer; - }; - }; - - domain_realm = optionalAttrs (lib.all (value: value != null) [ - cfg.domainRealm cfg.defaultRealm - ]) { - ".${cfg.domainRealm}" = cfg.defaultRealm; - ${cfg.domainRealm} = cfg.defaultRealm; - }; - }; - - mergedConfig = (recursiveUpdate defaultConfig { - inherit (config.krb5) - kerberos libdefaults realms domain_realm capaths appdefaults plugins - extraConfig config; - }); - - filterEmbeddedMetadata = value: if isAttrs value then - (filterAttrs - (attrName: attrValue: attrName != "_module" && attrValue != null) - value) - else value; - - indent = " "; - - mkRelation = name: value: - if (isList value) then - concatMapStringsSep "\n" (mkRelation name) value - else "${name} = ${mkVal value}"; - - mkVal = value: - if (value == true) then "true" - else if (value == false) then "false" - else if (isInt value) then (toString value) - else if (isAttrs value) then - let configLines = concatLists - (map (splitString "\n") - (mapAttrsToList mkRelation value)); - in - (concatStringsSep "\n${indent}" - ([ "{" ] ++ configLines)) - + "\n}" - else value; - - mkMappedAttrsOrString = value: concatMapStringsSep "\n" - (line: if builtins.stringLength line > 0 - then "${indent}${line}" - else line) - (splitString "\n" - (if isAttrs value then - concatStringsSep "\n" - (mapAttrsToList mkRelation value) - else value)); - -in { - - ###### interface - - options = { - krb5 = { - enable = mkEnableOption (lib.mdDoc "building krb5.conf, configuration file for Kerberos V"); - - kerberos = mkOption { - type = types.package; - default = pkgs.krb5; - defaultText = literalExpression "pkgs.krb5"; - example = literalExpression "pkgs.heimdal"; - description = lib.mdDoc '' - The Kerberos implementation that will be present in - `environment.systemPackages` after enabling this - service. - ''; - }; - - libdefaults = mkOption { - type = with types; either attrs lines; - default = {}; - apply = attrs: filterEmbeddedMetadata attrs; - example = literalExpression '' - { - default_realm = "ATHENA.MIT.EDU"; - }; - ''; - description = lib.mdDoc '' - Settings used by the Kerberos V5 library. - ''; - }; - - realms = mkOption { - type = with types; either attrs lines; - default = {}; - example = literalExpression '' - { - "ATHENA.MIT.EDU" = { - admin_server = "athena.mit.edu"; - kdc = [ - "athena01.mit.edu" - "athena02.mit.edu" - ]; - }; - }; - ''; - apply = attrs: filterEmbeddedMetadata attrs; - description = lib.mdDoc "Realm-specific contact information and settings."; - }; - - domain_realm = mkOption { - type = with types; either attrs lines; - default = {}; - example = literalExpression '' - { - "example.com" = "EXAMPLE.COM"; - ".example.com" = "EXAMPLE.COM"; - }; - ''; - apply = attrs: filterEmbeddedMetadata attrs; - description = lib.mdDoc '' - Map of server hostnames to Kerberos realms. - ''; - }; - - capaths = mkOption { - type = with types; either attrs lines; - default = {}; - example = literalExpression '' - { - "ATHENA.MIT.EDU" = { - "EXAMPLE.COM" = "."; - }; - "EXAMPLE.COM" = { - "ATHENA.MIT.EDU" = "."; - }; - }; - ''; - apply = attrs: filterEmbeddedMetadata attrs; - description = lib.mdDoc '' - Authentication paths for non-hierarchical cross-realm authentication. - ''; - }; - - appdefaults = mkOption { - type = with types; either attrs lines; - default = {}; - example = literalExpression '' - { - pam = { - debug = false; - ticket_lifetime = 36000; - renew_lifetime = 36000; - max_timeout = 30; - timeout_shift = 2; - initial_timeout = 1; - }; - }; - ''; - apply = attrs: filterEmbeddedMetadata attrs; - description = lib.mdDoc '' - Settings used by some Kerberos V5 applications. - ''; - }; - - plugins = mkOption { - type = with types; either attrs lines; - default = {}; - example = literalExpression '' - { - ccselect = { - disable = "k5identity"; - }; - }; - ''; - apply = attrs: filterEmbeddedMetadata attrs; - description = lib.mdDoc '' - Controls plugin module registration. - ''; - }; - - extraConfig = mkOption { - type = with types; nullOr lines; - default = null; - example = '' - [logging] - kdc = SYSLOG:NOTICE - admin_server = SYSLOG:NOTICE - default = SYSLOG:NOTICE - ''; - description = lib.mdDoc '' - These lines go to the end of `krb5.conf` verbatim. - `krb5.conf` may include any of the relations that are - valid for `kdc.conf` (see `man kdc.conf`), - but it is not a recommended practice. - ''; - }; - - config = mkOption { - type = with types; nullOr lines; - default = null; - example = '' - [libdefaults] - default_realm = EXAMPLE.COM - - [realms] - EXAMPLE.COM = { - admin_server = kerberos.example.com - kdc = kerberos.example.com - default_principal_flags = +preauth - } - - [domain_realm] - example.com = EXAMPLE.COM - .example.com = EXAMPLE.COM - - [logging] - kdc = SYSLOG:NOTICE - admin_server = SYSLOG:NOTICE - default = SYSLOG:NOTICE - ''; - description = lib.mdDoc '' - Verbatim `krb5.conf` configuration. Note that this - is mutually exclusive with configuration via - `libdefaults`, `realms`, - `domain_realm`, `capaths`, - `appdefaults`, `plugins` and - `extraConfig` configuration options. Consult - `man krb5.conf` for documentation. - ''; - }; - - defaultRealm = mkOption { - type = with types; nullOr str; - default = null; - example = "ATHENA.MIT.EDU"; - description = lib.mdDoc '' - DEPRECATED, please use - `krb5.libdefaults.default_realm`. - ''; - }; - - domainRealm = mkOption { - type = with types; nullOr str; - default = null; - example = "athena.mit.edu"; - description = lib.mdDoc '' - DEPRECATED, please create a map of server hostnames to Kerberos realms - in `krb5.domain_realm`. - ''; - }; - - kdc = mkOption { - type = with types; nullOr str; - default = null; - example = "kerberos.mit.edu"; - description = lib.mdDoc '' - DEPRECATED, please pass a `kdc` attribute to a realm - in `krb5.realms`. - ''; - }; - - kerberosAdminServer = mkOption { - type = with types; nullOr str; - default = null; - example = "kerberos.mit.edu"; - description = lib.mdDoc '' - DEPRECATED, please pass an `admin_server` attribute - to a realm in `krb5.realms`. - ''; - }; - }; - }; - - ###### implementation - - config = mkIf cfg.enable { - - environment.systemPackages = [ cfg.kerberos ]; - - environment.etc."krb5.conf".text = if isString cfg.config - then cfg.config - else ('' - [libdefaults] - ${mkMappedAttrsOrString mergedConfig.libdefaults} - - [realms] - ${mkMappedAttrsOrString mergedConfig.realms} - - [domain_realm] - ${mkMappedAttrsOrString mergedConfig.domain_realm} - - [capaths] - ${mkMappedAttrsOrString mergedConfig.capaths} - - [appdefaults] - ${mkMappedAttrsOrString mergedConfig.appdefaults} - - [plugins] - ${mkMappedAttrsOrString mergedConfig.plugins} - '' + optionalString (mergedConfig.extraConfig != null) - ("\n" + mergedConfig.extraConfig)); - - warnings = flatten [ - (optional (cfg.defaultRealm != null) '' - The option krb5.defaultRealm is deprecated, please use - krb5.libdefaults.default_realm. - '') - (optional (cfg.domainRealm != null) '' - The option krb5.domainRealm is deprecated, please use krb5.domain_realm. - '') - (optional (cfg.kdc != null) '' - The option krb5.kdc is deprecated, please pass a kdc attribute to a - realm in krb5.realms. - '') - (optional (cfg.kerberosAdminServer != null) '' - The option krb5.kerberosAdminServer is deprecated, please pass an - admin_server attribute to a realm in krb5.realms. - '') - ]; - - assertions = [ - { assertion = !((builtins.any (value: value != null) [ - cfg.defaultRealm cfg.domainRealm cfg.kdc cfg.kerberosAdminServer - ]) && ((builtins.any (value: value != {}) [ - cfg.libdefaults cfg.realms cfg.domain_realm cfg.capaths - cfg.appdefaults cfg.plugins - ]) || (builtins.any (value: value != null) [ - cfg.config cfg.extraConfig - ]))); - message = '' - Configuration of krb5.conf by deprecated options is mutually exclusive - with configuration by section. Please migrate your config using the - attributes suggested in the warnings. - ''; - } - { assertion = !(cfg.config != null - && ((builtins.any (value: value != {}) [ - cfg.libdefaults cfg.realms cfg.domain_realm cfg.capaths - cfg.appdefaults cfg.plugins - ]) || (builtins.any (value: value != null) [ - cfg.extraConfig cfg.defaultRealm cfg.domainRealm cfg.kdc - cfg.kerberosAdminServer - ]))); - message = '' - Configuration of krb5.conf using krb.config is mutually exclusive with - configuration by section. If you want to mix the two, you can pass - lines to any configuration section or lines to krb5.extraConfig. - ''; - } - ]; - }; -} diff --git a/nixpkgs/nixos/modules/config/no-x-libs.nix b/nixpkgs/nixos/modules/config/no-x-libs.nix index 0f5888f5ea3b..4727e5b85ef2 100644 --- a/nixpkgs/nixos/modules/config/no-x-libs.nix +++ b/nixpkgs/nixos/modules/config/no-x-libs.nix @@ -35,6 +35,7 @@ with lib; # dep of graphviz, libXpm is optional for Xpm support gd = super.gd.override { withXorg = false; }; ghostscript = super.ghostscript.override { cupsSupport = false; x11Support = false; }; + gjs = super.gjs.overrideAttrs { doCheck = false; installTests = false; }; # avoid test dependency on gtk3 gobject-introspection = super.gobject-introspection.override { x11Support = false; }; gpsd = super.gpsd.override { guiSupport = false; }; graphviz = super.graphviz-nox; diff --git a/nixpkgs/nixos/modules/hardware/usb-storage.nix b/nixpkgs/nixos/modules/hardware/usb-storage.nix index 9c1b7a125fd1..3cb2c60d7ccd 100644 --- a/nixpkgs/nixos/modules/hardware/usb-storage.nix +++ b/nixpkgs/nixos/modules/hardware/usb-storage.nix @@ -14,7 +14,7 @@ with lib; config = mkIf config.hardware.usbStorage.manageStartStop { services.udev.extraRules = '' - ACTION=="add|change", SUBSYSTEM=="scsi_disk", DRIVERS=="usb-storage", ATTR{manage_start_stop}="1" + ACTION=="add|change", SUBSYSTEM=="scsi_disk", DRIVERS=="usb-storage", ATTR{manage_system_start_stop}="1" ''; }; } diff --git a/nixpkgs/nixos/modules/hardware/video/webcam/ipu6.nix b/nixpkgs/nixos/modules/hardware/video/webcam/ipu6.nix index fce78cda34c7..c2dbdc217bd6 100644 --- a/nixpkgs/nixos/modules/hardware/video/webcam/ipu6.nix +++ b/nixpkgs/nixos/modules/hardware/video/webcam/ipu6.nix @@ -13,11 +13,12 @@ in enable = mkEnableOption (lib.mdDoc "support for Intel IPU6/MIPI cameras"); platform = mkOption { - type = types.enum [ "ipu6" "ipu6ep" ]; + type = types.enum [ "ipu6" "ipu6ep" "ipu6epmtl" ]; description = lib.mdDoc '' Choose the version for your hardware platform. - Use `ipu6` for Tiger Lake and `ipu6ep` for Alder Lake respectively. + Use `ipu6` for Tiger Lake, `ipu6ep` for Alder Lake or Raptor Lake, + and `ipu6epmtl` for Meteor Lake. ''; }; @@ -29,9 +30,7 @@ in ipu6-drivers ]; - hardware.firmware = with pkgs; [ ] - ++ optional (cfg.platform == "ipu6") ipu6-camera-bin - ++ optional (cfg.platform == "ipu6ep") ipu6ep-camera-bin; + hardware.firmware = [ pkgs.ipu6-camera-bins ]; services.udev.extraRules = '' SUBSYSTEM=="intel-ipu6-psys", MODE="0660", GROUP="video" @@ -44,14 +43,13 @@ in extraPackages = with pkgs.gst_all_1; [ ] ++ optional (cfg.platform == "ipu6") icamerasrc-ipu6 - ++ optional (cfg.platform == "ipu6ep") icamerasrc-ipu6ep; + ++ optional (cfg.platform == "ipu6ep") icamerasrc-ipu6ep + ++ optional (cfg.platform == "ipu6epmtl") icamerasrc-ipu6epmtl; input = { pipeline = "icamerasrc"; - format = mkIf (cfg.platform == "ipu6ep") (mkDefault "NV12"); + format = mkIf (cfg.platform != "ipu6") (mkDefault "NV12"); }; }; - }; - } diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix index 29afdd471091..1932f90d4c36 100644 --- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix @@ -18,7 +18,7 @@ # not including it may cause annoying cache misses in the case of the NixOS manual. documentation.doc.enable = lib.mkOverride 500 true; - fonts.fontconfig.enable = lib.mkForce false; + fonts.fontconfig.enable = lib.mkOverride 500 false; - isoImage.edition = lib.mkForce "minimal"; + isoImage.edition = lib.mkOverride 500 "minimal"; } diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix index 0b5135c088ea..6adb94e09aff 100644 --- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix @@ -512,9 +512,10 @@ in + lib.optionalString isAarch "-Xbcj arm" + lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc" + lib.optionalString (isSparc) "-Xbcj sparc"; - type = lib.types.str; + type = lib.types.nullOr lib.types.str; description = lib.mdDoc '' Compression settings to use for the squashfs nix store. + `null` disables compression. ''; example = "zstd -Xcompression-level 6"; }; diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix index 7b7b37c123b4..5f639e4e42e9 100644 --- a/nixpkgs/nixos/modules/module-list.nix +++ b/nixpkgs/nixos/modules/module-list.nix @@ -10,7 +10,6 @@ ./config/gtk/gtk-icon-cache.nix ./config/i18n.nix ./config/iproute2.nix - ./config/krb5/default.nix ./config/ldap.nix ./config/ldso.nix ./config/locale.nix @@ -273,6 +272,7 @@ ./programs/virt-manager.nix ./programs/wavemon.nix ./programs/wayland/cardboard.nix + ./programs/wayland/labwc.nix ./programs/wayland/river.nix ./programs/wayland/sway.nix ./programs/wayland/waybar.nix @@ -308,6 +308,7 @@ ./security/duosec.nix ./security/google_oslogin.nix ./security/ipa.nix + ./security/krb5 ./security/lock-kernel-modules.nix ./security/misc.nix ./security/oath.nix @@ -834,6 +835,7 @@ ./services/monitoring/riemann.nix ./services/monitoring/scollector.nix ./services/monitoring/smartd.nix + ./services/monitoring/snmpd.nix ./services/monitoring/statsd.nix ./services/monitoring/sysstat.nix ./services/monitoring/teamviewer.nix @@ -1043,6 +1045,7 @@ ./services/networking/ntopng.nix ./services/networking/ntp/chrony.nix ./services/networking/ntp/ntpd.nix + ./services/networking/ntp/ntpd-rs.nix ./services/networking/ntp/openntpd.nix ./services/networking/nullidentdmod.nix ./services/networking/nylon.nix @@ -1475,6 +1478,9 @@ ./system/boot/systemd/initrd-secrets.nix ./system/boot/systemd/initrd.nix ./system/boot/systemd/journald.nix + ./system/boot/systemd/journald-gateway.nix + ./system/boot/systemd/journald-remote.nix + ./system/boot/systemd/journald-upload.nix ./system/boot/systemd/logind.nix ./system/boot/systemd/nspawn.nix ./system/boot/systemd/oomd.nix diff --git a/nixpkgs/nixos/modules/programs/partition-manager.nix b/nixpkgs/nixos/modules/programs/partition-manager.nix index c18598b7c25d..cf0491ff028f 100644 --- a/nixpkgs/nixos/modules/programs/partition-manager.nix +++ b/nixpkgs/nixos/modules/programs/partition-manager.nix @@ -14,6 +14,6 @@ with lib; config = mkIf config.programs.partition-manager.enable { services.dbus.packages = [ pkgs.libsForQt5.kpmcore ]; # `kpmcore` need to be installed to pull in polkit actions. - environment.systemPackages = [ pkgs.libsForQt5.kpmcore pkgs.partition-manager ]; + environment.systemPackages = [ pkgs.libsForQt5.kpmcore pkgs.libsForQt5.partitionmanager ]; }; } diff --git a/nixpkgs/nixos/modules/programs/singularity.nix b/nixpkgs/nixos/modules/programs/singularity.nix index 9fd37e1793a7..7f285ab05537 100644 --- a/nixpkgs/nixos/modules/programs/singularity.nix +++ b/nixpkgs/nixos/modules/programs/singularity.nix @@ -61,7 +61,12 @@ in }; enableSuid = mkOption { type = types.bool; - default = true; + # SingularityCE requires SETUID for most things. Apptainer prefers user + # namespaces, e.g. `apptainer exec --nv` would fail if built + # `--with-suid`: + # > `FATAL: nvidia-container-cli not allowed in setuid mode` + default = cfg.package.projectName != "apptainer"; + defaultText = literalExpression ''config.services.singularity.package.projectName != "apptainer"''; example = false; description = mdDoc '' Whether to enable the SUID support of Singularity/Apptainer. diff --git a/nixpkgs/nixos/modules/programs/starship.nix b/nixpkgs/nixos/modules/programs/starship.nix index bec3900496fd..34f6f0882c61 100644 --- a/nixpkgs/nixos/modules/programs/starship.nix +++ b/nixpkgs/nixos/modules/programs/starship.nix @@ -1,13 +1,21 @@ { config, lib, pkgs, ... }: -with lib; - let cfg = config.programs.starship; settingsFormat = pkgs.formats.toml { }; - settingsFile = settingsFormat.generate "starship.toml" cfg.settings; + userSettingsFile = settingsFormat.generate "starship.toml" cfg.settings; + + settingsFile = if cfg.presets == [] then userSettingsFile else pkgs.runCommand "starship.toml" + { + nativeBuildInputs = [ pkgs.yq ]; + } '' + tomlq -s -t 'reduce .[] as $item ({}; . * $item)' \ + ${lib.concatStringsSep " " (map (f: "${pkgs.starship}/share/starship/presets/${f}.toml") cfg.presets)} \ + ${userSettingsFile} \ + > $out + ''; initOption = if cfg.interactiveOnly then @@ -18,19 +26,28 @@ let in { options.programs.starship = { - enable = mkEnableOption (lib.mdDoc "the Starship shell prompt"); + enable = lib.mkEnableOption (lib.mdDoc "the Starship shell prompt"); - interactiveOnly = mkOption { + interactiveOnly = lib.mkOption { default = true; example = false; - type = types.bool; + type = lib.types.bool; description = lib.mdDoc '' Whether to enable starship only when the shell is interactive. Some plugins require this to be set to false to function correctly. ''; }; - settings = mkOption { + presets = lib.mkOption { + default = [ ]; + example = [ "nerd-font-symbols" ]; + type = with lib.types; listOf str; + description = lib.mdDoc '' + Presets files to be merged with settings in order. + ''; + }; + + settings = lib.mkOption { inherit (settingsFormat) type; default = { }; description = lib.mdDoc '' @@ -41,7 +58,7 @@ in }; }; - config = mkIf cfg.enable { + config = lib.mkIf cfg.enable { programs.bash.${initOption} = '' if [[ $TERM != "dumb" ]]; then # don't set STARSHIP_CONFIG automatically if there's a user-specified diff --git a/nixpkgs/nixos/modules/programs/wayland/labwc.nix b/nixpkgs/nixos/modules/programs/wayland/labwc.nix new file mode 100644 index 000000000000..d0806c3aa5d0 --- /dev/null +++ b/nixpkgs/nixos/modules/programs/wayland/labwc.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.labwc; +in +{ + meta.maintainers = with lib.maintainers; [ AndersonTorres ]; + + options.programs.labwc = { + enable = lib.mkEnableOption (lib.mdDoc "labwc"); + package = lib.mkPackageOption pkgs "labwc" { }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + environment.systemPackages = [ cfg.package ]; + + xdg.portal.config.wlroots.default = lib.mkDefault [ "wlr" "gtk" ]; + + # To make a labwc session available for certain DMs like SDDM + services.xserver.displayManager.sessionPackages = [ cfg.package ]; + } + (import ./wayland-session.nix { inherit lib pkgs; }) + ]); +} diff --git a/nixpkgs/nixos/modules/security/acme/default.md b/nixpkgs/nixos/modules/security/acme/default.md index 51ee0428d84e..38fbfbf0caec 100644 --- a/nixpkgs/nixos/modules/security/acme/default.md +++ b/nixpkgs/nixos/modules/security/acme/default.md @@ -72,7 +72,7 @@ services.nginx = { }; }; }; -} +}; ``` ## Using ACME certificates in Apache/httpd {#module-security-acme-httpd} @@ -111,7 +111,7 @@ services.nginx = { }; }; }; -} +}; # Alternative config for Apache users.users.wwwrun.extraGroups = [ "acme" ]; services.httpd = { @@ -131,7 +131,7 @@ services.httpd = { ''; }; }; -} +}; ``` Now you need to configure ACME to generate a certificate. @@ -181,7 +181,7 @@ services.bind = { extraConfig = "allow-update { key rfc2136key.example.com.; };"; } ]; -} +}; # Now we can configure ACME security.acme.acceptTerms = true; @@ -271,7 +271,7 @@ services.nginx = { acmeRoot = null; }; }; -} +}; ``` And that's it! Next time your configuration is rebuilt, or when diff --git a/nixpkgs/nixos/modules/security/ipa.nix b/nixpkgs/nixos/modules/security/ipa.nix index 49226ec38199..3bf8b11f8626 100644 --- a/nixpkgs/nixos/modules/security/ipa.nix +++ b/nixpkgs/nixos/modules/security/ipa.nix @@ -117,8 +117,8 @@ in { config = mkIf cfg.enable { assertions = [ { - assertion = !config.krb5.enable; - message = "krb5 must be disabled through `krb5.enable` for FreeIPA integration to work."; + assertion = !config.security.krb5.enable; + message = "krb5 must be disabled through `security.krb5.enable` for FreeIPA integration to work."; } { assertion = !config.users.ldap.enable; diff --git a/nixpkgs/nixos/modules/security/krb5/default.nix b/nixpkgs/nixos/modules/security/krb5/default.nix new file mode 100644 index 000000000000..5921982f954c --- /dev/null +++ b/nixpkgs/nixos/modules/security/krb5/default.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) mdDoc mkIf mkOption mkPackageOption mkRemovedOptionModule; + inherit (lib.types) bool; + + mkRemovedOptionModule' = name: reason: mkRemovedOptionModule ["krb5" name] reason; + mkRemovedOptionModuleCfg = name: mkRemovedOptionModule' name '' + The option `krb5.${name}' has been removed. Use + `security.krb5.settings.${name}' for structured configuration. + ''; + + cfg = config.security.krb5; + format = import ./krb5-conf-format.nix { inherit pkgs lib; } { }; +in { + imports = [ + (mkRemovedOptionModuleCfg "libdefaults") + (mkRemovedOptionModuleCfg "realms") + (mkRemovedOptionModuleCfg "domain_realm") + (mkRemovedOptionModuleCfg "capaths") + (mkRemovedOptionModuleCfg "appdefaults") + (mkRemovedOptionModuleCfg "plugins") + (mkRemovedOptionModuleCfg "config") + (mkRemovedOptionModuleCfg "extraConfig") + (mkRemovedOptionModule' "kerberos" '' + The option `krb5.kerberos' has been moved to `security.krb5.package'. + '') + ]; + + options = { + security.krb5 = { + enable = mkOption { + default = false; + description = mdDoc "Enable and configure Kerberos utilities"; + type = bool; + }; + + package = mkPackageOption pkgs "krb5" { + example = "heimdal"; + }; + + settings = mkOption { + default = { }; + type = format.type; + description = mdDoc '' + Structured contents of the {file}`krb5.conf` file. See + {manpage}`krb5.conf(5)` for details about configuration. + ''; + example = { + include = [ "/run/secrets/secret-krb5.conf" ]; + includedir = [ "/run/secrets/secret-krb5.conf.d" ]; + + libdefaults = { + default_realm = "ATHENA.MIT.EDU"; + }; + + realms = { + "ATHENA.MIT.EDU" = { + admin_server = "athena.mit.edu"; + kdc = [ + "athena01.mit.edu" + "athena02.mit.edu" + ]; + }; + }; + + domain_realm = { + "mit.edu" = "ATHENA.MIT.EDU"; + }; + + logging = { + kdc = "SYSLOG:NOTICE"; + admin_server = "SYSLOG:NOTICE"; + default = "SYSLOG:NOTICE"; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + environment = { + systemPackages = [ cfg.package ]; + etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings; + }; + }; + + meta.maintainers = builtins.attrValues { + inherit (lib.maintainers) dblsaiko h7x4; + }; +} diff --git a/nixpkgs/nixos/modules/security/krb5/krb5-conf-format.nix b/nixpkgs/nixos/modules/security/krb5/krb5-conf-format.nix new file mode 100644 index 000000000000..d01e47a40be0 --- /dev/null +++ b/nixpkgs/nixos/modules/security/krb5/krb5-conf-format.nix @@ -0,0 +1,88 @@ +{ pkgs, lib, ... }: + +# Based on +# - https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html +# - https://manpages.debian.org/unstable/heimdal-docs/krb5.conf.5heimdal.en.html + +let + inherit (lib) boolToString concatMapStringsSep concatStringsSep filter + isAttrs isBool isList mapAttrsToList mdDoc mkOption singleton splitString; + inherit (lib.types) attrsOf bool coercedTo either int listOf oneOf path + str submodule; +in +{ }: { + type = let + section = attrsOf relation; + relation = either (attrsOf value) value; + value = either (listOf atom) atom; + atom = oneOf [int str bool]; + in submodule { + freeformType = attrsOf section; + options = { + include = mkOption { + default = [ ]; + description = mdDoc '' + Files to include in the Kerberos configuration. + ''; + type = coercedTo path singleton (listOf path); + }; + includedir = mkOption { + default = [ ]; + description = mdDoc '' + Directories containing files to include in the Kerberos configuration. + ''; + type = coercedTo path singleton (listOf path); + }; + module = mkOption { + default = [ ]; + description = mdDoc '' + Modules to obtain Kerberos configuration from. + ''; + type = coercedTo path singleton (listOf path); + }; + }; + }; + + generate = let + indent = str: concatMapStringsSep "\n" (line: " " + line) (splitString "\n" str); + + formatToplevel = args @ { + include ? [ ], + includedir ? [ ], + module ? [ ], + ... + }: let + sections = removeAttrs args [ "include" "includedir" "module" ]; + in concatStringsSep "\n" (filter (x: x != "") [ + (concatStringsSep "\n" (mapAttrsToList formatSection sections)) + (concatMapStringsSep "\n" (m: "module ${m}") module) + (concatMapStringsSep "\n" (i: "include ${i}") include) + (concatMapStringsSep "\n" (i: "includedir ${i}") includedir) + ]); + + formatSection = name: section: '' + [${name}] + ${indent (concatStringsSep "\n" (mapAttrsToList formatRelation section))} + ''; + + formatRelation = name: relation: + if isAttrs relation + then '' + ${name} = { + ${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))} + }'' + else formatValue name relation; + + formatValue = name: value: + if isList value + then concatMapStringsSep "\n" (formatAtom name) value + else formatAtom name value; + + formatAtom = name: atom: let + v = if isBool atom then boolToString atom else toString atom; + in "${name} = ${v}"; + in + name: value: pkgs.writeText name '' + ${formatToplevel value} + ''; +} diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix index 2f777f874f23..111be7057afc 100644 --- a/nixpkgs/nixos/modules/security/pam.nix +++ b/nixpkgs/nixos/modules/security/pam.nix @@ -654,8 +654,8 @@ let { name = "mysql"; enable = cfg.mysqlAuth; control = "sufficient"; modulePath = "${pkgs.pam_mysql}/lib/security/pam_mysql.so"; settings = { config_file = "/etc/security/pam_mysql.conf"; }; } - { name = "ssh_agent_auth"; enable = config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth; control = "sufficient"; modulePath = "${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so"; settings = { - file = lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles; + { name = "ssh_agent_auth"; enable = config.security.pam.sshAgentAuth.enable && cfg.sshAgentAuth; control = "sufficient"; modulePath = "${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so"; settings = { + file = lib.concatStringsSep ":" config.security.pam.sshAgentAuth.authorizedKeysFiles; }; } (let p11 = config.security.pam.p11; in { name = "p11"; enable = cfg.p11Auth; control = p11.control; modulePath = "${pkgs.pam_p11}/lib/security/pam_p11.so"; args = [ "${pkgs.opensc}/lib/opensc-pkcs11.so" @@ -943,7 +943,7 @@ let value.source = pkgs.writeText "${name}.pam" service.text; }; - optionalSudoConfigForSSHAgentAuth = optionalString config.security.pam.enableSSHAgentAuth '' + optionalSudoConfigForSSHAgentAuth = optionalString config.security.pam.sshAgentAuth.enable '' # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic. Defaults env_keep+=SSH_AUTH_SOCK ''; @@ -956,6 +956,7 @@ in imports = [ (mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ]) + (mkRenamedOptionModule [ "security" "pam" "enableSSHAgentAuth" ] [ "security" "pam" "sshAgentAuth" "enable" ]) ]; ###### interface @@ -1025,16 +1026,34 @@ in ''; }; - security.pam.enableSSHAgentAuth = mkOption { - type = types.bool; - default = false; - description = - lib.mdDoc '' - Enable sudo logins if the user's SSH agent provides a key - present in {file}`~/.ssh/authorized_keys`. - This allows machines to exclusively use SSH keys instead of - passwords. + security.pam.sshAgentAuth = { + enable = mkEnableOption '' + authenticating using a signature performed by the ssh-agent. + This allows using SSH keys exclusively, instead of passwords, for instance on remote machines + ''; + + authorizedKeysFiles = mkOption { + type = with types; listOf str; + description = '' + A list of paths to files in OpenSSH's `authorized_keys` format, containing + the keys that will be trusted by the `pam_ssh_agent_auth` module. + + The following patterns are expanded when interpreting the path: + - `%f` and `%H` respectively expand to the fully-qualified and short hostname ; + - `%u` expands to the username ; + - `~` or `%h` expands to the user's home directory. + + ::: {.note} + Specifying user-writeable files here result in an insecure configuration: a malicious process + can then edit such an authorized_keys file and bypass the ssh-agent-based authentication. + + See [issue #31611](https://github.com/NixOS/nixpkgs/issues/31611) + ::: ''; + example = [ "/etc/ssh/authorized_keys.d/%u" ]; + default = config.services.openssh.authorizedKeysFiles; + defaultText = literalExpression "config.services.openssh.authorizedKeysFiles"; + }; }; security.pam.enableOTPW = mkEnableOption (lib.mdDoc "the OTPW (one-time password) PAM module"); @@ -1067,8 +1086,8 @@ in security.pam.krb5 = { enable = mkOption { - default = config.krb5.enable; - defaultText = literalExpression "config.krb5.enable"; + default = config.security.krb5.enable; + defaultText = literalExpression "config.security.krb5.enable"; type = types.bool; description = lib.mdDoc '' Enables Kerberos PAM modules (`pam-krb5`, @@ -1076,7 +1095,7 @@ in If set, users can authenticate with their Kerberos password. This requires a valid Kerberos configuration - (`config.krb5.enable` should be set to + (`config.security.krb5.enable` should be set to `true`). Note that the Kerberos PAM modules are not necessary when using SSS @@ -1457,7 +1476,7 @@ in ''; } { - assertion = config.security.pam.enableSSHAgentAuth -> config.services.openssh.authorizedKeysFiles != []; + assertion = with config.security.pam.sshAgentAuth; enable -> authorizedKeysFiles != []; message = '' `security.pam.enableSSHAgentAuth` requires `services.openssh.authorizedKeysFiles` to be a non-empty list. Did you forget to set `services.openssh.enable` ? @@ -1465,6 +1484,16 @@ in } ]; + warnings = optional + (with lib; with config.security.pam.sshAgentAuth; + enable && any (s: hasPrefix "%h" s || hasPrefix "~" s) authorizedKeysFiles) + ''config.security.pam.sshAgentAuth.authorizedKeysFiles contains files in the user's home directory. + + Specifying user-writeable files there result in an insecure configuration: + a malicious process can then edit such an authorized_keys file and bypass the ssh-agent-based authentication. + See https://github.com/NixOS/nixpkgs/issues/31611 + ''; + environment.systemPackages = # Include the PAM modules in the system path mostly for the manpages. [ pkgs.pam ] diff --git a/nixpkgs/nixos/modules/security/sudo.nix b/nixpkgs/nixos/modules/security/sudo.nix index 3dd5d2e525d9..6aa9445eab65 100644 --- a/nixpkgs/nixos/modules/security/sudo.nix +++ b/nixpkgs/nixos/modules/security/sudo.nix @@ -6,8 +6,6 @@ let cfg = config.security.sudo; - inherit (config.security.pam) enableSSHAgentAuth; - toUserString = user: if (isInt user) then "#${toString user}" else "${user}"; toGroupString = group: if (isInt group) then "%#${toString group}" else "%${group}"; diff --git a/nixpkgs/nixos/modules/services/admin/pgadmin.nix b/nixpkgs/nixos/modules/services/admin/pgadmin.nix index 5eaa911e37f1..20b6b6670d9c 100644 --- a/nixpkgs/nixos/modules/services/admin/pgadmin.nix +++ b/nixpkgs/nixos/modules/services/admin/pgadmin.nix @@ -44,12 +44,19 @@ in initialPasswordFile = mkOption { description = lib.mdDoc '' - Initial password file for the pgAdmin account. + Initial password file for the pgAdmin account. Minimum length by default is 6. + Please see `services.pgadmin.minimumPasswordLength`. NOTE: Should be string not a store path, to prevent the password from being world readable ''; type = types.path; }; + minimumPasswordLength = mkOption { + description = lib.mdDoc "Minimum length of the password"; + type = types.int; + default = 6; + }; + emailServer = { enable = mkOption { description = lib.mdDoc '' @@ -116,7 +123,9 @@ in services.pgadmin.settings = { DEFAULT_SERVER_PORT = cfg.port; + PASSWORD_LENGTH_MIN = cfg.minimumPasswordLength; SERVER_MODE = true; + UPGRADE_CHECK_ENABLED = false; } // (optionalAttrs cfg.openFirewall { DEFAULT_SERVER = mkDefault "::"; }) // (optionalAttrs cfg.emailServer.enable { @@ -140,6 +149,14 @@ in preStart = '' # NOTE: this is idempotent (aka running it twice has no effect) + # Check here for password length to prevent pgadmin from starting + # and presenting a hard to find error message + # see https://github.com/NixOS/nixpkgs/issues/270624 + PW_LENGTH=$(wc -m < ${escapeShellArg cfg.initialPasswordFile}) + if [ $PW_LENGTH -lt ${toString cfg.minimumPasswordLength} ]; then + echo "Password must be at least ${toString cfg.minimumPasswordLength} characters long" + exit 1 + fi ( # Email address: echo ${escapeShellArg cfg.initialEmail} @@ -151,7 +168,7 @@ in echo "$PW" # Retype password: echo "$PW" - ) | ${cfg.package}/bin/pgadmin4-setup + ) | ${cfg.package}/bin/pgadmin4-cli setup-db ''; restartTriggers = [ diff --git a/nixpkgs/nixos/modules/services/databases/influxdb.nix b/nixpkgs/nixos/modules/services/databases/influxdb.nix index 34b4139e7c58..adb212ab08d0 100644 --- a/nixpkgs/nixos/modules/services/databases/influxdb.nix +++ b/nixpkgs/nixos/modules/services/databases/influxdb.nix @@ -161,6 +161,7 @@ in ExecStart = ''${cfg.package}/bin/influxd -config "${configFile}"''; User = cfg.user; Group = cfg.group; + Restart = "on-failure"; }; postStart = let diff --git a/nixpkgs/nixos/modules/services/hardware/acpid.nix b/nixpkgs/nixos/modules/services/hardware/acpid.nix index 821f4ef205fc..6021aad09f45 100644 --- a/nixpkgs/nixos/modules/services/hardware/acpid.nix +++ b/nixpkgs/nixos/modules/services/hardware/acpid.nix @@ -135,6 +135,7 @@ in wantedBy = [ "multi-user.target" ]; serviceConfig = { + PrivateNetwork = true; ExecStart = escapeShellArgs ([ "${pkgs.acpid}/bin/acpid" "--foreground" diff --git a/nixpkgs/nixos/modules/services/hardware/pcscd.nix b/nixpkgs/nixos/modules/services/hardware/pcscd.nix index a9e4998efe37..85accd8335f7 100644 --- a/nixpkgs/nixos/modules/services/hardware/pcscd.nix +++ b/nixpkgs/nixos/modules/services/hardware/pcscd.nix @@ -16,9 +16,6 @@ let in { - - ###### interface - options.services.pcscd = { enable = mkEnableOption (lib.mdDoc "PCSC-Lite daemon"); @@ -46,13 +43,10 @@ in }; }; - ###### implementation - config = mkIf config.services.pcscd.enable { - environment.etc."reader.conf".source = cfgFile; - environment.systemPackages = [ package ]; + environment.systemPackages = [ package.out ]; systemd.packages = [ (getBin package) ]; services.pcscd.plugins = [ pkgs.ccid ]; @@ -61,7 +55,6 @@ in systemd.services.pcscd = { environment.PCSCLITE_HP_DROPDIR = pluginEnv; - restartTriggers = [ "/etc/reader.conf" ]; # If the cfgFile is empty and not specified (in which case the default # /etc/reader.conf is assumed), pcscd will happily start going through the diff --git a/nixpkgs/nixos/modules/services/mail/dovecot.nix b/nixpkgs/nixos/modules/services/mail/dovecot.nix index abbb2f32e6cc..25c7017a1d25 100644 --- a/nixpkgs/nixos/modules/services/mail/dovecot.nix +++ b/nixpkgs/nixos/modules/services/mail/dovecot.nix @@ -1,8 +1,11 @@ { options, config, lib, pkgs, ... }: -with lib; - let + inherit (lib) any attrValues concatMapStringsSep concatStrings + concatStringsSep flatten imap1 isList literalExpression mapAttrsToList + mkEnableOption mkIf mkOption mkRemovedOptionModule optional optionalAttrs + optionalString singleton types; + cfg = config.services.dovecot2; dovecotPkg = pkgs.dovecot; @@ -113,6 +116,36 @@ let '' ) + '' + plugin { + sieve_plugins = ${concatStringsSep " " cfg.sieve.plugins} + sieve_extensions = ${concatStringsSep " " (map (el: "+${el}") cfg.sieve.extensions)} + sieve_global_extensions = ${concatStringsSep " " (map (el: "+${el}") cfg.sieve.globalExtensions)} + '' + (optionalString (cfg.imapsieve.mailbox != []) '' + ${ + concatStringsSep "\n" (flatten (imap1 ( + idx: el: + singleton "imapsieve_mailbox${toString idx}_name = ${el.name}" + ++ optional (el.from != null) "imapsieve_mailbox${toString idx}_from = ${el.from}" + ++ optional (el.causes != null) "imapsieve_mailbox${toString idx}_causes = ${el.causes}" + ++ optional (el.before != null) "imapsieve_mailbox${toString idx}_before = file:${stateDir}/imapsieve/before/${baseNameOf el.before}" + ++ optional (el.after != null) "imapsieve_mailbox${toString idx}_after = file:${stateDir}/imapsieve/after/${baseNameOf el.after}" + ) + cfg.imapsieve.mailbox)) + } + '') + (optionalString (cfg.sieve.pipeBins != []) '' + sieve_pipe_bin_dir = ${pkgs.linkFarm "sieve-pipe-bins" (map (el: { + name = builtins.unsafeDiscardStringContext (baseNameOf el); + path = el; + }) + cfg.sieve.pipeBins)} + '') + '' + } + '' + cfg.extraConfig ]; @@ -343,6 +376,104 @@ in description = lib.mdDoc "Quota limit for the user in bytes. Supports suffixes b, k, M, G, T and %."; }; + imapsieve.mailbox = mkOption { + default = []; + description = "Configure Sieve filtering rules on IMAP actions"; + type = types.listOf (types.submodule ({ config, ... }: { + options = { + name = mkOption { + description = '' + This setting configures the name of a mailbox for which administrator scripts are configured. + + The settings defined hereafter with matching sequence numbers apply to the mailbox named by this setting. + + This setting supports wildcards with a syntax compatible with the IMAP LIST command, meaning that this setting can apply to multiple or even all ("*") mailboxes. + ''; + example = "Junk"; + type = types.str; + }; + + from = mkOption { + default = null; + description = '' + Only execute the administrator Sieve scripts for the mailbox configured with services.dovecot2.imapsieve.mailbox.<name>.name when the message originates from the indicated mailbox. + + This setting supports wildcards with a syntax compatible with the IMAP LIST command, meaning that this setting can apply to multiple or even all ("*") mailboxes. + ''; + example = "*"; + type = types.nullOr types.str; + }; + + causes = mkOption { + default = null; + description = '' + Only execute the administrator Sieve scripts for the mailbox configured with services.dovecot2.imapsieve.mailbox.<name>.name when one of the listed IMAPSIEVE causes apply. + + This has no effect on the user script, which is always executed no matter the cause. + ''; + example = "COPY"; + type = types.nullOr (types.enum [ "APPEND" "COPY" "FLAG" ]); + }; + + before = mkOption { + default = null; + description = '' + When an IMAP event of interest occurs, this sieve script is executed before any user script respectively. + + This setting each specify the location of a single sieve script. The semantics of this setting is similar to sieve_before: the specified scripts form a sequence together with the user script in which the next script is only executed when an (implicit) keep action is executed. + ''; + example = literalExpression "./report-spam.sieve"; + type = types.nullOr types.path; + }; + + after = mkOption { + default = null; + description = '' + When an IMAP event of interest occurs, this sieve script is executed after any user script respectively. + + This setting each specify the location of a single sieve script. The semantics of this setting is similar to sieve_after: the specified scripts form a sequence together with the user script in which the next script is only executed when an (implicit) keep action is executed. + ''; + example = literalExpression "./report-spam.sieve"; + type = types.nullOr types.path; + }; + }; + })); + }; + + sieve = { + plugins = mkOption { + default = []; + example = [ "sieve_extprograms" ]; + description = "Sieve plugins to load"; + type = types.listOf types.str; + }; + + extensions = mkOption { + default = []; + description = "Sieve extensions for use in user scripts"; + example = [ "notify" "imapflags" "vnd.dovecot.filter" ]; + type = types.listOf types.str; + }; + + globalExtensions = mkOption { + default = []; + example = [ "vnd.dovecot.environment" ]; + description = "Sieve extensions for use in global scripts"; + type = types.listOf types.str; + }; + + pipeBins = mkOption { + default = []; + example = literalExpression '' + map lib.getExe [ + (pkgs.writeShellScriptBin "learn-ham.sh" "exec ''${pkgs.rspamd}/bin/rspamc learn_ham") + (pkgs.writeShellScriptBin "learn-spam.sh" "exec ''${pkgs.rspamd}/bin/rspamc learn_spam") + ] + ''; + description = "Programs available for use by the vnd.dovecot.pipe extension"; + type = types.listOf types.path; + }; + }; }; @@ -353,14 +484,23 @@ in enable = true; params.dovecot2 = {}; }; - services.dovecot2.protocols = - optional cfg.enableImap "imap" - ++ optional cfg.enablePop3 "pop3" - ++ optional cfg.enableLmtp "lmtp"; - - services.dovecot2.mailPlugins = mkIf cfg.enableQuota { - globally.enable = [ "quota" ]; - perProtocol.imap.enable = [ "imap_quota" ]; + + services.dovecot2 = { + protocols = + optional cfg.enableImap "imap" + ++ optional cfg.enablePop3 "pop3" + ++ optional cfg.enableLmtp "lmtp"; + + mailPlugins = mkIf cfg.enableQuota { + globally.enable = [ "quota" ]; + perProtocol.imap.enable = [ "imap_quota" ]; + }; + + sieve.plugins = + optional (cfg.imapsieve.mailbox != []) "sieve_imapsieve" + ++ optional (cfg.sieve.pipeBins != []) "sieve_extprograms"; + + sieve.globalExtensions = optional (cfg.sieve.pipeBins != []) "vnd.dovecot.pipe"; }; users.users = { @@ -415,7 +555,7 @@ in # (should be 0) so that the compiled sieve script is newer than # the source file and Dovecot won't try to compile it. preStart = '' - rm -rf ${stateDir}/sieve + rm -rf ${stateDir}/sieve ${stateDir}/imapsieve '' + optionalString (cfg.sieveScripts != {}) '' mkdir -p ${stateDir}/sieve ${concatStringsSep "\n" ( @@ -432,6 +572,29 @@ in ) cfg.sieveScripts )} chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve' + '' + + optionalString (cfg.imapsieve.mailbox != []) '' + mkdir -p ${stateDir}/imapsieve/{before,after} + + ${ + concatMapStringsSep "\n" + (el: + optionalString (el.before != null) '' + cp -p ${el.before} ${stateDir}/imapsieve/before/${baseNameOf el.before} + ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/imapsieve/before/${baseNameOf el.before}' + '' + + optionalString (el.after != null) '' + cp -p ${el.after} ${stateDir}/imapsieve/after/${baseNameOf el.after} + ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/imapsieve/after/${baseNameOf el.after}' + '' + ) + cfg.imapsieve.mailbox + } + + ${ + optionalString (cfg.mailUser != null && cfg.mailGroup != null) + "chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/imapsieve'" + } ''; }; @@ -459,4 +622,5 @@ in }; + meta.maintainers = [ lib.maintainers.dblsaiko ]; } diff --git a/nixpkgs/nixos/modules/services/mail/listmonk.nix b/nixpkgs/nixos/modules/services/mail/listmonk.nix index be2f9680ca5a..945eb436c1f2 100644 --- a/nixpkgs/nixos/modules/services/mail/listmonk.nix +++ b/nixpkgs/nixos/modules/services/mail/listmonk.nix @@ -201,13 +201,12 @@ in { DynamicUser = true; NoNewPrivileges = true; CapabilityBoundingSet = ""; - SystemCallArchitecture = "native"; + SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" ]; - ProtectDevices = true; + PrivateDevices = true; ProtectControlGroups = true; ProtectKernelTunables = true; ProtectHome = true; - DeviceAllow = false; RestrictNamespaces = true; RestrictRealtime = true; UMask = "0027"; diff --git a/nixpkgs/nixos/modules/services/mail/nullmailer.nix b/nixpkgs/nixos/modules/services/mail/nullmailer.nix index f6befe246b12..4fd0026dbe4e 100644 --- a/nixpkgs/nixos/modules/services/mail/nullmailer.nix +++ b/nixpkgs/nixos/modules/services/mail/nullmailer.nix @@ -120,7 +120,7 @@ with lib; }; maxpause = mkOption { - type = types.nullOr types.str; + type = with types; nullOr (oneOf [ str int ]); default = null; description = lib.mdDoc '' The maximum time to pause between successive queue runs, in seconds. @@ -138,7 +138,7 @@ with lib; }; pausetime = mkOption { - type = types.nullOr types.str; + type = with types; nullOr (oneOf [ str int ]); default = null; description = lib.mdDoc '' The minimum time to pause between successive queue runs when there @@ -168,7 +168,7 @@ with lib; }; sendtimeout = mkOption { - type = types.nullOr types.str; + type = with types; nullOr (oneOf [ str int ]); default = null; description = lib.mdDoc '' The time to wait for a remote module listed above to complete sending @@ -194,7 +194,7 @@ with lib; environment = { systemPackages = [ pkgs.nullmailer ]; etc = let - validAttrs = filterAttrs (name: value: value != null) cfg.config; + validAttrs = lib.mapAttrs (_: toString) (filterAttrs (_: value: value != null) cfg.config); in (foldl' (as: name: as // { "nullmailer/${name}".text = validAttrs.${name}; }) {} (attrNames validAttrs)) // optionalAttrs (cfg.remotesFile != null) { "nullmailer/remotes".source = cfg.remotesFile; }; diff --git a/nixpkgs/nixos/modules/services/mail/roundcube.nix b/nixpkgs/nixos/modules/services/mail/roundcube.nix index c35ece8362f6..c883c143e523 100644 --- a/nixpkgs/nixos/modules/services/mail/roundcube.nix +++ b/nixpkgs/nixos/modules/services/mail/roundcube.nix @@ -102,6 +102,12 @@ in apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.3)}M"; }; + configureNginx = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc "Configure nginx as a reverse proxy for roundcube."; + }; + extraConfig = mkOption { type = types.lines; default = ""; @@ -142,26 +148,39 @@ in ${cfg.extraConfig} ''; - services.nginx = { + services.nginx = lib.mkIf cfg.configureNginx { enable = true; virtualHosts = { ${cfg.hostName} = { forceSSL = mkDefault true; enableACME = mkDefault true; + root = cfg.package; locations."/" = { - root = cfg.package; index = "index.php"; + priority = 1100; extraConfig = '' - location ~* \.php(/|$) { - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${fpm.socket}; - - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param PATH_INFO $fastcgi_path_info; - - include ${config.services.nginx.package}/conf/fastcgi_params; - include ${pkgs.nginx}/conf/fastcgi.conf; - } + add_header Cache-Control 'public, max-age=604800, must-revalidate'; + ''; + }; + locations."~ ^/(SQL|bin|config|logs|temp|vendor)/" = { + priority = 3110; + extraConfig = '' + return 404; + ''; + }; + locations."~ ^/(CHANGELOG.md|INSTALL|LICENSE|README.md|SECURITY.md|UPGRADING|composer.json|composer.lock)" = { + priority = 3120; + extraConfig = '' + return 404; + ''; + }; + locations."~* \\.php(/|$)" = { + priority = 3130; + extraConfig = '' + fastcgi_pass unix:${fpm.socket}; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + include ${config.services.nginx.package}/conf/fastcgi.conf; ''; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix index 98134e94eeed..b8b077240115 100644 --- a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix +++ b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix @@ -79,12 +79,6 @@ in cache-file = mkDefault "/var/lib/ntfy-sh/cache-file.db"; }; - systemd.tmpfiles.rules = [ - "f ${cfg.settings.auth-file} 0600 ${cfg.user} ${cfg.group} - -" - "d ${cfg.settings.attachment-cache-dir} 0700 ${cfg.user} ${cfg.group} - -" - "f ${cfg.settings.cache-file} 0600 ${cfg.user} ${cfg.group} - -" - ]; - systemd.services.ntfy-sh = { description = "Push notifications server"; diff --git a/nixpkgs/nixos/modules/services/monitoring/netdata.nix b/nixpkgs/nixos/modules/services/monitoring/netdata.nix index ec6aa5615039..5cf3c096397c 100644 --- a/nixpkgs/nixos/modules/services/monitoring/netdata.nix +++ b/nixpkgs/nixos/modules/services/monitoring/netdata.nix @@ -206,7 +206,15 @@ in { description = "Real time performance monitoring"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - path = (with pkgs; [ curl gawk iproute2 which procps bash ]) + path = (with pkgs; [ + curl + gawk + iproute2 + which + procps + bash + util-linux # provides logger command; required for syslog health alarms + ]) ++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages) ++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package); environment = { diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix index edc6e4b5022a..840ce493ee81 100644 --- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix +++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix @@ -4,6 +4,25 @@ with lib; let cfg = config.services.prometheus.exporters.snmp; + + # This ensures that we can deal with string paths, path types and + # store-path strings with context. + coerceConfigFile = file: + if (builtins.isPath file) || (lib.isStorePath file) then + file + else + (lib.warn '' + ${logPrefix}: configuration file "${file}" is being copied to the nix-store. + If you would like to avoid that, please set enableConfigCheck to false. + '' /. + file); + + checkConfig = file: + pkgs.runCommandLocal "checked-snmp-exporter-config.yml" { + nativeBuildInputs = [ pkgs.buildPackages.prometheus-snmp-exporter ]; + } '' + ln -s ${coerceConfigFile file} $out + snmp_exporter --dry-run --config.file $out + ''; in { port = 9116; @@ -24,15 +43,23 @@ in Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option. ''; example = { - "default" = { - "version" = 2; - "auth" = { - "community" = "public"; - }; + auths.public_v2 = { + community = "public"; + version = 2; }; }; }; + enableConfigCheck = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to run a correctness check for the configuration file. This depends + on the configuration file residing in the nix-store. Paths passed as string will + be copied to the store. + ''; + }; + logFormat = mkOption { type = types.enum ["logfmt" "json"]; default = "logfmt"; @@ -50,9 +77,13 @@ in }; }; serviceOpts = let - configFile = if cfg.configurationPath != null - then cfg.configurationPath - else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}"; + uncheckedConfigFile = if cfg.configurationPath != null + then cfg.configurationPath + else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}"; + configFile = if cfg.enableConfigCheck then + checkConfig uncheckedConfigFile + else + uncheckedConfigFile; in { serviceConfig = { ExecStart = '' diff --git a/nixpkgs/nixos/modules/services/monitoring/snmpd.nix b/nixpkgs/nixos/modules/services/monitoring/snmpd.nix new file mode 100644 index 000000000000..f2d3953e6a62 --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/snmpd.nix @@ -0,0 +1,83 @@ +{ pkgs, config, lib, ... }: + +let + cfg = config.services.snmpd; + configFile = if cfg.configText != "" then + pkgs.writeText "snmpd.cfg" '' + ${cfg.configText} + '' else null; +in { + options.services.snmpd = { + enable = lib.mkEnableOption "snmpd"; + + package = lib.mkPackageOption pkgs "net-snmp" {}; + + listenAddress = lib.mkOption { + type = lib.types.str; + default = "0.0.0.0"; + description = lib.mdDoc '' + The address to listen on for SNMP and AgentX messages. + ''; + example = "127.0.0.1"; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 161; + description = lib.mdDoc '' + The port to listen on for SNMP and AgentX messages. + ''; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Open port in firewall for snmpd. + ''; + }; + + configText = lib.mkOption { + type = lib.types.lines; + default = ""; + description = lib.mdDoc '' + The contents of the snmpd.conf. If the {option}`configFile` option + is set, this value will be ignored. + + Note that the contents of this option will be added to the Nix + store as world-readable plain text, {option}`configFile` can be used in + addition to a secret management tool to protect sensitive data. + ''; + }; + + configFile = lib.mkOption { + type = lib.types.path; + default = configFile; + defaultText = lib.literalMD "The value of {option}`configText`."; + description = lib.mdDoc '' + Path to the snmpd.conf file. By default, if {option}`configText` is set, + a config file will be automatically generated. + ''; + }; + + }; + + config = lib.mkIf cfg.enable { + systemd.services."snmpd" = { + description = "Simple Network Management Protocol (SNMP) daemon."; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + ExecStart = "${lib.getExe' cfg.package "snmpd"} -f -Lo -c ${cfg.configFile} ${cfg.listenAddress}:${toString cfg.port}"; + }; + }; + + networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall [ + cfg.port + ]; + }; + + meta.maintainers = [ lib.maintainers.eliandoran ]; + +} diff --git a/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix b/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix index 8226fc614bc4..10162c1633e7 100644 --- a/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix +++ b/nixpkgs/nixos/modules/services/network-filesystems/kubo.nix @@ -52,7 +52,7 @@ let multiaddrsToListenStreams = addrIn: let - addrs = if builtins.typeOf addrIn == "list" + addrs = if builtins.isList addrIn then addrIn else [ addrIn ]; unfilteredResult = map multiaddrToListenStream addrs; in @@ -60,7 +60,7 @@ let multiaddrsToListenDatagrams = addrIn: let - addrs = if builtins.typeOf addrIn == "list" + addrs = if builtins.isList addrIn then addrIn else [ addrIn ]; unfilteredResult = map multiaddrToListenDatagram addrs; in @@ -99,7 +99,12 @@ in services.kubo = { - enable = mkEnableOption (lib.mdDoc "Interplanetary File System (WARNING: may cause severe network degradation)"); + enable = mkEnableOption (lib.mdDoc '' + the Interplanetary File System (WARNING: may cause severe network degradation). + NOTE: after enabling this option and rebuilding your system, you need to log out + and back in for the `IPFS_PATH` environment variable to be present in your shell. + Until you do that, the CLI tools won't be able to talk to the daemon by default + ''); package = mkPackageOption pkgs "kubo" { }; @@ -274,16 +279,17 @@ in { assertion = !((lib.versionAtLeast cfg.package.version "0.21") && (builtins.hasAttr "Experimental" cfg.settings) && (builtins.hasAttr "AcceleratedDHTClient" cfg.settings.Experimental)); message = '' - The `services.kubo.settings.Experimental.AcceleratedDHTClient` option was renamed to `services.kubo.settings.Routing.AcceleratedDHTClient` in Kubo 0.21. - ''; + The `services.kubo.settings.Experimental.AcceleratedDHTClient` option was renamed to `services.kubo.settings.Routing.AcceleratedDHTClient` in Kubo 0.21. + ''; } ]; environment.systemPackages = [ cfg.package ]; environment.variables.IPFS_PATH = fakeKuboRepo; - # https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size + # https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes boot.kernel.sysctl."net.core.rmem_max" = mkDefault 2500000; + boot.kernel.sysctl."net.core.wmem_max" = mkDefault 2500000; programs.fuse = mkIf cfg.autoMount { userAllowOther = true; diff --git a/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix b/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix index 08fc092e230c..782681018116 100644 --- a/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix +++ b/nixpkgs/nixos/modules/services/networking/avahi-daemon.nix @@ -273,17 +273,17 @@ in system.nssModules = optional (cfg.nssmdns4 || cfg.nssmdns6) pkgs.nssmdns; system.nssDatabases.hosts = let - mdnsMinimal = if (cfg.nssmdns4 && cfg.nssmdns6) then - "mdns_minimal" + mdns = if (cfg.nssmdns4 && cfg.nssmdns6) then + "mdns" else if (!cfg.nssmdns4 && cfg.nssmdns6) then - "mdns6_minimal" + "mdns6" else if (cfg.nssmdns4 && !cfg.nssmdns6) then - "mdns4_minimal" + "mdns4" else ""; in optionals (cfg.nssmdns4 || cfg.nssmdns6) (mkMerge [ - (mkBefore [ "${mdnsMinimal} [NOTFOUND=return]" ]) # before resolve - (mkAfter [ "mdns" ]) # after dns + (mkBefore [ "${mdns}_minimal [NOTFOUND=return]" ]) # before resolve + (mkAfter [ "${mdns}" ]) # after dns ]); environment.systemPackages = [ cfg.package ]; diff --git a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix index 8b6d3fc55f3e..2b59352ac616 100644 --- a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix +++ b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix @@ -98,7 +98,7 @@ let # anything ever again ("couldn't resolve ..., giving up on # it"), so we silently lose time synchronisation. This also # applies to openntpd. - /run/current-system/systemd/bin/systemctl try-reload-or-restart ntpd.service openntpd.service chronyd.service || true + /run/current-system/systemd/bin/systemctl try-reload-or-restart ntpd.service openntpd.service chronyd.service ntpd-rs.service || true fi ${cfg.runHook} diff --git a/nixpkgs/nixos/modules/services/networking/frp.nix b/nixpkgs/nixos/modules/services/networking/frp.nix index 218d532c12da..eb022308bc29 100644 --- a/nixpkgs/nixos/modules/services/networking/frp.nix +++ b/nixpkgs/nixos/modules/services/networking/frp.nix @@ -4,8 +4,8 @@ with lib; let cfg = config.services.frp; - settingsFormat = pkgs.formats.ini { }; - configFile = settingsFormat.generate "frp.ini" cfg.settings; + settingsFormat = pkgs.formats.toml { }; + configFile = settingsFormat.generate "frp.toml" cfg.settings; isClient = (cfg.role == "client"); isServer = (cfg.role == "server"); in @@ -31,17 +31,13 @@ in default = { }; description = mdDoc '' Frp configuration, for configuration options - see the example of [client](https://github.com/fatedier/frp/blob/dev/conf/frpc_legacy_full.ini) - or [server](https://github.com/fatedier/frp/blob/dev/conf/frps_legacy_full.ini) on github. - ''; - example = literalExpression '' - { - common = { - server_addr = "x.x.x.x"; - server_port = 7000; - }; - } + see the example of [client](https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml) + or [server](https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml) on github. ''; + example = { + serverAddr = "x.x.x.x"; + serverPort = 7000; + }; }; }; }; @@ -62,7 +58,7 @@ in Type = "simple"; Restart = "on-failure"; RestartSec = 15; - ExecStart = "${cfg.package}/bin/${executableFile} -c ${configFile}"; + ExecStart = "${cfg.package}/bin/${executableFile} --strict_config -c ${configFile}"; StateDirectoryMode = optionalString isServer "0700"; DynamicUser = true; # Hardening diff --git a/nixpkgs/nixos/modules/services/networking/miniupnpd.nix b/nixpkgs/nixos/modules/services/networking/miniupnpd.nix index 64aacaf35040..116298dc6b1d 100644 --- a/nixpkgs/nixos/modules/services/networking/miniupnpd.nix +++ b/nixpkgs/nixos/modules/services/networking/miniupnpd.nix @@ -13,8 +13,17 @@ let listening_ip=${range} '') cfg.internalIPs} + ${lib.optionalString (firewall == "nftables") '' + upnp_table_name=miniupnpd + upnp_nat_table_name=miniupnpd + ''} + ${cfg.appendConfig} ''; + firewall = if config.networking.nftables.enable then "nftables" else "iptables"; + miniupnpd = pkgs.miniupnpd.override { inherit firewall; }; + firewallScripts = lib.optionals (firewall == "iptables") + ([ "iptables"] ++ lib.optional (config.networking.enableIPv6) "ip6tables"); in { options = { @@ -57,20 +66,50 @@ in }; config = mkIf cfg.enable { - networking.firewall.extraCommands = '' - ${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_init.sh -i ${cfg.externalInterface} - ''; + networking.firewall.extraCommands = lib.mkIf (firewallScripts != []) (builtins.concatStringsSep "\n" (map (fw: '' + EXTIF=${cfg.externalInterface} ${pkgs.bash}/bin/bash -x ${miniupnpd}/etc/miniupnpd/${fw}_init.sh + '') firewallScripts)); + + networking.firewall.extraStopCommands = lib.mkIf (firewallScripts != []) (builtins.concatStringsSep "\n" (map (fw: '' + EXTIF=${cfg.externalInterface} ${pkgs.bash}/bin/bash -x ${miniupnpd}/etc/miniupnpd/${fw}_removeall.sh + '') firewallScripts)); - networking.firewall.extraStopCommands = '' - ${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_removeall.sh -i ${cfg.externalInterface} - ''; + networking.nftables = lib.mkIf (firewall == "nftables") { + # see nft_init in ${miniupnpd-nftables}/etc/miniupnpd + tables.miniupnpd = { + family = "inet"; + # The following is omitted because it's expected that the firewall is to be responsible for it. + # + # chain forward { + # type filter hook forward priority filter; policy drop; + # jump miniupnpd + # } + # + # Otherwise, it quickly gets ugly with (potentially) two forward chains with "policy drop". + # This means the chain "miniupnpd" never actually gets triggered and is simply there to satisfy + # miniupnpd. If you're doing it yourself (without networking.firewall), the easiest way to get + # it to work is adding a rule "ct status dnat accept" - this is what networking.firewall does. + # If you don't want to simply accept forwarding for all "ct status dnat" packets, override + # upnp_table_name with whatever your table is, create a chain "miniupnpd" in your table and + # jump into it from your forward chain. + content = '' + chain miniupnpd {} + chain prerouting_miniupnpd { + type nat hook prerouting priority dstnat; policy accept; + } + chain postrouting_miniupnpd { + type nat hook postrouting priority srcnat; policy accept; + } + ''; + }; + }; systemd.services.miniupnpd = { description = "MiniUPnP daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${pkgs.miniupnpd}/bin/miniupnpd -f ${configFile}"; + ExecStart = "${miniupnpd}/bin/miniupnpd -f ${configFile}"; PIDFile = "/run/miniupnpd.pid"; Type = "forking"; }; diff --git a/nixpkgs/nixos/modules/services/networking/networkmanager.nix b/nixpkgs/nixos/modules/services/networking/networkmanager.nix index d32712c8243d..c96439cf2641 100644 --- a/nixpkgs/nixos/modules/services/networking/networkmanager.nix +++ b/nixpkgs/nixos/modules/services/networking/networkmanager.nix @@ -565,7 +565,10 @@ in wantedBy = [ "network-online.target" ]; }; - systemd.services.ModemManager.aliases = [ "dbus-org.freedesktop.ModemManager1.service" ]; + systemd.services.ModemManager = { + aliases = [ "dbus-org.freedesktop.ModemManager1.service" ]; + path = lib.optionals (cfg.fccUnlockScripts != []) [ pkgs.libqmi pkgs.libmbim ]; + }; systemd.services.NetworkManager-dispatcher = { wantedBy = [ "network.target" ]; diff --git a/nixpkgs/nixos/modules/services/networking/ntp/ntpd-rs.nix b/nixpkgs/nixos/modules/services/networking/ntp/ntpd-rs.nix new file mode 100644 index 000000000000..4643ac146ddb --- /dev/null +++ b/nixpkgs/nixos/modules/services/networking/ntp/ntpd-rs.nix @@ -0,0 +1,89 @@ +{ lib, config, pkgs, ... }: + +let + cfg = config.services.ntpd-rs; + format = pkgs.formats.toml { }; + configFile = format.generate "ntpd-rs.toml" cfg.settings; +in +{ + options.services.ntpd-rs = { + enable = lib.mkEnableOption "Network Time Service (ntpd-rs)"; + metrics.enable = lib.mkEnableOption "ntpd-rs Prometheus Metrics Exporter"; + + package = lib.mkPackageOption pkgs "ntpd-rs" { }; + + useNetworkingTimeServers = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc '' + Use source time servers from {var}`networking.timeServers` in config. + ''; + }; + + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = format.type; + }; + default = { }; + description = lib.mdDoc '' + Settings to write to {file}`ntp.toml` + + See <https://docs.ntpd-rs.pendulum-project.org/man/ntp.toml.5> + for more information about available options. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = !config.services.timesyncd.enable; + message = '' + `ntpd-rs` is not compatible with `services.timesyncd`. Please disable one of them. + ''; + } + ]; + + environment.systemPackages = [ cfg.package ]; + systemd.packages = [ cfg.package ]; + + services.timesyncd.enable = false; + systemd.services.systemd-timedated.environment = { + SYSTEMD_TIMEDATED_NTP_SERVICES = "ntpd-rs.service"; + }; + + services.ntpd-rs.settings = { + observability = { + observation-path = lib.mkDefault "/var/run/ntpd-rs/observe"; + }; + source = lib.mkIf cfg.useNetworkingTimeServers (map + (ts: { + mode = "server"; + address = ts; + }) + config.networking.timeServers); + }; + + systemd.services.ntpd-rs = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = ""; + Group = ""; + DynamicUser = true; + ExecStart = [ "" "${lib.makeBinPath [ cfg.package ]}/ntp-daemon --config=${configFile}" ]; + }; + }; + + systemd.services.ntpd-rs-metrics = lib.mkIf cfg.metrics.enable { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = ""; + Group = ""; + DynamicUser = true; + ExecStart = [ "" "${lib.makeBinPath [ cfg.package ]}/ntp-metrics-exporter --config=${configFile}" ]; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ fpletz ]; +} diff --git a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix index c15780551493..e19b53f5f3ff 100644 --- a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix @@ -602,7 +602,11 @@ in { description = "SSH Socket"; wantedBy = [ "sockets.target" ]; socketConfig.ListenStream = if cfg.listenAddresses != [] then - map (l: "${l.addr}:${toString (if l.port != null then l.port else 22)}") cfg.listenAddresses + concatMap + ({ addr, port }: + if port != null then [ "${addr}:${toString port}" ] + else map (p: "${addr}:${toString p}") cfg.ports) + cfg.listenAddresses else cfg.ports; socketConfig.Accept = true; diff --git a/nixpkgs/nixos/modules/services/networking/xrdp.nix b/nixpkgs/nixos/modules/services/networking/xrdp.nix index 3b674840b936..7e6634cd239a 100644 --- a/nixpkgs/nixos/modules/services/networking/xrdp.nix +++ b/nixpkgs/nixos/modules/services/networking/xrdp.nix @@ -4,14 +4,17 @@ with lib; let cfg = config.services.xrdp; + confDir = pkgs.runCommand "xrdp.conf" { preferLocalBuild = true; } '' - mkdir $out + mkdir -p $out - cp ${cfg.package}/etc/xrdp/{km-*,xrdp,sesman,xrdp_keyboard}.ini $out + cp -r ${cfg.package}/etc/xrdp/* $out + chmod -R +w $out cat > $out/startwm.sh <<EOF #!/bin/sh . /etc/profile + ${lib.optionalString cfg.audio.enable "${cfg.audio.package}/libexec/pulsaudio-xrdp-module/pulseaudio_xrdp_init"} ${cfg.defaultWindowManager} EOF chmod +x $out/startwm.sh @@ -25,13 +28,17 @@ let substituteInPlace $out/sesman.ini \ --replace LogFile=xrdp-sesman.log LogFile=/dev/null \ - --replace EnableSyslog=1 EnableSyslog=0 + --replace EnableSyslog=1 EnableSyslog=0 \ + --replace startwm.sh $out/startwm.sh \ + --replace reconnectwm.sh $out/reconnectwm.sh \ # Ensure that clipboard works for non-ASCII characters sed -i -e '/.*SessionVariables.*/ a\ LANG=${config.i18n.defaultLocale}\ LOCALE_ARCHIVE=${config.i18n.glibcLocales}/lib/locale/locale-archive ' $out/sesman.ini + + ${cfg.extraConfDirCommands} ''; in { @@ -44,7 +51,12 @@ in enable = mkEnableOption (lib.mdDoc "xrdp, the Remote Desktop Protocol server"); - package = mkPackageOption pkgs "xrdp" { }; + package = mkPackageOptionMD pkgs "xrdp" { }; + + audio = { + enable = mkEnableOption (lib.mdDoc "audio support for xrdp sessions. So far it only works with PulseAudio sessions on the server side. No PipeWire support yet"); + package = mkPackageOptionMD pkgs "pulseaudio-module-xrdp" {}; + }; port = mkOption { type = types.port; @@ -93,86 +105,117 @@ in confDir = mkOption { type = types.path; default = confDir; - defaultText = literalMD "generated from configuration"; - description = lib.mdDoc "The location of the config files for xrdp."; + internal = true; + description = lib.mdDoc '' + Configuration directory of xrdp and sesman. + + Changes to this must be made through extraConfDirCommands. + ''; + readOnly = true; + }; + + extraConfDirCommands = mkOption { + type = types.str; + default = ""; + description = lib.mdDoc '' + Extra commands to run on the default confDir derivation. + ''; + example = '' + substituteInPlace $out/sesman.ini \ + --replace LogLevel=INFO LogLevel=DEBUG \ + --replace LogFile=/dev/null LogFile=/var/log/xrdp.log + ''; }; }; }; - ###### implementation - config = mkIf cfg.enable { + config = lib.mkMerge [ + (mkIf cfg.audio.enable { + environment.systemPackages = [ cfg.audio.package ]; # needed for autostart - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; + hardware.pulseaudio.extraModules = [ cfg.audio.package ]; + }) - # xrdp can run X11 program even if "services.xserver.enable = false" - xdg = { - autostart.enable = true; - menus.enable = true; - mime.enable = true; - icons.enable = true; - }; + (mkIf cfg.enable { - fonts.enableDefaultPackages = mkDefault true; - - systemd = { - services.xrdp = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - description = "xrdp daemon"; - requires = [ "xrdp-sesman.service" ]; - preStart = '' - # prepare directory for unix sockets (the sockets will be owned by loggedinuser:xrdp) - mkdir -p /tmp/.xrdp || true - chown xrdp:xrdp /tmp/.xrdp - chmod 3777 /tmp/.xrdp - - # generate a self-signed certificate - if [ ! -s ${cfg.sslCert} -o ! -s ${cfg.sslKey} ]; then - mkdir -p $(dirname ${cfg.sslCert}) || true - mkdir -p $(dirname ${cfg.sslKey}) || true - ${pkgs.openssl.bin}/bin/openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days 365 \ - -subj /C=US/ST=CA/L=Sunnyvale/O=xrdp/CN=www.xrdp.org \ - -config ${cfg.package}/share/xrdp/openssl.conf \ - -keyout ${cfg.sslKey} -out ${cfg.sslCert} - chown root:xrdp ${cfg.sslKey} ${cfg.sslCert} - chmod 440 ${cfg.sslKey} ${cfg.sslCert} - fi - if [ ! -s /run/xrdp/rsakeys.ini ]; then - mkdir -p /run/xrdp - ${cfg.package}/bin/xrdp-keygen xrdp /run/xrdp/rsakeys.ini - fi - ''; - serviceConfig = { - User = "xrdp"; - Group = "xrdp"; - PermissionsStartOnly = true; - ExecStart = "${cfg.package}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${cfg.confDir}/xrdp.ini"; - }; + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; + + # xrdp can run X11 program even if "services.xserver.enable = false" + xdg = { + autostart.enable = true; + menus.enable = true; + mime.enable = true; + icons.enable = true; }; - services.xrdp-sesman = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - description = "xrdp session manager"; - restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children - serviceConfig = { - ExecStart = "${cfg.package}/bin/xrdp-sesman --nodaemon --config ${cfg.confDir}/sesman.ini"; - ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; + fonts.enableDefaultPackages = mkDefault true; + + environment.etc."xrdp".source = "${confDir}/*"; + + systemd = { + services.xrdp = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "xrdp daemon"; + requires = [ "xrdp-sesman.service" ]; + preStart = '' + # prepare directory for unix sockets (the sockets will be owned by loggedinuser:xrdp) + mkdir -p /tmp/.xrdp || true + chown xrdp:xrdp /tmp/.xrdp + chmod 3777 /tmp/.xrdp + + # generate a self-signed certificate + if [ ! -s ${cfg.sslCert} -o ! -s ${cfg.sslKey} ]; then + mkdir -p $(dirname ${cfg.sslCert}) || true + mkdir -p $(dirname ${cfg.sslKey}) || true + ${lib.getExe pkgs.openssl} req -x509 -newkey rsa:2048 -sha256 -nodes -days 365 \ + -subj /C=US/ST=CA/L=Sunnyvale/O=xrdp/CN=www.xrdp.org \ + -config ${cfg.package}/share/xrdp/openssl.conf \ + -keyout ${cfg.sslKey} -out ${cfg.sslCert} + chown root:xrdp ${cfg.sslKey} ${cfg.sslCert} + chmod 440 ${cfg.sslKey} ${cfg.sslCert} + fi + if [ ! -s /run/xrdp/rsakeys.ini ]; then + mkdir -p /run/xrdp + ${pkgs.xrdp}/bin/xrdp-keygen xrdp /run/xrdp/rsakeys.ini + fi + ''; + serviceConfig = { + User = "xrdp"; + Group = "xrdp"; + PermissionsStartOnly = true; + ExecStart = "${pkgs.xrdp}/bin/xrdp --nodaemon --port ${toString cfg.port} --config ${confDir}/xrdp.ini"; + }; + }; + + services.xrdp-sesman = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "xrdp session manager"; + restartIfChanged = false; # do not restart on "nixos-rebuild switch". like "display-manager", it can have many interactive programs as children + serviceConfig = { + ExecStart = "${pkgs.xrdp}/bin/xrdp-sesman --nodaemon --config ${confDir}/sesman.ini"; + ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; + }; }; + }; - }; + users.users.xrdp = { + description = "xrdp daemon user"; + isSystemUser = true; + group = "xrdp"; + }; + users.groups.xrdp = {}; - users.users.xrdp = { - description = "xrdp daemon user"; - isSystemUser = true; - group = "xrdp"; - }; - users.groups.xrdp = {}; + security.pam.services.xrdp-sesman = { + allowNullPassword = true; + startSession = true; + }; - security.pam.services.xrdp-sesman = { allowNullPassword = true; startSession = true; }; - }; + }) + ]; } diff --git a/nixpkgs/nixos/modules/services/printing/cupsd.nix b/nixpkgs/nixos/modules/services/printing/cupsd.nix index 3a2744303474..1f044384a5b8 100644 --- a/nixpkgs/nixos/modules/services/printing/cupsd.nix +++ b/nixpkgs/nixos/modules/services/printing/cupsd.nix @@ -4,9 +4,10 @@ with lib; let - inherit (pkgs) cups cups-pk-helper cups-filters xdg-utils; + inherit (pkgs) cups-pk-helper cups-filters xdg-utils; cfg = config.services.printing; + cups = cfg.package; avahiEnabled = config.services.avahi.enable; polkitEnabled = config.security.polkit.enable; @@ -140,6 +141,8 @@ in ''; }; + package = lib.mkPackageOption pkgs "cups" {}; + stateless = mkOption { type = types.bool; default = false; diff --git a/nixpkgs/nixos/modules/services/security/vaultwarden/backup.sh b/nixpkgs/nixos/modules/services/security/vaultwarden/backup.sh index 2a3de0ab1dee..7668da5bc88f 100644 --- a/nixpkgs/nixos/modules/services/security/vaultwarden/backup.sh +++ b/nixpkgs/nixos/modules/services/security/vaultwarden/backup.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # Based on: https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault -if ! mkdir -p "$BACKUP_FOLDER"; then - echo "Could not create backup folder '$BACKUP_FOLDER'" >&2 +if [ ! -d "$BACKUP_FOLDER" ]; then + echo "Backup folder '$BACKUP_FOLDER' does not exist" >&2 exit 1 fi diff --git a/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix b/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix index 14bbfa95a9ca..470db735bf64 100644 --- a/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix +++ b/nixpkgs/nixos/modules/services/security/vaultwarden/default.nix @@ -55,6 +55,7 @@ in { description = lib.mdDoc '' The directory under which vaultwarden will backup its persistent data. ''; + example = "/var/backup/vaultwarden"; }; config = mkOption { @@ -230,6 +231,13 @@ in { }; wantedBy = [ "multi-user.target" ]; }; + + systemd.tmpfiles.settings = mkIf (cfg.backupDir != null) { + "10-vaultwarden".${cfg.backupDir}.d = { + inherit user group; + mode = "0770"; + }; + }; }; # uses attributes of the linked package diff --git a/nixpkgs/nixos/modules/services/system/kerberos/default.nix b/nixpkgs/nixos/modules/services/system/kerberos/default.nix index 4ed48e463741..486d4b49c195 100644 --- a/nixpkgs/nixos/modules/services/system/kerberos/default.nix +++ b/nixpkgs/nixos/modules/services/system/kerberos/default.nix @@ -3,7 +3,7 @@ let inherit (lib) mkOption mkIf types length attrNames; cfg = config.services.kerberos_server; - kerberos = config.krb5.kerberos; + kerberos = config.security.krb5.package; aclEntry = { options = { diff --git a/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix b/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix index 837c59caa562..ecafc9276670 100644 --- a/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix +++ b/nixpkgs/nixos/modules/services/system/kerberos/heimdal.nix @@ -4,7 +4,7 @@ let inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs mapAttrsToList; cfg = config.services.kerberos_server; - kerberos = config.krb5.kerberos; + kerberos = config.security.krb5.package; stateDir = "/var/heimdal"; aclFiles = mapAttrs (name: {acl, ...}: pkgs.writeText "${name}.acl" (concatMapStrings (( @@ -35,7 +35,7 @@ in mkdir -m 0755 -p ${stateDir} ''; serviceConfig.ExecStart = - "${kerberos}/libexec/heimdal/kadmind --config-file=/etc/heimdal-kdc/kdc.conf"; + "${kerberos}/libexec/kadmind --config-file=/etc/heimdal-kdc/kdc.conf"; restartTriggers = [ kdcConfFile ]; }; @@ -46,7 +46,7 @@ in mkdir -m 0755 -p ${stateDir} ''; serviceConfig.ExecStart = - "${kerberos}/libexec/heimdal/kdc --config-file=/etc/heimdal-kdc/kdc.conf"; + "${kerberos}/libexec/kdc --config-file=/etc/heimdal-kdc/kdc.conf"; restartTriggers = [ kdcConfFile ]; }; @@ -56,7 +56,7 @@ in preStart = '' mkdir -m 0755 -p ${stateDir} ''; - serviceConfig.ExecStart = "${kerberos}/libexec/heimdal/kpasswdd"; + serviceConfig.ExecStart = "${kerberos}/libexec/kpasswdd"; restartTriggers = [ kdcConfFile ]; }; diff --git a/nixpkgs/nixos/modules/services/system/kerberos/mit.nix b/nixpkgs/nixos/modules/services/system/kerberos/mit.nix index 112000140453..a654bd1fe7e1 100644 --- a/nixpkgs/nixos/modules/services/system/kerberos/mit.nix +++ b/nixpkgs/nixos/modules/services/system/kerberos/mit.nix @@ -4,7 +4,7 @@ let inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList mapAttrs mapAttrsToList; cfg = config.services.kerberos_server; - kerberos = config.krb5.kerberos; + kerberos = config.security.krb5.package; stateDir = "/var/lib/krb5kdc"; PIDFile = "/run/kdc.pid"; aclMap = { diff --git a/nixpkgs/nixos/modules/services/web-apps/c2fmzq-server.nix b/nixpkgs/nixos/modules/services/web-apps/c2fmzq-server.nix index 2749c2a5a87a..87938fe160e1 100644 --- a/nixpkgs/nixos/modules/services/web-apps/c2fmzq-server.nix +++ b/nixpkgs/nixos/modules/services/web-apps/c2fmzq-server.nix @@ -6,8 +6,12 @@ let cfg = config.services.c2fmzq-server; argsFormat = { - type = with lib.types; nullOr (oneOf [ bool int str ]); - generate = lib.cli.toGNUCommandLineShell { }; + type = with lib.types; attrsOf (nullOr (oneOf [ bool int str ])); + generate = lib.cli.toGNUCommandLineShell { + mkBool = k: v: [ + "--${k}=${if v then "true" else "false"}" + ]; + }; }; in { options.services.c2fmzq-server = { diff --git a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix index 1df1cbf9f0e1..256ab3229ea6 100644 --- a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix +++ b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix @@ -122,62 +122,8 @@ let }; }; - # The current implementations of `doRename`, `mkRenamedOptionModule` do not provide the full options path when used with submodules. - # They would only show `settings.useacl' instead of `services.dokuwiki.sites."site1.local".settings.useacl' - # The partial re-implementation of these functions is done to help users in debugging by showing the full path. - mkRenamed = from: to: { config, options, name, ... }: let - pathPrefix = [ "services" "dokuwiki" "sites" name ]; - fromPath = pathPrefix ++ from; - fromOpt = getAttrFromPath from options; - toOp = getAttrsFromPath to config; - toPath = pathPrefix ++ to; - in { - options = setAttrByPath from (mkOption { - visible = false; - description = lib.mdDoc "Alias of {option}${showOption toPath}"; - apply = x: builtins.trace "Obsolete option `${showOption fromPath}' is used. It was renamed to ${showOption toPath}" toOp; - }); - config = mkMerge [ - { - warnings = optional fromOpt.isDefined - "The option `${showOption fromPath}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption toPath}'."; - } - (lib.modules.mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt) - ]; - }; - siteOpts = { options, config, lib, name, ... }: { - imports = [ - (mkRenamed [ "aclUse" ] [ "settings" "useacl" ]) - (mkRenamed [ "superUser" ] [ "settings" "superuser" ]) - (mkRenamed [ "disableActions" ] [ "settings" "disableactions" ]) - ({ config, options, ... }: let - showPath = suffix: lib.options.showOption ([ "services" "dokuwiki" "sites" name ] ++ suffix); - replaceExtraConfig = "Please use `${showPath ["settings"]}' to pass structured settings instead."; - ecOpt = options.extraConfig; - ecPath = showPath [ "extraConfig" ]; - in { - options.extraConfig = mkOption { - visible = false; - apply = x: throw "The option ${ecPath} can no longer be used since it's been removed.\n${replaceExtraConfig}"; - }; - config.assertions = [ - { - assertion = !ecOpt.isDefined; - message = "The option definition `${ecPath}' in ${showFiles ecOpt.files} no longer has any effect; please remove it.\n${replaceExtraConfig}"; - } - { - assertion = config.mergedConfig.useacl -> (config.acl != null || config.aclFile != null); - message = "Either ${showPath [ "acl" ]} or ${showPath [ "aclFile" ]} is mandatory if ${showPath [ "settings" "useacl" ]} is true"; - } - { - assertion = config.usersFile != null -> config.mergedConfig.useacl != false; - message = "${showPath [ "settings" "useacl" ]} is required when ${showPath [ "usersFile" ]} is set (Currently defined as `${config.usersFile}' in ${showFiles options.usersFile.files})."; - } - ]; - }) - ]; options = { enable = mkEnableOption (lib.mdDoc "DokuWiki web application"); @@ -392,21 +338,6 @@ let ''; }; - # Required for the mkRenamedOptionModule - # TODO: Remove me once https://github.com/NixOS/nixpkgs/issues/96006 is fixed - # or we don't have any more notes about the removal of extraConfig, ... - warnings = mkOption { - type = types.listOf types.unspecified; - default = [ ]; - visible = false; - internal = true; - }; - assertions = mkOption { - type = types.listOf types.unspecified; - default = [ ]; - visible = false; - internal = true; - }; }; }; in @@ -440,10 +371,6 @@ in # implementation config = mkIf (eachSite != {}) (mkMerge [{ - warnings = flatten (mapAttrsToList (_: cfg: cfg.warnings) eachSite); - - assertions = flatten (mapAttrsToList (_: cfg: cfg.assertions) eachSite); - services.phpfpm.pools = mapAttrs' (hostName: cfg: ( nameValuePair "dokuwiki-${hostName}" { inherit user; diff --git a/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix b/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix index 429520470a0d..618bd848ebcb 100644 --- a/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix +++ b/nixpkgs/nixos/modules/services/web-apps/invoiceplane.nix @@ -252,11 +252,11 @@ in }; options.webserver = mkOption { - type = types.enum [ "caddy" ]; + type = types.enum [ "caddy" "nginx" ]; default = "caddy"; + example = "nginx"; description = lib.mdDoc '' - Which webserver to use for virtual host management. Currently only - caddy is supported. + Which webserver to use for virtual host management. ''; }; }; @@ -390,5 +390,39 @@ in }; }) + (mkIf (cfg.webserver == "nginx") { + services.nginx = { + enable = true; + virtualHosts = mapAttrs' (hostName: cfg: ( + nameValuePair hostName { + root = pkg hostName cfg; + extraConfig = '' + index index.php index.html index.htm; + + if (!-e $request_filename){ + rewrite ^(.*)$ /index.php break; + } + ''; + + locations = { + "/setup".extraConfig = '' + rewrite ^(.*)$ http://${hostName}/ redirect; + ''; + + "~ .php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass unix:${config.services.phpfpm.pools."invoiceplane-${hostName}".socket}; + include ${config.services.nginx.package}/conf/fastcgi_params; + include ${config.services.nginx.package}/conf/fastcgi.conf; + ''; + }; + }; + } + )) eachSite; + }; + }) + ]); } diff --git a/nixpkgs/nixos/modules/services/web-apps/miniflux.nix b/nixpkgs/nixos/modules/services/web-apps/miniflux.nix index a500008fc792..1a5b7d0c24e9 100644 --- a/nixpkgs/nixos/modules/services/web-apps/miniflux.nix +++ b/nixpkgs/nixos/modules/services/web-apps/miniflux.nix @@ -21,10 +21,10 @@ in package = mkPackageOption pkgs "miniflux" { }; config = mkOption { - type = types.attrsOf types.str; + type = with types; attrsOf (oneOf [ str int ]); example = literalExpression '' { - CLEANUP_FREQUENCY = "48"; + CLEANUP_FREQUENCY = 48; LISTEN_ADDR = "localhost:8080"; } ''; @@ -51,12 +51,11 @@ in }; config = mkIf cfg.enable { - services.miniflux.config = { LISTEN_ADDR = mkDefault defaultAddress; DATABASE_URL = "user=miniflux host=/run/postgresql dbname=miniflux"; - RUN_MIGRATIONS = "1"; - CREATE_ADMIN = "1"; + RUN_MIGRATIONS = 1; + CREATE_ADMIN = 1; }; services.postgresql = { @@ -90,7 +89,7 @@ in User = "miniflux"; DynamicUser = true; RuntimeDirectory = "miniflux"; - RuntimeDirectoryMode = "0700"; + RuntimeDirectoryMode = "0750"; EnvironmentFile = cfg.adminCredentialsFile; # Hardening CapabilityBoundingSet = [ "" ]; @@ -117,7 +116,7 @@ in UMask = "0077"; }; - environment = cfg.config; + environment = lib.mapAttrs (_: toString) cfg.config; }; environment.systemPackages = [ cfg.package ]; diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix index 39f4e8f11620..38c51251aac1 100644 --- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix @@ -107,31 +107,10 @@ let in { imports = [ - (mkRemovedOptionModule [ "services" "nextcloud" "config" "adminpass" ] '' - Please use `services.nextcloud.config.adminpassFile' instead! - '') - (mkRemovedOptionModule [ "services" "nextcloud" "config" "dbpass" ] '' - Please use `services.nextcloud.config.dbpassFile' instead! - '') - (mkRemovedOptionModule [ "services" "nextcloud" "nginx" "enable" ] '' - The nextcloud module supports `nginx` as reverse-proxy by default and doesn't - support other reverse-proxies officially. - - However it's possible to use an alternative reverse-proxy by - - * disabling nginx - * setting `listen.owner` & `listen.group` in the phpfpm-pool to a different value - - Further details about this can be found in the `Nextcloud`-section of the NixOS-manual - (which can be opened e.g. by running `nixos-help`). - '') (mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] '' This option has no effect since there's no supported Nextcloud version packaged here using OpenSSL for RC4 SSE. '') - (mkRemovedOptionModule [ "services" "nextcloud" "disableImagemagick" ] '' - Use services.nextcloud.enableImagemagick instead. - '') (mkRemovedOptionModule [ "services" "nextcloud" "config" "dbport" ] '' Add port to services.nextcloud.config.dbhost instead. '') diff --git a/nixpkgs/nixos/modules/services/web-apps/outline.nix b/nixpkgs/nixos/modules/services/web-apps/outline.nix index d97b45d62418..702755dfa2ab 100644 --- a/nixpkgs/nixos/modules/services/web-apps/outline.nix +++ b/nixpkgs/nixos/modules/services/web-apps/outline.nix @@ -586,6 +586,37 @@ in ensureDatabases = [ "outline" ]; }; + # Outline is unable to create the uuid-ossp extension when using postgresql 12, in later version this + # extension can be created without superuser permission. This services therefor this extension before + # outline starts and postgresql 12 is using on the host. + # + # Can be removed after postgresql 12 is dropped from nixos. + systemd.services.outline-postgresql = + let + pgsql = config.services.postgresql; + in + lib.mkIf (cfg.databaseUrl == "local" && pgsql.package == pkgs.postgresql_12) { + after = [ "postgresql.service" ]; + bindsTo = [ "postgresql.service" ]; + wantedBy = [ "outline.service" ]; + partOf = [ "outline.service" ]; + path = [ + pgsql.package + ]; + script = '' + set -o errexit -o pipefail -o nounset -o errtrace + shopt -s inherit_errexit + + psql outline -tAc 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"' + ''; + + serviceConfig = { + User = pgsql.superUser; + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + services.redis.servers.outline = lib.mkIf (cfg.redisUrl == "local") { enable = true; user = config.services.outline.user; diff --git a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix index 002d6683b2ed..2f7306309d69 100644 --- a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix +++ b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix @@ -174,22 +174,22 @@ let List of path(s) to respective language(s) which are copied from the 'languages' directory. ''; example = literalExpression '' - [( + [ # Let's package the German language. # For other languages try to replace language and country code in the download URL with your desired one. # Reference https://translate.wordpress.org for available translations and # codes. - language-de = pkgs.stdenv.mkDerivation { + (pkgs.stdenv.mkDerivation { name = "language-de"; src = pkgs.fetchurl { url = "https://de.wordpress.org/wordpress-''${pkgs.wordpress.version}-de_DE.tar.gz"; # Name is required to invalidate the hash when wordpress is updated - name = "wordpress-''${pkgs.wordpress.version}-language-de" + name = "wordpress-''${pkgs.wordpress.version}-language-de"; sha256 = "sha256-dlas0rXTSV4JAl8f/UyMbig57yURRYRhTMtJwF9g8h0="; }; installPhase = "mkdir -p $out; cp -r ./wp-content/languages/* $out/"; - }; - )]; + }) + ]; ''; }; diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix index 1285c2bbb916..6799de6c7d96 100644 --- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix @@ -334,8 +334,8 @@ let + optionalString vhost.default "default_server " + optionalString vhost.reuseport "reuseport " + optionalString (extraParameters != []) (concatStringsSep " " - (let inCompatibleParameters = [ "ssl" "proxy_protocol" "http2" ]; - isCompatibleParameter = param: !(any (p: p == param) inCompatibleParameters); + (let inCompatibleParameters = [ "accept_filter" "backlog" "deferred" "fastopen" "http2" "proxy_protocol" "so_keepalive" "ssl" ]; + isCompatibleParameter = param: !(any (p: lib.hasPrefix p param) inCompatibleParameters); in filter isCompatibleParameter extraParameters)) + ";")) + " @@ -408,12 +408,6 @@ let ssl_conf_command Options KTLS; ''} - ${optionalString (hasSSL && vhost.quic && vhost.http3) - # Advertise that HTTP/3 is available - '' - add_header Alt-Svc 'h3=":$server_port"; ma=86400'; - ''} - ${mkBasicAuth vhostName vhost} ${optionalString (vhost.root != null) "root ${vhost.root};"} @@ -475,7 +469,7 @@ let mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix; - oldHTTP2 = versionOlder cfg.package.version "1.25.1"; + oldHTTP2 = (versionOlder cfg.package.version "1.25.1" && !(cfg.package.pname == "angie" || cfg.package.pname == "angieQuic")); in { diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix index 64a95afab9f4..ea98439d3823 100644 --- a/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixpkgs/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -235,9 +235,9 @@ with lib; which can be achieved by setting `services.nginx.package = pkgs.nginxQuic;` and activate the QUIC transport protocol `services.nginx.virtualHosts.<name>.quic = true;`. - Note that HTTP/3 support is experimental and - *not* yet recommended for production. + Note that HTTP/3 support is experimental and *not* yet recommended for production. Read more at https://quic.nginx.org/ + HTTP/3 availability must be manually advertised, preferably in each location block. ''; }; @@ -250,8 +250,7 @@ with lib; which can be achieved by setting `services.nginx.package = pkgs.nginxQuic;` and activate the QUIC transport protocol `services.nginx.virtualHosts.<name>.quic = true;`. - Note that special application protocol support is experimental and - *not* yet recommended for production. + Note that special application protocol support is experimental and *not* yet recommended for production. Read more at https://quic.nginx.org/ ''; }; diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix index 20eca7746447..2cf9bc2eac37 100644 --- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix +++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome.nix @@ -449,7 +449,6 @@ in gnome-color-manager gnome-control-center gnome-shell-extensions - gnome-themes-extra pkgs.gnome-tour # GNOME Shell detects the .desktop file on first log-in. pkgs.gnome-user-docs pkgs.orca diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix index e0227f93e2f2..fc9de2500ba4 100644 --- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -26,10 +26,8 @@ let emptyValue.value = {}; }; - libsForQt5 = pkgs.plasma5Packages; - inherit (libsForQt5) kdeGear kdeFrameworks plasma5; inherit (lib) - getBin optionalAttrs optionalString literalExpression + getBin optionalAttrs literalExpression mkRemovedOptionModule mkRenamedOptionModule mkDefault mkIf mkMerge mkOption mkPackageOption types; @@ -65,7 +63,7 @@ let # recognize that software that has been removed. rm -fv $HOME/.cache/ksycoca* - ${libsForQt5.kservice}/bin/kbuildsycoca5 + ${pkgs.plasma5Packages.kservice}/bin/kbuildsycoca5 ''; set_XDG_CONFIG_HOME = '' @@ -176,20 +174,19 @@ in owner = "root"; group = "root"; capabilities = "cap_sys_nice+ep"; - source = "${getBin plasma5.kwin}/bin/kwin_wayland"; + source = "${getBin pkgs.plasma5Packages.kwin}/bin/kwin_wayland"; }; } // optionalAttrs (!cfg.runUsingSystemd) { start_kdeinit = { setuid = true; owner = "root"; group = "root"; - source = "${getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit"; + source = "${getBin pkgs.plasma5Packages.kinit}/libexec/kf5/start_kdeinit"; }; }; environment.systemPackages = - with libsForQt5; - with plasma5; with kdeGear; with kdeFrameworks; + with pkgs.plasma5Packages; let requiredPackages = [ frameworkintegration @@ -284,8 +281,8 @@ in ++ utils.removePackagesByName optionalPackages config.environment.plasma5.excludePackages # Phonon audio backend - ++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer - ++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc + ++ lib.optional (cfg.phononBackend == "gstreamer") pkgs.plasma5Packages.phonon-backend-gstreamer + ++ lib.optional (cfg.phononBackend == "vlc") pkgs.plasma5Packages.phonon-backend-vlc # Optional hardware support features ++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt pkgs.openobex pkgs.obexftp ] @@ -301,7 +298,7 @@ in # Extra services for D-Bus activation services.dbus.packages = [ - plasma5.kactivitymanagerd + pkgs.plasma5Packages.kactivitymanagerd ]; environment.pathsToLink = [ @@ -334,7 +331,7 @@ in serif = [ "Noto Serif" ]; }; - programs.ssh.askPassword = mkDefault "${plasma5.ksshaskpass.out}/bin/ksshaskpass"; + programs.ssh.askPassword = mkDefault "${pkgs.plasma5Packages.ksshaskpass.out}/bin/ksshaskpass"; # Enable helpful DBus services. services.accounts-daemon.enable = true; @@ -372,8 +369,8 @@ in }; xdg.portal.enable = true; - xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ]; - xdg.portal.configPackages = mkDefault [ plasma5.xdg-desktop-portal-kde ]; + xdg.portal.extraPortals = [ pkgs.plasma5Packages.xdg-desktop-portal-kde ]; + xdg.portal.configPackages = mkDefault [ pkgs.plasma5Packages.xdg-desktop-portal-kde ]; # xdg-desktop-portal-kde expects PipeWire to be running. # This does not, by default, replace PulseAudio. services.pipewire.enable = mkDefault true; @@ -404,15 +401,14 @@ in '' ]; - services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-workspace ]; + services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-workspace ]; # Default to be `plasma` (X11) instead of `plasmawayland`, since plasma wayland currently has # many tiny bugs. # See: https://github.com/NixOS/nixpkgs/issues/143272 services.xserver.displayManager.defaultSession = mkDefault "plasma"; environment.systemPackages = - with libsForQt5; - with plasma5; with kdeGear; with kdeFrameworks; + with pkgs.plasma5Packages; let requiredPackages = [ ksystemstats @@ -448,7 +444,7 @@ in script = '' ${set_XDG_CONFIG_HOME} - ${kdeFrameworks.kconfig}/bin/kwriteconfig5 \ + ${pkgs.plasma5Packages.kconfig}/bin/kwriteconfig5 \ --file startkderc --group General --key systemdBoot ${lib.boolToString cfg.runUsingSystemd} ''; }; @@ -476,8 +472,7 @@ in ]; environment.systemPackages = - with libsForQt5; - with plasma5; with kdeApplications; with kdeFrameworks; + with pkgs.plasma5Packages; [ # Basic packages without which Plasma Mobile fails to work properly. plasma-mobile @@ -536,7 +531,7 @@ in }; }; - services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-mobile ]; + services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-mobile ]; }) # Plasma Bigscreen diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix index 16a7ff1a4bd5..3e2d5780a5cb 100644 --- a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix +++ b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix @@ -514,7 +514,7 @@ in # Make xsessions and wayland sessions available in XDG_DATA_DIRS # as some programs have behavior that depends on them being present - environment.sessionVariables.XDG_DATA_DIRS = [ + environment.sessionVariables.XDG_DATA_DIRS = lib.mkIf (cfg.displayManager.sessionPackages != [ ]) [ "${cfg.displayManager.sessionData.desktops}/share" ]; }; diff --git a/nixpkgs/nixos/modules/services/x11/xserver.nix b/nixpkgs/nixos/modules/services/x11/xserver.nix index 4a8f2f61caaf..36f25d5547ca 100644 --- a/nixpkgs/nixos/modules/services/x11/xserver.nix +++ b/nixpkgs/nixos/modules/services/x11/xserver.nix @@ -804,14 +804,14 @@ in ]; system.checks = singleton (pkgs.runCommand "xkb-validated" { - inherit (cfg.xkb) model layout variant options; + inherit (cfg.xkb) dir model layout variant options; nativeBuildInputs = with pkgs.buildPackages; [ xkbvalidate ]; preferLocalBuild = true; } '' ${optionalString (config.environment.sessionVariables ? XKB_CONFIG_ROOT) "export XKB_CONFIG_ROOT=${config.environment.sessionVariables.XKB_CONFIG_ROOT}" } - xkbvalidate "$model" "$layout" "$variant" "$options" + XKB_CONFIG_ROOT="$dir" xkbvalidate "$model" "$layout" "$variant" "$options" touch "$out" ''); diff --git a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl index e2f66a287bc4..ba45231465fb 100755 --- a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl @@ -889,9 +889,15 @@ while (my $f = <$list_active_users>) { close($list_active_users) || die("Unable to close the file handle to loginctl"); -# Set the new tmpfiles -print STDERR "setting up tmpfiles\n"; -system("$new_systemd/bin/systemd-tmpfiles", "--create", "--remove", "--exclude-prefix=/dev") == 0 or $res = 3; +# Restart sysinit-reactivation.target. +# This target only exists to restart services ordered before sysinit.target. We +# cannot use X-StopOnReconfiguration to restart sysinit.target because then ALL +# services of the system would be restarted since all normal services have a +# default dependency on sysinit.target. sysinit-reactivation.target ensures +# that services ordered BEFORE sysinit.target get re-started in the correct +# order. Ordering between these services is respected. +print STDERR "restarting sysinit-reactivation.target\n"; +system("$new_systemd/bin/systemctl", "restart", "sysinit-reactivation.target") == 0 or $res = 4; # Before reloading we need to ensure that the units are still active. They may have been # deactivated because one of their requirements got stopped. If they are inactive diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix index 87333999313e..46c3f66f02dc 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd.nix @@ -451,6 +451,21 @@ in cfg.services ); + assertions = concatLists ( + mapAttrsToList + (name: service: + map (message: { + assertion = false; + inherit message; + }) (concatLists [ + (optional ((builtins.elem "network-interfaces.target" service.after) || (builtins.elem "network-interfaces.target" service.wants)) + "Service '${name}.service' is using the deprecated target network-interfaces.target, which no longer exists. Using network.target is recommended instead." + ) + ]) + ) + cfg.services + ); + system.build.units = cfg.units; system.nssModules = [ cfg.package.out ]; @@ -554,6 +569,13 @@ in unitConfig.X-StopOnReconfiguration = true; }; + # This target only exists so that services ordered before sysinit.target + # are restarted in the correct order, notably BEFORE the other services, + # when switching configurations. + systemd.targets.sysinit-reactivation = { + description = "Reactivate sysinit units"; + }; + systemd.units = mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services diff --git a/nixpkgs/nixos/modules/system/boot/systemd/journald-gateway.nix b/nixpkgs/nixos/modules/system/boot/systemd/journald-gateway.nix new file mode 100644 index 000000000000..854965282344 --- /dev/null +++ b/nixpkgs/nixos/modules/system/boot/systemd/journald-gateway.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.journald.gateway; + + cliArgs = lib.cli.toGNUCommandLineShell { } { + # If either of these are null / false, they are not passed in the command-line + inherit (cfg) cert key trust system user merge; + }; +in +{ + meta.maintainers = [ lib.maintainers.raitobezarius ]; + options.services.journald.gateway = { + enable = lib.mkEnableOption "the HTTP gateway to the journal"; + + port = lib.mkOption { + default = 19531; + type = lib.types.port; + description = '' + The port to listen to. + ''; + }; + + cert = lib.mkOption { + default = null; + type = with lib.types; nullOr str; + description = lib.mdDoc '' + The path to a file or `AF_UNIX` stream socket to read the server + certificate from. + + The certificate must be in PEM format. This option switches + `systemd-journal-gatewayd` into HTTPS mode and must be used together + with {option}`services.journald.gateway.key`. + ''; + }; + + key = lib.mkOption { + default = null; + type = with lib.types; nullOr str; + description = lib.mdDoc '' + Specify the path to a file or `AF_UNIX` stream socket to read the + secret server key corresponding to the certificate specified with + {option}`services.journald.gateway.cert` from. + + The key must be in PEM format. + + This key should not be world-readable, and must be readably by the + `systemd-journal-gateway` user. + ''; + }; + + trust = lib.mkOption { + default = null; + type = with lib.types; nullOr str; + description = lib.mdDoc '' + Specify the path to a file or `AF_UNIX` stream socket to read a CA + certificate from. + + The certificate must be in PEM format. + + Setting this option enforces client certificate checking. + ''; + }; + + system = lib.mkOption { + default = true; + type = lib.types.bool; + description = lib.mdDoc '' + Serve entries from system services and the kernel. + + This has the same meaning as `--system` for {manpage}`journalctl(1)`. + ''; + }; + + user = lib.mkOption { + default = true; + type = lib.types.bool; + description = lib.mdDoc '' + Serve entries from services for the current user. + + This has the same meaning as `--user` for {manpage}`journalctl(1)`. + ''; + }; + + merge = lib.mkOption { + default = false; + type = lib.types.bool; + description = lib.mdDoc '' + Serve entries interleaved from all available journals, including other + machines. + + This has the same meaning as `--merge` option for + {manpage}`journalctl(1)`. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + # This prevents the weird case were disabling "system" and "user" + # actually enables both because the cli flags are not present. + assertion = cfg.system || cfg.user; + message = '' + systemd-journal-gatewayd cannot serve neither "system" nor "user" + journals. + ''; + } + ]; + + systemd.additionalUpstreamSystemUnits = [ + "systemd-journal-gatewayd.socket" + "systemd-journal-gatewayd.service" + ]; + + users.users.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway; + users.users.systemd-journal-gateway.group = "systemd-journal-gateway"; + users.groups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway; + + systemd.services.systemd-journal-gatewayd.serviceConfig.ExecStart = [ + # Clear the default command line + "" + "${pkgs.systemd}/lib/systemd/systemd-journal-gatewayd ${cliArgs}" + ]; + + systemd.sockets.systemd-journal-gatewayd = { + wantedBy = [ "sockets.target" ]; + listenStreams = [ + # Clear the default port + "" + (toString cfg.port) + ]; + }; + }; +} diff --git a/nixpkgs/nixos/modules/system/boot/systemd/journald-remote.nix b/nixpkgs/nixos/modules/system/boot/systemd/journald-remote.nix new file mode 100644 index 000000000000..57a0a133e1c6 --- /dev/null +++ b/nixpkgs/nixos/modules/system/boot/systemd/journald-remote.nix @@ -0,0 +1,163 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.journald.remote; + format = pkgs.formats.systemd; + + cliArgs = lib.cli.toGNUCommandLineShell { } { + inherit (cfg) output; + # "-3" specifies the file descriptor from the .socket unit. + "listen-${cfg.listen}" = "-3"; + }; +in +{ + meta.maintainers = [ lib.maintainers.raitobezarius ]; + options.services.journald.remote = { + enable = lib.mkEnableOption "receiving systemd journals from the network"; + + listen = lib.mkOption { + default = "https"; + type = lib.types.enum [ "https" "http" ]; + description = lib.mdDoc '' + Which protocol to listen to. + ''; + }; + + output = lib.mkOption { + default = "/var/log/journal/remote/"; + type = lib.types.str; + description = lib.mdDoc '' + The location of the output journal. + + In case the output file is not specified, journal files will be created + underneath the selected directory. Files will be called + {file}`remote-hostname.journal`, where the `hostname` part is the + escaped hostname of the source endpoint of the connection, or the + numerical address if the hostname cannot be determined. + ''; + }; + + port = lib.mkOption { + default = 19532; + type = lib.types.port; + description = '' + The port to listen to. + + Note that this option is used only if + {option}`services.journald.upload.listen` is configured to be either + "https" or "http". + ''; + }; + + settings = lib.mkOption { + default = { }; + + description = lib.mdDoc '' + Configuration in the journal-remote configuration file. See + {manpage}`journal-remote.conf(5)` for available options. + ''; + + type = lib.types.submodule { + freeformType = format.type; + + options.Remote = { + Seal = lib.mkOption { + default = false; + example = true; + type = lib.types.bool; + description = '' + Periodically sign the data in the journal using Forward Secure + Sealing. + ''; + }; + + SplitMode = lib.mkOption { + default = "host"; + example = "none"; + type = lib.types.enum [ "host" "none" ]; + description = lib.mdDoc '' + With "host", a separate output file is used, based on the + hostname of the other endpoint of a connection. With "none", only + one output journal file is used. + ''; + }; + + ServerKeyFile = lib.mkOption { + default = "/etc/ssl/private/journal-remote.pem"; + type = lib.types.str; + description = lib.mdDoc '' + A path to a SSL secret key file in PEM format. + + Note that due to security reasons, `systemd-journal-remote` will + refuse files from the world-readable `/nix/store`. This file + should be readable by the "" user. + + This option can be used with `listen = "https"`. If the path + refers to an `AF_UNIX` stream socket in the file system a + connection is made to it and the key read from it. + ''; + }; + + ServerCertificateFile = lib.mkOption { + default = "/etc/ssl/certs/journal-remote.pem"; + type = lib.types.str; + description = lib.mdDoc '' + A path to a SSL certificate file in PEM format. + + This option can be used with `listen = "https"`. If the path + refers to an `AF_UNIX` stream socket in the file system a + connection is made to it and the certificate read from it. + ''; + }; + + TrustedCertificateFile = lib.mkOption { + default = "/etc/ssl/ca/trusted.pem"; + type = lib.types.str; + description = lib.mdDoc '' + A path to a SSL CA certificate file in PEM format, or `all`. + + If `all` is set, then client certificate checking will be + disabled. + + This option can be used with `listen = "https"`. If the path + refers to an `AF_UNIX` stream socket in the file system a + connection is made to it and the certificate read from it. + ''; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.additionalUpstreamSystemUnits = [ + "systemd-journal-remote.service" + "systemd-journal-remote.socket" + ]; + + systemd.services.systemd-journal-remote.serviceConfig.ExecStart = [ + # Clear the default command line + "" + "${pkgs.systemd}/lib/systemd/systemd-journal-remote ${cliArgs}" + ]; + + systemd.sockets.systemd-journal-remote = { + wantedBy = [ "sockets.target" ]; + listenStreams = [ + # Clear the default port + "" + (toString cfg.port) + ]; + }; + + # User and group used by systemd-journal-remote.service + users.groups.systemd-journal-remote = { }; + users.users.systemd-journal-remote = { + isSystemUser = true; + group = "systemd-journal-remote"; + }; + + environment.etc."systemd/journal-remote.conf".source = + format.generate "journal-remote.conf" cfg.settings; + }; +} diff --git a/nixpkgs/nixos/modules/system/boot/systemd/journald-upload.nix b/nixpkgs/nixos/modules/system/boot/systemd/journald-upload.nix new file mode 100644 index 000000000000..6421e5fa486f --- /dev/null +++ b/nixpkgs/nixos/modules/system/boot/systemd/journald-upload.nix @@ -0,0 +1,111 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.journald.upload; + format = pkgs.formats.systemd; +in +{ + meta.maintainers = [ lib.maintainers.raitobezarius ]; + options.services.journald.upload = { + enable = lib.mkEnableOption "uploading the systemd journal to a remote server"; + + settings = lib.mkOption { + default = { }; + + description = lib.mdDoc '' + Configuration for journal-upload. See {manpage}`journal-upload.conf(5)` + for available options. + ''; + + type = lib.types.submodule { + freeformType = format.type; + + options.Upload = { + URL = lib.mkOption { + type = lib.types.str; + example = "https://192.168.1.1"; + description = '' + The URL to upload the journal entries to. + + See the description of `--url=` option in + {manpage}`systemd-journal-upload(8)` for the description of + possible values. + ''; + }; + + ServerKeyFile = lib.mkOption { + type = with lib.types; nullOr str; + example = lib.literalExpression "./server-key.pem"; + # Since systemd-journal-upload uses a DynamicUser, permissions must + # be done using groups + description = '' + SSL key in PEM format. + + In contrary to what the name suggests, this option configures the + client private key sent to the remote journal server. + + This key should not be world-readable, and must be readably by + the `systemd-journal` group. + ''; + default = null; + }; + + ServerCertificateFile = lib.mkOption { + type = with lib.types; nullOr str; + example = lib.literalExpression "./server-ca.pem"; + description = '' + SSL CA certificate in PEM format. + + In contrary to what the name suggests, this option configures the + client certificate sent to the remote journal server. + ''; + default = null; + }; + + TrustedCertificateFile = lib.mkOption { + type = with lib.types; nullOr str; + example = lib.literalExpression "./ca"; + description = '' + SSL CA certificate. + + This certificate will be used to check the remote journal HTTPS + server certificate. + ''; + default = null; + }; + + NetworkTimeoutSec = lib.mkOption { + type = with lib.types; nullOr str; + example = "1s"; + description = '' + When network connectivity to the server is lost, this option + configures the time to wait for the connectivity to get restored. + + If the server is not reachable over the network for the + configured time, `systemd-journal-upload` exits. Takes a value in + seconds (or in other time units if suffixed with "ms", "min", + "h", etc). For details, see {manpage}`systemd.time(5)`. + ''; + default = null; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.additionalUpstreamSystemUnits = [ "systemd-journal-upload.service" ]; + + systemd.services."systemd-journal-upload" = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Restart = "always"; + # To prevent flooding the server in case the server is struggling + RestartSec = "3sec"; + }; + }; + + environment.etc."systemd/journal-upload.conf".source = + format.generate "journal-upload.conf" cfg.settings; + }; +} diff --git a/nixpkgs/nixos/modules/system/boot/systemd/journald.nix b/nixpkgs/nixos/modules/system/boot/systemd/journald.nix index 7e62a4c9bfed..9a8e7d592603 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/journald.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/journald.nix @@ -5,6 +5,10 @@ with lib; let cfg = config.services.journald; in { + imports = [ + (mkRenamedOptionModule [ "services" "journald" "enableHttpGateway" ] [ "services" "journald" "gateway" "enable" ]) + ]; + options = { services.journald.console = mkOption { default = ""; @@ -71,14 +75,6 @@ in { ''; }; - services.journald.enableHttpGateway = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Whether to enable the HTTP gateway to the journal. - ''; - }; - services.journald.forwardToSyslog = mkOption { default = config.services.rsyslogd.enable || config.services.syslog-ng.enable; defaultText = literalExpression "services.rsyslogd.enable || services.syslog-ng.enable"; @@ -101,9 +97,6 @@ in { ] ++ (optional (!config.boot.isContainer) "systemd-journald-audit.socket") ++ [ "systemd-journald-dev-log.socket" "syslog.socket" - ] ++ optionals cfg.enableHttpGateway [ - "systemd-journal-gatewayd.socket" - "systemd-journal-gatewayd.service" ]; environment.etc = { @@ -124,12 +117,6 @@ in { }; users.groups.systemd-journal.gid = config.ids.gids.systemd-journal; - users.users.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway; - users.users.systemd-journal-gateway.group = "systemd-journal-gateway"; - users.groups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway; - - systemd.sockets.systemd-journal-gatewayd.wantedBy = - optional cfg.enableHttpGateway "sockets.target"; systemd.services.systemd-journal-flush.restartIfChanged = false; systemd.services.systemd-journald.restartTriggers = [ config.environment.etc."systemd/journald.conf".source ]; diff --git a/nixpkgs/nixos/modules/system/boot/systemd/repart.nix b/nixpkgs/nixos/modules/system/boot/systemd/repart.nix index 5ac2ace56ba0..3be744acd0b3 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/repart.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/repart.nix @@ -83,6 +83,9 @@ in } ]; + # systemd-repart uses loopback devices for partition creation + boot.initrd.availableKernelModules = lib.optional initrdCfg.enable "loop"; + boot.initrd.systemd = lib.mkIf initrdCfg.enable { additionalUpstreamUnits = [ "systemd-repart.service" diff --git a/nixpkgs/nixos/modules/system/boot/systemd/sysupdate.nix b/nixpkgs/nixos/modules/system/boot/systemd/sysupdate.nix index b1914a9c4e76..cab35ddf270c 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/sysupdate.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/sysupdate.nix @@ -71,7 +71,7 @@ in type = with lib.types; attrsOf format.type; default = { }; example = { - "10-uki.conf" = { + "10-uki" = { Transfer = { ProtectVersion = "%A"; }; diff --git a/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix b/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix index f7ef45aab3c9..ee06648f568c 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/tmpfiles.nix @@ -150,6 +150,41 @@ in "systemd-tmpfiles-setup.service" ]; + # Allow systemd-tmpfiles to be restarted by switch-to-configuration. This + # service is not pulled into the normal boot process. It only exists for + # switch-to-configuration. + # + # This needs to be a separate unit because it does not execute + # systemd-tmpfiles with `--boot` as that is supposed to only be executed + # once at boot time. + # + # Keep this aligned with the upstream `systemd-tmpfiles-setup.service` unit. + systemd.services."systemd-tmpfiles-resetup" = { + description = "Re-setup tmpfiles on a system that is already running."; + + requiredBy = [ "sysinit-reactivation.target" ]; + after = [ "local-fs.target" "systemd-sysusers.service" "systemd-journald.service" ]; + before = [ "sysinit-reactivation.target" "shutdown.target" ]; + conflicts = [ "shutdown.target" ]; + restartTriggers = [ config.environment.etc."tmpfiles.d".source ]; + + unitConfig.DefaultDependencies = false; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "systemd-tmpfiles --create --remove --exclude-prefix=/dev"; + SuccessExitStatus = "DATAERR CANTCREAT"; + ImportCredential = [ + "tmpfiles.*" + "loging.motd" + "login.issue" + "network.hosts" + "ssh.authorized_keys.root" + ]; + }; + }; + environment.etc = { "tmpfiles.d".source = (pkgs.symlinkJoin { name = "tmpfiles.d"; diff --git a/nixpkgs/nixos/modules/system/boot/timesyncd.nix b/nixpkgs/nixos/modules/system/boot/timesyncd.nix index 7487cf97fe53..2666e4cd6b28 100644 --- a/nixpkgs/nixos/modules/system/boot/timesyncd.nix +++ b/nixpkgs/nixos/modules/system/boot/timesyncd.nix @@ -46,6 +46,13 @@ with lib; wantedBy = [ "sysinit.target" ]; aliases = [ "dbus-org.freedesktop.timesync1.service" ]; restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ]; + # systemd-timesyncd disables DNSSEC validation in the nss-resolve module by setting SYSTEMD_NSS_RESOLVE_VALIDATE to 0 in the unit file. + # This is required in order to solve the chicken-and-egg problem when DNSSEC validation needs the correct time to work, but to set the + # correct time, we need to connect to an NTP server, which usually requires resolving its hostname. + # In order for nss-resolve to be able to read this environment variable we patch systemd-timesyncd to disable NSCD and use NSS modules directly. + # This means that systemd-timesyncd needs to have NSS modules path in LD_LIBRARY_PATH. When systemd-resolved is disabled we still need to set + # NSS module path so that systemd-timesyncd keeps using other NSS modules that are configured in the system. + environment.LD_LIBRARY_PATH = config.system.nssModules.path; preStart = ( # Ensure that we have some stored time to prevent diff --git a/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix b/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix index e771b706bece..fdb149a3d9a1 100644 --- a/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix +++ b/nixpkgs/nixos/modules/tasks/filesystems/bcachefs.nix @@ -123,8 +123,8 @@ in inherit assertions; # needed for systemd-remount-fs system.fsPackages = [ pkgs.bcachefs-tools ]; - # FIXME: Replace this with `linuxPackages_latest` when 6.7 is released, remove this line when the LTS version is at least 6.7 - boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_testing; + # FIXME: Remove this line when the default kernel has bcachefs + boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_latest; systemd.services = lib.mapAttrs' (mkUnits "") (lib.filterAttrs (n: fs: (fs.fsType == "bcachefs") && (!utils.fsNeededForBoot fs)) config.fileSystems); } diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix index b38f228fc160..b289d2151eb7 100644 --- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix @@ -71,7 +71,7 @@ let done poolReady() { pool="$1" - state="$("${zpoolCmd}" import 2>/dev/null | "${awkCmd}" "/pool: $pool/ { found = 1 }; /state:/ { if (found == 1) { print \$2; exit } }; END { if (found == 0) { print \"MISSING\" } }")" + state="$("${zpoolCmd}" import -d "${cfgZfs.devNodes}" 2>/dev/null | "${awkCmd}" "/pool: $pool/ { found = 1 }; /state:/ { if (found == 1) { print \$2; exit } }; END { if (found == 0) { print \"MISSING\" } }")" if [[ "$state" = "ONLINE" ]]; then return 0 else @@ -108,12 +108,12 @@ let getKeyLocations = pool: if isBool cfgZfs.requestEncryptionCredentials then { hasKeys = cfgZfs.requestEncryptionCredentials; - command = "${cfgZfs.package}/sbin/zfs list -rHo name,keylocation,keystatus ${pool}"; + command = "${cfgZfs.package}/sbin/zfs list -rHo name,keylocation,keystatus -t volume,filesystem ${pool}"; } else let keys = filter (x: datasetToPool x == pool) cfgZfs.requestEncryptionCredentials; in { hasKeys = keys != []; - command = "${cfgZfs.package}/sbin/zfs list -Ho name,keylocation,keystatus ${toString keys}"; + command = "${cfgZfs.package}/sbin/zfs list -Ho name,keylocation,keystatus -t volume,filesystem ${toString keys}"; }; createImportService = { pool, systemd, force, prefix ? "" }: diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix index e1ac7f24cb32..2f2d282fbefb 100644 --- a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix @@ -70,7 +70,8 @@ let deviceDependency = dev: # Use systemd service if we manage device creation, else # trust udev when not in a container - if (hasAttr dev (filterAttrs (k: v: v.virtual) cfg.interfaces)) || + if (dev == null || dev == "lo") then [] + else if (hasAttr dev (filterAttrs (k: v: v.virtual) cfg.interfaces)) || (hasAttr dev cfg.bridges) || (hasAttr dev cfg.bonds) || (hasAttr dev cfg.macvlans) || @@ -78,7 +79,7 @@ let (hasAttr dev cfg.vlans) || (hasAttr dev cfg.vswitches) then [ "${dev}-netdev.service" ] - else optional (dev != null && dev != "lo" && !config.boot.isContainer) (subsystemDevice dev); + else optional (!config.boot.isContainer) (subsystemDevice dev); hasDefaultGatewaySet = (cfg.defaultGateway != null && cfg.defaultGateway.address != "") || (cfg.enableIPv6 && cfg.defaultGateway6 != null && cfg.defaultGateway6.address != ""); diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces.nix b/nixpkgs/nixos/modules/tasks/network-interfaces.nix index 2b2d24a64cb2..ca0b219b3c93 100644 --- a/nixpkgs/nixos/modules/tasks/network-interfaces.nix +++ b/nixpkgs/nixos/modules/tasks/network-interfaces.nix @@ -1449,16 +1449,6 @@ in listToAttrs ]; - # The network-interfaces target is kept for backwards compatibility. - # New modules must NOT use it. - systemd.targets.network-interfaces = - { description = "All Network Interfaces (deprecated)"; - wantedBy = [ "network.target" ]; - before = [ "network.target" ]; - after = [ "network-pre.target" ]; - unitConfig.X-StopOnReconfiguration = true; - }; - systemd.services = { network-local-commands = { description = "Extra networking commands."; diff --git a/nixpkgs/nixos/modules/tasks/trackpoint.nix b/nixpkgs/nixos/modules/tasks/trackpoint.nix index 317613b84792..b3f6f32eaa47 100644 --- a/nixpkgs/nixos/modules/tasks/trackpoint.nix +++ b/nixpkgs/nixos/modules/tasks/trackpoint.nix @@ -88,7 +88,7 @@ with lib; serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; serviceConfig.ExecStart = '' - ${config.systemd.package}/bin/udevadm trigger --attr-match=name="${cfg.device} + ${config.systemd.package}/bin/udevadm trigger --attr-match=name="${cfg.device}" ''; }; }) diff --git a/nixpkgs/nixos/modules/virtualisation/incus.nix b/nixpkgs/nixos/modules/virtualisation/incus.nix index 3e48f8873ed4..ea4cb916aa08 100644 --- a/nixpkgs/nixos/modules/virtualisation/incus.nix +++ b/nixpkgs/nixos/modules/virtualisation/incus.nix @@ -150,10 +150,12 @@ in after = [ "network-online.target" "lxcfs.service" - ] ++ (lib.optional cfg.socketActivation "incus.socket"); + "incus.socket" + ]; requires = [ "lxcfs.service" - ] ++ (lib.optional cfg.socketActivation "incus.socket"); + "incus.socket" + ]; wants = [ "network-online.target" ]; @@ -183,7 +185,7 @@ in }; }; - systemd.sockets.incus = lib.mkIf cfg.socketActivation { + systemd.sockets.incus = { description = "Incus UNIX socket"; wantedBy = [ "sockets.target" ]; @@ -191,7 +193,6 @@ in ListenStream = "/var/lib/incus/unix.socket"; SocketMode = "0660"; SocketGroup = "incus-admin"; - Service = "incus.service"; }; }; diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix index e195ff937d68..217242a8fbd2 100644 --- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix +++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix @@ -116,6 +116,15 @@ let QEMU's swtpm options. ''; }; + + vhostUserPackages = mkOption { + type = types.listOf types.package; + default = [ ]; + example = lib.literalExpression "[ pkgs.virtiofsd ]"; + description = lib.mdDoc '' + Packages containing out-of-tree vhost-user drivers. + ''; + }; }; }; @@ -502,6 +511,14 @@ in # https://libvirt.org/daemons.html#monolithic-systemd-integration systemd.sockets.libvirtd.wantedBy = [ "sockets.target" ]; + systemd.tmpfiles.rules = let + vhostUserCollection = pkgs.buildEnv { + name = "vhost-user"; + paths = cfg.qemu.vhostUserPackages; + pathsToLink = [ "/share/qemu/vhost-user" ]; + }; + in [ "L+ /var/lib/qemu/vhost-user - - - - ${vhostUserCollection}/share/qemu/vhost-user" ]; + security.polkit = { enable = true; extraConfig = '' diff --git a/nixpkgs/nixos/modules/virtualisation/lxd.nix b/nixpkgs/nixos/modules/virtualisation/lxd.nix index c4c856d9be30..e0d61b175494 100644 --- a/nixpkgs/nixos/modules/virtualisation/lxd.nix +++ b/nixpkgs/nixos/modules/virtualisation/lxd.nix @@ -33,21 +33,11 @@ in { ''; }; - package = lib.mkOption { - type = lib.types.package; - default = pkgs.lxd; - defaultText = lib.literalExpression "pkgs.lxd"; - description = lib.mdDoc '' - The LXD package to use. - ''; - }; + package = lib.mkPackageOption pkgs "lxd" { }; - lxcPackage = lib.mkOption { - type = lib.types.package; - default = pkgs.lxc; - defaultText = lib.literalExpression "pkgs.lxc"; - description = lib.mdDoc '' - The LXC package to use with LXD (required for AppArmor profiles). + lxcPackage = lib.mkPackageOption pkgs "lxc" { + extraDescription = '' + Required for AppArmor profiles. ''; }; @@ -149,7 +139,7 @@ in { ui = { enable = lib.mkEnableOption (lib.mdDoc "(experimental) LXD UI"); - package = lib.mkPackageOption pkgs.lxd-unwrapped "ui" { }; + package = lib.mkPackageOption pkgs [ "lxd-unwrapped" "ui" ] { }; }; }; }; @@ -224,16 +214,14 @@ in { LimitNPROC = "infinity"; TasksMax = "infinity"; - Restart = "on-failure"; - TimeoutStartSec = "${cfg.startTimeout}s"; - TimeoutStopSec = "30s"; - # By default, `lxd` loads configuration files from hard-coded # `/usr/share/lxc/config` - since this is a no-go for us, we have to # explicitly tell it where the actual configuration files are Environment = lib.mkIf (config.virtualisation.lxc.lxcfs.enable) "LXD_LXC_TEMPLATE_CONFIG=${pkgs.lxcfs}/share/lxc/config"; }; + + unitConfig.ConditionPathExists = "!/var/lib/incus/.migrated-from-lxd"; }; systemd.services.lxd-preseed = lib.mkIf (cfg.preseed != null) { |