diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/misc')
64 files changed, 873 insertions, 713 deletions
diff --git a/nixpkgs/nixos/modules/services/misc/airsonic.nix b/nixpkgs/nixos/modules/services/misc/airsonic.nix index b8e9dcaf4663..6ba6ff5ca3cb 100644 --- a/nixpkgs/nixos/modules/services/misc/airsonic.nix +++ b/nixpkgs/nixos/modules/services/misc/airsonic.nix @@ -85,15 +85,12 @@ in { ''; }; - jre = mkOption { - type = types.package; - default = pkgs.jre8; - defaultText = literalExpression "pkgs.jre8"; - description = lib.mdDoc '' - JRE package to use. - + jre = mkPackageOption pkgs "jre8" { + extraDescription = '' + ::: {.note} Airsonic only supports Java 8, airsonic-advanced requires at least Java 11. + ::: ''; }; diff --git a/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix index 02e44c73d87a..20b836abe164 100644 --- a/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix +++ b/nixpkgs/nixos/modules/services/misc/amazon-ssm-agent.nix @@ -15,6 +15,11 @@ let -r) echo "${config.system.nixos.version}";; esac ''; + + sudoRule = { + users = [ "ssm-user" ]; + commands = [ { command = "ALL"; options = [ "NOPASSWD" ]; } ]; + }; in { imports = [ (mkRenamedOptionModule [ "services" "ssm-agent" "enable" ] [ "services" "amazon-ssm-agent" "enable" ]) @@ -54,17 +59,9 @@ in { # Add user that Session Manager needs, and give it sudo. # This is consistent with Amazon Linux 2 images. - security.sudo.extraRules = [ - { - users = [ "ssm-user" ]; - commands = [ - { - command = "ALL"; - options = [ "NOPASSWD" ]; - } - ]; - } - ]; + security.sudo.extraRules = [ sudoRule ]; + security.sudo-rs.extraRules = [ sudoRule ]; + # On Amazon Linux 2 images, the ssm-user user is pretty much a # normal user with its own group. We do the same. users.groups.ssm-user = {}; diff --git a/nixpkgs/nixos/modules/services/misc/ananicy.nix b/nixpkgs/nixos/modules/services/misc/ananicy.nix index bc1b28efc0ba..01e1053c9e0e 100644 --- a/nixpkgs/nixos/modules/services/misc/ananicy.nix +++ b/nixpkgs/nixos/modules/services/misc/ananicy.nix @@ -15,21 +15,13 @@ in services.ananicy = { enable = mkEnableOption (lib.mdDoc "Ananicy, an auto nice daemon"); - package = mkOption { - type = types.package; - default = pkgs.ananicy; - defaultText = literalExpression "pkgs.ananicy"; - example = literalExpression "pkgs.ananicy-cpp"; - description = lib.mdDoc '' - Which ananicy package to use. - ''; + package = mkPackageOption pkgs "ananicy" { + example = "ananicy-cpp"; }; - rulesProvider = mkOption { - type = types.package; - default = pkgs.ananicy; - defaultText = literalExpression "pkgs.ananicy"; - example = literalExpression "pkgs.ananicy-cpp"; + rulesProvider = mkPackageOption pkgs "ananicy" { + example = "ananicy-cpp"; + } // { description = lib.mdDoc '' Which package to copy default rules,types,cgroups from. ''; diff --git a/nixpkgs/nixos/modules/services/misc/anki-sync-server.md b/nixpkgs/nixos/modules/services/misc/anki-sync-server.md new file mode 100644 index 000000000000..5d2b4da4d2fc --- /dev/null +++ b/nixpkgs/nixos/modules/services/misc/anki-sync-server.md @@ -0,0 +1,68 @@ +# Anki Sync Server {#module-services-anki-sync-server} + +[Anki Sync Server](https://docs.ankiweb.net/sync-server.html) is the built-in +sync server, present in recent versions of Anki. Advanced users who cannot or +do not wish to use AnkiWeb can use this sync server instead of AnkiWeb. + +This module is compatible only with Anki versions >=2.1.66, due to [recent +enhancements to the Nix anki +package](https://github.com/NixOS/nixpkgs/commit/05727304f8815825565c944d012f20a9a096838a). + +## Basic Usage {#module-services-anki-sync-server-basic-usage} + +By default, the module creates a +[`systemd`](https://www.freedesktop.org/wiki/Software/systemd/) +unit which runs the sync server with an isolated user using the systemd +`DynamicUser` option. + +This can be done by enabling the `anki-sync-server` service: +``` +{ ... }: + +{ + services.anki-sync-server.enable = true; +} +``` + +It is necessary to set at least one username-password pair under +{option}`services.anki-sync-server.users`. For example + +``` +{ + services.anki-sync-server.users = [ + { + username = "user"; + passwordFile = /etc/anki-sync-server/user; + } + ]; +} +``` + +Here, `passwordFile` is the path to a file containing just the password in +plaintext. Make sure to set permissions to make this file unreadable to any +user besides root. + +By default, the server listen address {option}`services.anki-sync-server.host` +is set to localhost, listening on port +{option}`services.anki-sync-server.port`, and does not open the firewall. This +is suitable for purely local testing, or to be used behind a reverse proxy. If +you want to expose the sync server directly to other computers (not recommended +in most circumstances, because the sync server doesn't use HTTPS), then set the +following options: + +``` +{ + services.anki-sync-server.host = "0.0.0.0"; + services.anki-sync-server.openFirewall = true; +} +``` + + +## Alternatives {#module-services-anki-sync-server-alternatives} + +The [`ankisyncd` NixOS +module](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/misc/ankisyncd.nix) +provides similar functionality, but using a third-party implementation, +[`anki-sync-server-rs`](https://github.com/ankicommunity/anki-sync-server-rs/). +According to that project's README, it is "no longer maintained", and not +recommended for Anki 2.1.64+. diff --git a/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix b/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix new file mode 100644 index 000000000000..a65382009417 --- /dev/null +++ b/nixpkgs/nixos/modules/services/misc/anki-sync-server.nix @@ -0,0 +1,140 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.services.anki-sync-server; + name = "anki-sync-server"; + specEscape = replaceStrings ["%"] ["%%"]; + usersWithIndexes = + lists.imap1 (i: user: { + i = i; + user = user; + }) + cfg.users; + usersWithIndexesFile = filter (x: x.user.passwordFile != null) usersWithIndexes; + usersWithIndexesNoFile = filter (x: x.user.passwordFile == null && x.user.password != null) usersWithIndexes; + anki-sync-server-run = pkgs.writeShellScriptBin "anki-sync-server-run" '' + # When services.anki-sync-server.users.passwordFile is set, + # each password file is passed as a systemd credential, which is mounted in + # a file system exposed to the service. Here we read the passwords from + # the credential files to pass them as environment variables to the Anki + # sync server. + ${ + concatMapStringsSep + "\n" + (x: ''export SYNC_USER${toString x.i}=${escapeShellArg x.user.username}:"''$(cat "''${CREDENTIALS_DIRECTORY}/"${escapeShellArg x.user.username})"'') + usersWithIndexesFile + } + # For users where services.anki-sync-server.users.password isn't set, + # export passwords in environment variables in plaintext. + ${ + concatMapStringsSep + "\n" + (x: ''export SYNC_USER${toString x.i}=${escapeShellArg x.user.username}:${escapeShellArg x.user.password}'') + usersWithIndexesNoFile + } + exec ${cfg.package}/bin/anki-sync-server + ''; +in { + options.services.anki-sync-server = { + enable = mkEnableOption "anki-sync-server"; + + package = mkPackageOption pkgs "anki-sync-server" { }; + + address = mkOption { + type = types.str; + default = "::1"; + description = '' + IP address anki-sync-server listens to. + Note host names are not resolved. + ''; + }; + + port = mkOption { + type = types.port; + default = 27701; + description = "Port number anki-sync-server listens to."; + }; + + openFirewall = mkOption { + default = false; + type = types.bool; + description = "Whether to open the firewall for the specified port."; + }; + + users = mkOption { + type = with types; + listOf (submodule { + options = { + username = mkOption { + type = str; + description = "User name accepted by anki-sync-server."; + }; + password = mkOption { + type = nullOr str; + default = null; + description = '' + Password accepted by anki-sync-server for the associated username. + **WARNING**: This option is **not secure**. This password will + be stored in *plaintext* and will be visible to *all users*. + See {option}`services.anki-sync-server.users.passwordFile` for + a more secure option. + ''; + }; + passwordFile = mkOption { + type = nullOr path; + default = null; + description = '' + File containing the password accepted by anki-sync-server for + the associated username. Make sure to make readable only by + root. + ''; + }; + }; + }); + description = "List of user-password pairs to provide to the sync server."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = (builtins.length usersWithIndexesFile) + (builtins.length usersWithIndexesNoFile) > 0; + message = "At least one username-password pair must be set."; + } + ]; + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port]; + + systemd.services.anki-sync-server = { + description = "anki-sync-server: Anki sync server built into Anki"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + path = [cfg.package]; + environment = { + SYNC_BASE = "%S/%N"; + SYNC_HOST = specEscape cfg.address; + SYNC_PORT = toString cfg.port; + }; + + serviceConfig = { + Type = "simple"; + DynamicUser = true; + StateDirectory = name; + ExecStart = "${anki-sync-server-run}/bin/anki-sync-server-run"; + Restart = "always"; + LoadCredential = + map + (x: "${specEscape x.user.username}:${specEscape (toString x.user.passwordFile)}") + usersWithIndexesFile; + }; + }; + }; + + meta = { + maintainers = with maintainers; [telotortium]; + doc = ./anki-sync-server.md; + }; +} diff --git a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix index 7be8dc7dab8f..e4de46e19a8f 100644 --- a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix +++ b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix @@ -24,12 +24,7 @@ in options.services.ankisyncd = { enable = mkEnableOption (lib.mdDoc "ankisyncd"); - package = mkOption { - type = types.package; - default = pkgs.ankisyncd; - defaultText = literalExpression "pkgs.ankisyncd"; - description = lib.mdDoc "The package to use for the ankisyncd command."; - }; + package = mkPackageOption pkgs "ankisyncd" { }; host = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/apache-kafka.nix b/nixpkgs/nixos/modules/services/misc/apache-kafka.nix index 598907aaf1c6..b7281a0d9d5f 100644 --- a/nixpkgs/nixos/modules/services/misc/apache-kafka.nix +++ b/nixpkgs/nixos/modules/services/misc/apache-kafka.nix @@ -5,75 +5,117 @@ with lib; let cfg = config.services.apache-kafka; - serverProperties = - if cfg.serverProperties != null then - cfg.serverProperties - else - '' - # Generated by nixos - broker.id=${toString cfg.brokerId} - port=${toString cfg.port} - host.name=${cfg.hostname} - log.dirs=${concatStringsSep "," cfg.logDirs} - zookeeper.connect=${cfg.zookeeper} - ${toString cfg.extraProperties} - ''; + # The `javaProperties` generator takes care of various escaping rules and + # generation of the properties file, but we'll handle stringly conversion + # ourselves in mkPropertySettings and stringlySettings, since we know more + # about the specifically allowed format eg. for lists of this type, and we + # don't want to coerce-downsample values to str too early by having the + # coercedTypes from javaProperties directly in our NixOS option types. + # + # Make sure every `freeformType` and any specific option type in `settings` is + # supported here. + + mkPropertyString = let + render = { + bool = boolToString; + int = toString; + list = concatMapStringsSep "," mkPropertyString; + string = id; + }; + in + v: render.${builtins.typeOf v} v; - serverConfig = pkgs.writeText "server.properties" serverProperties; - logConfig = pkgs.writeText "log4j.properties" cfg.log4jProperties; + stringlySettings = mapAttrs (_: mkPropertyString) + (filterAttrs (_: v: v != null) cfg.settings); + generator = (pkgs.formats.javaProperties {}).generate; in { options.services.apache-kafka = { - enable = mkOption { - description = lib.mdDoc "Whether to enable Apache Kafka."; - default = false; - type = types.bool; - }; - - brokerId = mkOption { - description = lib.mdDoc "Broker ID."; - default = -1; - type = types.int; - }; + enable = mkEnableOption (lib.mdDoc "Apache Kafka event streaming broker"); - port = mkOption { - description = lib.mdDoc "Port number the broker should listen on."; - default = 9092; - type = types.port; + settings = mkOption { + description = lib.mdDoc '' + [Kafka broker configuration](https://kafka.apache.org/documentation.html#brokerconfigs) + {file}`server.properties`. + + Note that .properties files contain mappings from string to string. + Keys with dots are NOT represented by nested attrs in these settings, + but instead as quoted strings (ie. `settings."broker.id"`, NOT + `settings.broker.id`). + ''; + type = types.submodule { + freeformType = with types; let + primitive = oneOf [bool int str]; + in lazyAttrsOf (nullOr (either primitive (listOf primitive))); + + options = { + "broker.id" = mkOption { + description = lib.mdDoc "Broker ID. -1 or null to auto-allocate in zookeeper mode."; + default = null; + type = with types; nullOr int; + }; + + "log.dirs" = mkOption { + description = lib.mdDoc "Log file directories."; + # Deliberaly leave out old default and use the rewrite opportunity + # to have users choose a safer value -- /tmp might be volatile and is a + # slightly scary default choice. + # default = [ "/tmp/apache-kafka" ]; + type = with types; listOf path; + }; + + "listeners" = mkOption { + description = lib.mdDoc '' + Kafka Listener List. + See [listeners](https://kafka.apache.org/documentation/#brokerconfigs_listeners). + ''; + type = types.listOf types.str; + default = [ "PLAINTEXT://localhost:9092" ]; + }; + }; + }; }; - hostname = mkOption { - description = lib.mdDoc "Hostname the broker should bind to."; - default = "localhost"; - type = types.str; + clusterId = mkOption { + description = lib.mdDoc '' + KRaft mode ClusterId used for formatting log directories. Can be generated with `kafka-storage.sh random-uuid` + ''; + type = with types; nullOr str; + default = null; }; - logDirs = mkOption { - description = lib.mdDoc "Log file directories"; - default = [ "/tmp/kafka-logs" ]; - type = types.listOf types.path; + configFiles.serverProperties = mkOption { + description = lib.mdDoc '' + Kafka server.properties configuration file path. + Defaults to the rendered `settings`. + ''; + type = types.path; }; - zookeeper = mkOption { - description = lib.mdDoc "Zookeeper connection string"; - default = "localhost:2181"; - type = types.str; + configFiles.log4jProperties = mkOption { + description = lib.mdDoc "Kafka log4j property configuration file path"; + type = types.path; + default = pkgs.writeText "log4j.properties" cfg.log4jProperties; + defaultText = ''pkgs.writeText "log4j.properties" cfg.log4jProperties''; }; - extraProperties = mkOption { - description = lib.mdDoc "Extra properties for server.properties."; - type = types.nullOr types.lines; - default = null; + formatLogDirs = mkOption { + description = lib.mdDoc '' + Whether to format log dirs in KRaft mode if all log dirs are + unformatted, ie. they contain no meta.properties. + ''; + type = types.bool; + default = false; }; - serverProperties = mkOption { + formatLogDirsIgnoreFormatted = mkOption { description = lib.mdDoc '' - Complete server.properties content. Other server.properties config - options will be ignored if this option is used. + Whether to ignore already formatted log dirs when formatting log dirs, + instead of failing. Useful when replacing or adding disks. ''; - type = types.nullOr types.lines; - default = null; + type = types.bool; + default = false; }; log4jProperties = mkOption { @@ -99,12 +141,7 @@ in { ]; }; - package = mkOption { - description = lib.mdDoc "The kafka package to use"; - default = pkgs.apacheKafka; - defaultText = literalExpression "pkgs.apacheKafka"; - type = types.package; - }; + package = mkPackageOption pkgs "apacheKafka" { }; jre = mkOption { description = lib.mdDoc "The JRE with which to run Kafka"; @@ -112,40 +149,70 @@ in { defaultText = literalExpression "pkgs.apacheKafka.passthru.jre"; type = types.package; }; - }; - config = mkIf cfg.enable { + imports = [ + (mkRenamedOptionModule + [ "services" "apache-kafka" "brokerId" ] + [ "services" "apache-kafka" "settings" ''broker.id'' ]) + (mkRenamedOptionModule + [ "services" "apache-kafka" "logDirs" ] + [ "services" "apache-kafka" "settings" ''log.dirs'' ]) + (mkRenamedOptionModule + [ "services" "apache-kafka" "zookeeper" ] + [ "services" "apache-kafka" "settings" ''zookeeper.connect'' ]) + + (mkRemovedOptionModule [ "services" "apache-kafka" "port" ] + "Please see services.apache-kafka.settings.listeners and its documentation instead") + (mkRemovedOptionModule [ "services" "apache-kafka" "hostname" ] + "Please see services.apache-kafka.settings.listeners and its documentation instead") + (mkRemovedOptionModule [ "services" "apache-kafka" "extraProperties" ] + "Please see services.apache-kafka.settings and its documentation instead") + (mkRemovedOptionModule [ "services" "apache-kafka" "serverProperties" ] + "Please see services.apache-kafka.settings and its documentation instead") + ]; - environment.systemPackages = [cfg.package]; + config = mkIf cfg.enable { + services.apache-kafka.configFiles.serverProperties = generator "server.properties" stringlySettings; users.users.apache-kafka = { isSystemUser = true; group = "apache-kafka"; description = "Apache Kafka daemon user"; - home = head cfg.logDirs; }; users.groups.apache-kafka = {}; - systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.logDirs; + systemd.tmpfiles.rules = map (logDir: "d '${logDir}' 0700 apache-kafka - - -") cfg.settings."log.dirs"; systemd.services.apache-kafka = { description = "Apache Kafka Daemon"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + preStart = mkIf cfg.formatLogDirs + (if cfg.formatLogDirsIgnoreFormatted then '' + ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} --ignore-formatted + '' else '' + if ${concatMapStringsSep " && " (l: ''[ ! -f "${l}/meta.properties" ]'') cfg.settings."log.dirs"}; then + ${cfg.package}/bin/kafka-storage.sh format -t "${cfg.clusterId}" -c ${cfg.configFiles.serverProperties} + fi + ''); serviceConfig = { ExecStart = '' ${cfg.jre}/bin/java \ -cp "${cfg.package}/libs/*" \ - -Dlog4j.configuration=file:${logConfig} \ + -Dlog4j.configuration=file:${cfg.configFiles.log4jProperties} \ ${toString cfg.jvmOptions} \ kafka.Kafka \ - ${serverConfig} + ${cfg.configFiles.serverProperties} ''; User = "apache-kafka"; SuccessExitStatus = "0 143"; }; }; - }; + + meta.doc = ./kafka.md; + meta.maintainers = with lib.maintainers; [ + srhb + ]; } diff --git a/nixpkgs/nixos/modules/services/misc/autosuspend.nix b/nixpkgs/nixos/modules/services/misc/autosuspend.nix index b3e362533a09..28dfa12105ec 100644 --- a/nixpkgs/nixos/modules/services/misc/autosuspend.nix +++ b/nixpkgs/nixos/modules/services/misc/autosuspend.nix @@ -1,7 +1,7 @@ { config, pkgs, lib, ... }: let inherit (lib) mapAttrs' nameValuePair filterAttrs types mkEnableOption - mdDoc mkPackageOptionMD mkOption literalExpression mkIf flatten + mdDoc mkPackageOption mkOption literalExpression mkIf flatten maintainers attrValues; cfg = config.services.autosuspend; @@ -96,7 +96,7 @@ in services.autosuspend = { enable = mkEnableOption (mdDoc "the autosuspend daemon"); - package = mkPackageOptionMD pkgs "autosuspend" { }; + package = mkPackageOption pkgs "autosuspend" { }; settings = mkOption { type = types.submodule { diff --git a/nixpkgs/nixos/modules/services/misc/bcg.nix b/nixpkgs/nixos/modules/services/misc/bcg.nix index 214c89dbfe72..9da4a879cdd0 100644 --- a/nixpkgs/nixos/modules/services/misc/bcg.nix +++ b/nixpkgs/nixos/modules/services/misc/bcg.nix @@ -26,12 +26,7 @@ in options = { services.bcg = { enable = mkEnableOption (mdDoc "BigClown gateway"); - package = mkOption { - default = pkgs.python3Packages.bcg; - defaultText = literalExpression "pkgs.python3Packages.bcg"; - description = mdDoc "Which bcg derivation to use."; - type = types.package; - }; + package = mkPackageOption pkgs [ "python3Packages" "bcg" ] { }; environmentFiles = mkOption { type = types.listOf types.path; default = []; diff --git a/nixpkgs/nixos/modules/services/misc/calibre-server.nix b/nixpkgs/nixos/modules/services/misc/calibre-server.nix index e1ddae1de1f8..66ae5fa91bb6 100644 --- a/nixpkgs/nixos/modules/services/misc/calibre-server.nix +++ b/nixpkgs/nixos/modules/services/misc/calibre-server.nix @@ -33,7 +33,7 @@ in services.calibre-server = { enable = mkEnableOption (lib.mdDoc "calibre-server"); - package = lib.mkPackageOptionMD pkgs "calibre" { }; + package = lib.mkPackageOption pkgs "calibre" { }; libraries = mkOption { type = types.listOf types.path; diff --git a/nixpkgs/nixos/modules/services/misc/cgminer.nix b/nixpkgs/nixos/modules/services/misc/cgminer.nix index a6fbfee73bad..ad6cbf50918d 100644 --- a/nixpkgs/nixos/modules/services/misc/cgminer.nix +++ b/nixpkgs/nixos/modules/services/misc/cgminer.nix @@ -33,12 +33,7 @@ in enable = mkEnableOption (lib.mdDoc "cgminer, an ASIC/FPGA/GPU miner for bitcoin and litecoin"); - package = mkOption { - default = pkgs.cgminer; - defaultText = literalExpression "pkgs.cgminer"; - description = lib.mdDoc "Which cgminer derivation to use."; - type = types.package; - }; + package = mkPackageOption pkgs "cgminer" { }; user = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/clipcat.nix b/nixpkgs/nixos/modules/services/misc/clipcat.nix index 0129de3a9efb..fb6442709530 100644 --- a/nixpkgs/nixos/modules/services/misc/clipcat.nix +++ b/nixpkgs/nixos/modules/services/misc/clipcat.nix @@ -9,12 +9,7 @@ in { options.services.clipcat= { enable = mkEnableOption (lib.mdDoc "Clipcat clipboard daemon"); - package = mkOption { - type = types.package; - default = pkgs.clipcat; - defaultText = literalExpression "pkgs.clipcat"; - description = lib.mdDoc "clipcat derivation to use."; - }; + package = mkPackageOption pkgs "clipcat" { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/clipmenu.nix b/nixpkgs/nixos/modules/services/misc/clipmenu.nix index 1cc8c4c47f7e..343167b1df2e 100644 --- a/nixpkgs/nixos/modules/services/misc/clipmenu.nix +++ b/nixpkgs/nixos/modules/services/misc/clipmenu.nix @@ -9,12 +9,7 @@ in { options.services.clipmenu = { enable = mkEnableOption (lib.mdDoc "clipmenu, the clipboard management daemon"); - package = mkOption { - type = types.package; - default = pkgs.clipmenu; - defaultText = literalExpression "pkgs.clipmenu"; - description = lib.mdDoc "clipmenu derivation to use."; - }; + package = mkPackageOption pkgs "clipmenu" { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/confd.nix b/nixpkgs/nixos/modules/services/misc/confd.nix index 17c1be57ccbc..93731547ede8 100644 --- a/nixpkgs/nixos/modules/services/misc/confd.nix +++ b/nixpkgs/nixos/modules/services/misc/confd.nix @@ -61,12 +61,7 @@ in { type = types.path; }; - package = mkOption { - description = lib.mdDoc "Confd package to use."; - default = pkgs.confd; - defaultText = literalExpression "pkgs.confd"; - type = types.package; - }; + package = mkPackageOption pkgs "confd" { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/disnix.nix b/nixpkgs/nixos/modules/services/misc/disnix.nix index 13c57ce6b85b..ee342cbc2e47 100644 --- a/nixpkgs/nixos/modules/services/misc/disnix.nix +++ b/nixpkgs/nixos/modules/services/misc/disnix.nix @@ -27,12 +27,7 @@ in useWebServiceInterface = mkEnableOption (lib.mdDoc "the DisnixWebService interface running on Apache Tomcat"); - package = mkOption { - type = types.path; - description = lib.mdDoc "The Disnix package"; - default = pkgs.disnix; - defaultText = literalExpression "pkgs.disnix"; - }; + package = mkPackageOption pkgs "disnix" {}; enableProfilePath = mkEnableOption (lib.mdDoc "exposing the Disnix profiles in the system's PATH"); diff --git a/nixpkgs/nixos/modules/services/misc/docker-registry.nix b/nixpkgs/nixos/modules/services/misc/docker-registry.nix index b0e910634637..e8fbc05423d3 100644 --- a/nixpkgs/nixos/modules/services/misc/docker-registry.nix +++ b/nixpkgs/nixos/modules/services/misc/docker-registry.nix @@ -47,12 +47,8 @@ in { options.services.dockerRegistry = { enable = mkEnableOption (lib.mdDoc "Docker Registry"); - package = mkOption { - type = types.package; - description = mdDoc "Which Docker registry package to use."; - default = pkgs.docker-distribution; - defaultText = literalExpression "pkgs.docker-distribution"; - example = literalExpression "pkgs.gitlab-container-registry"; + package = mkPackageOption pkgs "docker-distribution" { + example = "gitlab-container-registry"; }; listenAddress = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/dwm-status.nix b/nixpkgs/nixos/modules/services/misc/dwm-status.nix index de3e28c41d27..351adf31d922 100644 --- a/nixpkgs/nixos/modules/services/misc/dwm-status.nix +++ b/nixpkgs/nixos/modules/services/misc/dwm-status.nix @@ -24,14 +24,8 @@ in enable = mkEnableOption (lib.mdDoc "dwm-status user service"); - package = mkOption { - type = types.package; - default = pkgs.dwm-status; - defaultText = literalExpression "pkgs.dwm-status"; - example = literalExpression "pkgs.dwm-status.override { enableAlsaUtils = false; }"; - description = lib.mdDoc '' - Which dwm-status package to use. - ''; + package = mkPackageOption pkgs "dwm-status" { + example = "dwm-status.override { enableAlsaUtils = false; }"; }; order = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/etcd.nix b/nixpkgs/nixos/modules/services/misc/etcd.nix index 7bc7a9499113..73bdeb3b0afd 100644 --- a/nixpkgs/nixos/modules/services/misc/etcd.nix +++ b/nixpkgs/nixos/modules/services/misc/etcd.nix @@ -15,7 +15,7 @@ in { type = types.bool; }; - package = mkPackageOptionMD pkgs "etcd" { }; + package = mkPackageOption pkgs "etcd" { }; name = mkOption { description = lib.mdDoc "Etcd unique node name."; diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.md b/nixpkgs/nixos/modules/services/misc/forgejo.md index 3df8bc20976a..14b21933e6b0 100644 --- a/nixpkgs/nixos/modules/services/misc/forgejo.md +++ b/nixpkgs/nixos/modules/services/misc/forgejo.md @@ -20,7 +20,7 @@ If you experience issues with your instance using `services.gitea`, ::: {.note} Migrating is, while not strictly necessary at this point, highly recommended. -Both modules and projects are likely to divide further with each release. +Both modules and projects are likely to diverge further with each release. Which might lead to an even more involved migration. ::: diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.nix b/nixpkgs/nixos/modules/services/misc/forgejo.nix index 454febda5893..08cddc3a0710 100644 --- a/nixpkgs/nixos/modules/services/misc/forgejo.nix +++ b/nixpkgs/nixos/modules/services/misc/forgejo.nix @@ -21,7 +21,7 @@ let mkIf mkMerge mkOption - mkPackageOptionMD + mkPackageOption mkRemovedOptionModule mkRenamedOptionModule optionalAttrs @@ -57,7 +57,7 @@ in services.forgejo = { enable = mkEnableOption (mdDoc "Forgejo"); - package = mkPackageOptionMD pkgs "forgejo" { }; + package = mkPackageOption pkgs "forgejo" { }; useWizard = mkOption { default = false; diff --git a/nixpkgs/nixos/modules/services/misc/freeswitch.nix b/nixpkgs/nixos/modules/services/misc/freeswitch.nix index b8b81e586944..a8f7b3d0c3ae 100644 --- a/nixpkgs/nixos/modules/services/misc/freeswitch.nix +++ b/nixpkgs/nixos/modules/services/misc/freeswitch.nix @@ -58,14 +58,7 @@ in { Also check available templates in [FreeSWITCH repository](https://github.com/signalwire/freeswitch/tree/master/conf). ''; }; - package = mkOption { - type = types.package; - default = pkgs.freeswitch; - defaultText = literalExpression "pkgs.freeswitch"; - description = lib.mdDoc '' - FreeSWITCH package. - ''; - }; + package = mkPackageOption pkgs "freeswitch" { }; }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/gitea.nix b/nixpkgs/nixos/modules/services/misc/gitea.nix index be528a298991..f4305bea2ad7 100644 --- a/nixpkgs/nixos/modules/services/misc/gitea.nix +++ b/nixpkgs/nixos/modules/services/misc/gitea.nix @@ -51,12 +51,7 @@ in description = lib.mdDoc "Enable Gitea Service."; }; - package = mkOption { - default = pkgs.gitea; - type = types.package; - defaultText = literalExpression "pkgs.gitea"; - description = lib.mdDoc "gitea derivation to use"; - }; + package = mkPackageOption pkgs "gitea" { }; useWizard = mkOption { default = false; diff --git a/nixpkgs/nixos/modules/services/misc/gitlab.nix b/nixpkgs/nixos/modules/services/misc/gitlab.nix index b399ccc38f58..6756d59cf367 100644 --- a/nixpkgs/nixos/modules/services/misc/gitlab.nix +++ b/nixpkgs/nixos/modules/services/misc/gitlab.nix @@ -258,41 +258,17 @@ in { ''; }; - packages.gitlab = mkOption { - type = types.package; - default = pkgs.gitlab; - defaultText = literalExpression "pkgs.gitlab"; - description = lib.mdDoc "Reference to the gitlab package"; - example = literalExpression "pkgs.gitlab-ee"; + packages.gitlab = mkPackageOption pkgs "gitlab" { + example = "gitlab-ee"; }; - packages.gitlab-shell = mkOption { - type = types.package; - default = pkgs.gitlab-shell; - defaultText = literalExpression "pkgs.gitlab-shell"; - description = lib.mdDoc "Reference to the gitlab-shell package"; - }; + packages.gitlab-shell = mkPackageOption pkgs "gitlab-shell" { }; - packages.gitlab-workhorse = mkOption { - type = types.package; - default = pkgs.gitlab-workhorse; - defaultText = literalExpression "pkgs.gitlab-workhorse"; - description = lib.mdDoc "Reference to the gitlab-workhorse package"; - }; + packages.gitlab-workhorse = mkPackageOption pkgs "gitlab-workhorse" { }; - packages.gitaly = mkOption { - type = types.package; - default = pkgs.gitaly; - defaultText = literalExpression "pkgs.gitaly"; - description = lib.mdDoc "Reference to the gitaly package"; - }; + packages.gitaly = mkPackageOption pkgs "gitaly" { }; - packages.pages = mkOption { - type = types.package; - default = pkgs.gitlab-pages; - defaultText = literalExpression "pkgs.gitlab-pages"; - description = lib.mdDoc "Reference to the gitlab-pages package"; - }; + packages.pages = mkPackageOption pkgs "gitlab-pages" { }; statePath = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/gollum.nix b/nixpkgs/nixos/modules/services/misc/gollum.nix index b73528abaf65..e31eeaf8a30a 100644 --- a/nixpkgs/nixos/modules/services/misc/gollum.nix +++ b/nixpkgs/nixos/modules/services/misc/gollum.nix @@ -83,14 +83,7 @@ in description = lib.mdDoc "Specifies the path of the repository directory. If it does not exist, Gollum will create it on startup."; }; - package = mkOption { - type = types.package; - default = pkgs.gollum; - defaultText = literalExpression "pkgs.gollum"; - description = lib.mdDoc '' - The package used in the service - ''; - }; + package = mkPackageOption pkgs "gollum" { }; user = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/greenclip.nix b/nixpkgs/nixos/modules/services/misc/greenclip.nix index 45847af71141..ecfb864ab2b7 100644 --- a/nixpkgs/nixos/modules/services/misc/greenclip.nix +++ b/nixpkgs/nixos/modules/services/misc/greenclip.nix @@ -9,12 +9,7 @@ in { options.services.greenclip = { enable = mkEnableOption (lib.mdDoc "Greenclip daemon"); - package = mkOption { - type = types.package; - default = pkgs.haskellPackages.greenclip; - defaultText = literalExpression "pkgs.haskellPackages.greenclip"; - description = lib.mdDoc "greenclip derivation to use."; - }; + package = mkPackageOption pkgs [ "haskellPackages" "greenclip" ] { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/heisenbridge.nix b/nixpkgs/nixos/modules/services/misc/heisenbridge.nix index 822a09d7cd4d..d7ce9c605c9e 100644 --- a/nixpkgs/nixos/modules/services/misc/heisenbridge.nix +++ b/nixpkgs/nixos/modules/services/misc/heisenbridge.nix @@ -25,14 +25,7 @@ in options.services.heisenbridge = { enable = mkEnableOption (lib.mdDoc "the Matrix to IRC bridge"); - package = mkOption { - type = types.package; - default = pkgs.heisenbridge; - defaultText = lib.literalExpression "pkgs.heisenbridge"; - description = lib.mdDoc '' - Package of the application to run, exposed for overriding purposes. - ''; - }; + package = mkPackageOption pkgs "heisenbridge" { }; homeserver = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix b/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix index e68571253433..07a09e2b6bbf 100644 --- a/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix +++ b/nixpkgs/nixos/modules/services/misc/homepage-dashboard.nix @@ -12,7 +12,7 @@ in services.homepage-dashboard = { enable = lib.mkEnableOption (lib.mdDoc "Homepage Dashboard"); - package = lib.mkPackageOptionMD pkgs "homepage-dashboard" { }; + package = lib.mkPackageOption pkgs "homepage-dashboard" { }; openFirewall = lib.mkOption { type = lib.types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/input-remapper.nix b/nixpkgs/nixos/modules/services/misc/input-remapper.nix index 3f6d97f85738..5b9f16e019d8 100644 --- a/nixpkgs/nixos/modules/services/misc/input-remapper.nix +++ b/nixpkgs/nixos/modules/services/misc/input-remapper.nix @@ -7,7 +7,7 @@ let cfg = config.services.input-remapper; in options = { services.input-remapper = { enable = mkEnableOption (lib.mdDoc "input-remapper, an easy to use tool to change the mapping of your input device buttons"); - package = mkPackageOptionMD pkgs "input-remapper" { }; + package = mkPackageOption pkgs "input-remapper" { }; enableUdevRules = mkEnableOption (lib.mdDoc "udev rules added by input-remapper to handle hotplugged devices. Currently disabled by default due to https://github.com/sezanzeb/input-remapper/issues/140"); serviceWantedBy = mkOption { default = [ "graphical.target" ]; diff --git a/nixpkgs/nixos/modules/services/misc/jackett.nix b/nixpkgs/nixos/modules/services/misc/jackett.nix index b0edf0d18da4..c0bb0a575f01 100644 --- a/nixpkgs/nixos/modules/services/misc/jackett.nix +++ b/nixpkgs/nixos/modules/services/misc/jackett.nix @@ -35,12 +35,7 @@ in description = lib.mdDoc "Group under which Jackett runs."; }; - package = mkOption { - type = types.package; - default = pkgs.jackett; - defaultText = literalExpression "pkgs.jackett"; - description = lib.mdDoc "Jackett package to use."; - }; + package = mkPackageOption pkgs "jackett" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/jellyfin.nix b/nixpkgs/nixos/modules/services/misc/jellyfin.nix index 43fdc09f4559..7042b491ffa4 100644 --- a/nixpkgs/nixos/modules/services/misc/jellyfin.nix +++ b/nixpkgs/nixos/modules/services/misc/jellyfin.nix @@ -16,14 +16,7 @@ in description = lib.mdDoc "User account under which Jellyfin runs."; }; - package = mkOption { - type = types.package; - default = pkgs.jellyfin; - defaultText = literalExpression "pkgs.jellyfin"; - description = lib.mdDoc '' - Jellyfin package to use. - ''; - }; + package = mkPackageOption pkgs "jellyfin" { }; group = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/kafka.md b/nixpkgs/nixos/modules/services/misc/kafka.md new file mode 100644 index 000000000000..370bb3b482d2 --- /dev/null +++ b/nixpkgs/nixos/modules/services/misc/kafka.md @@ -0,0 +1,63 @@ +# Apache Kafka {#module-services-apache-kafka} + +[Apache Kafka](https://kafka.apache.org/) is an open-source distributed event +streaming platform + +## Basic Usage {#module-services-apache-kafka-basic-usage} + +The Apache Kafka service is configured almost exclusively through its +[settings](#opt-services.apache-kafka.settings) option, with each attribute +corresponding to the [upstream configuration +manual](https://kafka.apache.org/documentation/#configuration) broker settings. + +## KRaft {#module-services-apache-kafka-kraft} + +Unlike in Zookeeper mode, Kafka in +[KRaft](https://kafka.apache.org/documentation/#kraft) mode requires each log +dir to be "formatted" (which means a cluster-specific a metadata file must +exist in each log dir) + +The upstream intention is for users to execute the [storage +tool](https://kafka.apache.org/documentation/#kraft_storage) to achieve this, +but this module contains a few extra options to automate this: + +- [](#opt-services.apache-kafka.clusterId) +- [](#opt-services.apache-kafka.formatLogDirs) +- [](#opt-services.apache-kafka.formatLogDirsIgnoreFormatted) + +## Migrating to settings {#module-services-apache-kafka-migrating-to-settings} + +Migrating a cluster to the new `settings`-based changes requires adapting removed options to the corresponding upstream settings. + +This means that the upstream [Broker Configs documentation](https://kafka.apache.org/documentation/#brokerconfigs) should be followed closely. + +Note that dotted options in the upstream docs do _not_ correspond to nested Nix attrsets, but instead as quoted top level `settings` attributes, as in `services.apache-kafka.settings."broker.id"`, *NOT* `services.apache-kafka.settings.broker.id`. + +Care should be taken, especially when migrating clusters from the old module, to ensure that the same intended configuration is reproduced faithfully via `settings`. + +To assist in the comparison, the final config can be inspected by building the config file itself, ie. with: `nix-build <nixpkgs/nixos> -A config.services.apache-kafka.configFiles.serverProperties`. + +Notable changes to be aware of include: + +- Removal of `services.apache-kafka.extraProperties` and `services.apache-kafka.serverProperties` + - Translate using arbitrary properties using [](#opt-services.apache-kafka.settings) + - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs) + - The intention is for all broker properties to be fully representable via [](#opt-services.apache-kafka.settings). + - If this is not the case, please do consider raising an issue. + - Until it can be remedied, you *can* bail out by using [](#opt-services.apache-kafka.configFiles.serverProperties) to the path of a fully rendered properties file. + +- Removal of `services.apache-kafka.hostname` and `services.apache-kafka.port` + - Translate using: `services.apache-kafka.settings.listeners` + - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_listeners) + +- Removal of `services.apache-kafka.logDirs` + - Translate using: `services.apache-kafka.settings."log.dirs"` + - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_log.dirs) + +- Removal of `services.apache-kafka.brokerId` + - Translate using: `services.apache-kafka.settings."broker.id"` + - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_broker.id) + +- Removal of `services.apache-kafka.zookeeper` + - Translate using: `services.apache-kafka.settings."zookeeper.connect"` + - [Upstream docs](https://kafka.apache.org/documentation.html#brokerconfigs_zookeeper.connect) diff --git a/nixpkgs/nixos/modules/services/misc/klipper.nix b/nixpkgs/nixos/modules/services/misc/klipper.nix index 9eb2fdb46593..a0eb409599b5 100644 --- a/nixpkgs/nixos/modules/services/misc/klipper.nix +++ b/nixpkgs/nixos/modules/services/misc/klipper.nix @@ -16,12 +16,7 @@ in services.klipper = { enable = mkEnableOption (lib.mdDoc "Klipper, the 3D printer firmware"); - package = mkOption { - type = types.package; - default = pkgs.klipper; - defaultText = literalExpression "pkgs.klipper"; - description = lib.mdDoc "The Klipper package."; - }; + package = mkPackageOption pkgs "klipper" { }; logFile = mkOption { type = types.nullOr types.path; diff --git a/nixpkgs/nixos/modules/services/misc/libreddit.nix b/nixpkgs/nixos/modules/services/misc/libreddit.nix index fd58928d2821..02d71c198e78 100644 --- a/nixpkgs/nixos/modules/services/misc/libreddit.nix +++ b/nixpkgs/nixos/modules/services/misc/libreddit.nix @@ -15,12 +15,7 @@ in services.libreddit = { enable = mkEnableOption (lib.mdDoc "Private front-end for Reddit"); - package = mkOption { - type = types.package; - default = pkgs.libreddit; - defaultText = literalExpression "pkgs.libreddit"; - description = lib.mdDoc "Libreddit package to use."; - }; + package = mkPackageOption pkgs "libreddit" { }; address = mkOption { default = "0.0.0.0"; diff --git a/nixpkgs/nixos/modules/services/misc/lidarr.nix b/nixpkgs/nixos/modules/services/misc/lidarr.nix index 92b00054bdff..4dc0fc63863b 100644 --- a/nixpkgs/nixos/modules/services/misc/lidarr.nix +++ b/nixpkgs/nixos/modules/services/misc/lidarr.nix @@ -16,12 +16,7 @@ in description = lib.mdDoc "The directory where Lidarr stores its data files."; }; - package = mkOption { - type = types.package; - default = pkgs.lidarr; - defaultText = literalExpression "pkgs.lidarr"; - description = lib.mdDoc "The Lidarr package to use"; - }; + package = mkPackageOption pkgs "lidarr" { }; openFirewall = mkOption { type = types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/mbpfan.nix b/nixpkgs/nixos/modules/services/misc/mbpfan.nix index 8f64fb2d9c52..ef56ea49d1a9 100644 --- a/nixpkgs/nixos/modules/services/misc/mbpfan.nix +++ b/nixpkgs/nixos/modules/services/misc/mbpfan.nix @@ -11,12 +11,7 @@ in { options.services.mbpfan = { enable = mkEnableOption (lib.mdDoc "mbpfan, fan controller daemon for Apple Macs and MacBooks"); - package = mkOption { - type = types.package; - default = pkgs.mbpfan; - defaultText = literalExpression "pkgs.mbpfan"; - description = lib.mdDoc "The package used for the mbpfan daemon."; - }; + package = mkPackageOption pkgs "mbpfan" { }; verbose = mkOption { type = types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/mediatomb.nix b/nixpkgs/nixos/modules/services/misc/mediatomb.nix index 335b1b684b1a..d421d74c53ad 100644 --- a/nixpkgs/nixos/modules/services/misc/mediatomb.nix +++ b/nixpkgs/nixos/modules/services/misc/mediatomb.nix @@ -215,14 +215,7 @@ in { ''; }; - package = mkOption { - type = types.package; - default = pkgs.gerbera; - defaultText = literalExpression "pkgs.gerbera"; - description = lib.mdDoc '' - Underlying package to be used with the module. - ''; - }; + package = mkPackageOption pkgs "gerbera" { }; ps3Support = mkOption { type = types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/moonraker.nix b/nixpkgs/nixos/modules/services/misc/moonraker.nix index 797e145c47a6..0ee7e898cf76 100644 --- a/nixpkgs/nixos/modules/services/misc/moonraker.nix +++ b/nixpkgs/nixos/modules/services/misc/moonraker.nix @@ -18,12 +18,9 @@ in { services.moonraker = { enable = mkEnableOption (lib.mdDoc "Moonraker, an API web server for Klipper"); - package = mkOption { - type = with types; nullOr package; - default = pkgs.moonraker; - defaultText = literalExpression "pkgs.moonraker"; - example = literalExpression "pkgs.moonraker.override { useGpiod = true; }"; - description = lib.mdDoc "Moonraker package to use"; + package = mkPackageOption pkgs "moonraker" { + nullable = true; + example = "moonraker.override { useGpiod = true; }"; }; klipperSocket = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/nitter.nix b/nixpkgs/nixos/modules/services/misc/nitter.nix index 77f5459d117c..c2c462d46bb5 100644 --- a/nixpkgs/nixos/modules/services/misc/nitter.nix +++ b/nixpkgs/nixos/modules/services/misc/nitter.nix @@ -54,12 +54,7 @@ in services.nitter = { enable = mkEnableOption (lib.mdDoc "Nitter"); - package = mkOption { - default = pkgs.nitter; - type = types.package; - defaultText = literalExpression "pkgs.nitter"; - description = lib.mdDoc "The nitter derivation to use."; - }; + package = mkPackageOption pkgs "nitter" { }; server = { address = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix index 8fc1df93afb1..98134e94eeed 100644 --- a/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix +++ b/nixpkgs/nixos/modules/services/misc/ntfy-sh.nix @@ -12,12 +12,7 @@ in options.services.ntfy-sh = { enable = mkEnableOption (mdDoc "[ntfy-sh](https://ntfy.sh), a push notification service"); - package = mkOption { - type = types.package; - default = pkgs.ntfy-sh; - defaultText = literalExpression "pkgs.ntfy-sh"; - description = mdDoc "The ntfy.sh package to use."; - }; + package = mkPackageOption pkgs "ntfy-sh" { }; user = mkOption { default = "ntfy-sh"; diff --git a/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix index 47d08135f57e..536a4e4b0075 100644 --- a/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix +++ b/nixpkgs/nixos/modules/services/misc/nzbhydra2.nix @@ -22,12 +22,7 @@ in { lib.mdDoc "Open ports in the firewall for the NZBHydra2 web interface."; }; - package = mkOption { - type = types.package; - default = pkgs.nzbhydra2; - defaultText = literalExpression "pkgs.nzbhydra2"; - description = lib.mdDoc "NZBHydra2 package to use."; - }; + package = mkPackageOption pkgs "nzbhydra2" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/paperless.nix b/nixpkgs/nixos/modules/services/misc/paperless.nix index 1e0a8d0f928e..b3bc7d89009d 100644 --- a/nixpkgs/nixos/modules/services/misc/paperless.nix +++ b/nixpkgs/nixos/modules/services/misc/paperless.nix @@ -194,12 +194,7 @@ in description = lib.mdDoc "User under which Paperless runs."; }; - package = mkOption { - type = types.package; - default = pkgs.paperless-ngx; - defaultText = literalExpression "pkgs.paperless-ngx"; - description = lib.mdDoc "The Paperless package to use."; - }; + package = mkPackageOption pkgs "paperless-ngx" { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/plex.nix b/nixpkgs/nixos/modules/services/misc/plex.nix index 7fc76028c02a..164801605713 100644 --- a/nixpkgs/nixos/modules/services/misc/plex.nix +++ b/nixpkgs/nixos/modules/services/misc/plex.nix @@ -93,13 +93,10 @@ in ''; }; - package = mkOption { - type = types.package; - default = pkgs.plex; - defaultText = literalExpression "pkgs.plex"; - description = lib.mdDoc '' - The Plex package to use. Plex subscribers may wish to use their own - package here, pointing to subscriber-only server versions. + package = mkPackageOption pkgs "plex" { + extraDescription = '' + Plex subscribers may wish to use their own package here, + pointing to subscriber-only server versions. ''; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/polaris.nix b/nixpkgs/nixos/modules/services/misc/polaris.nix index 70f097f02840..83da486083b4 100644 --- a/nixpkgs/nixos/modules/services/misc/polaris.nix +++ b/nixpkgs/nixos/modules/services/misc/polaris.nix @@ -13,7 +13,7 @@ in services.polaris = { enable = mkEnableOption (lib.mdDoc "Polaris Music Server"); - package = mkPackageOptionMD pkgs "polaris" { }; + package = mkPackageOption pkgs "polaris" { }; user = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/portunus.nix b/nixpkgs/nixos/modules/services/misc/portunus.nix index d18881986970..3299b6404c2b 100644 --- a/nixpkgs/nixos/modules/services/misc/portunus.nix +++ b/nixpkgs/nixos/modules/services/misc/portunus.nix @@ -26,12 +26,7 @@ in ''; }; - package = mkOption { - type = types.package; - default = pkgs.portunus; - defaultText = lib.literalExpression "pkgs.portunus"; - description = lib.mdDoc "The Portunus package to use."; - }; + package = mkPackageOption pkgs "portunus" { }; seedPath = mkOption { type = types.nullOr types.path; diff --git a/nixpkgs/nixos/modules/services/misc/preload.nix b/nixpkgs/nixos/modules/services/misc/preload.nix new file mode 100644 index 000000000000..19b2531087dd --- /dev/null +++ b/nixpkgs/nixos/modules/services/misc/preload.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.preload; +in { + meta = { maintainers = pkgs.preload.meta.maintainers; }; + + options.services.preload = { + enable = mkEnableOption "preload"; + package = mkPackageOption pkgs "preload" { }; + }; + + config = mkIf cfg.enable { + systemd.services.preload = { + description = "Loads data into ram during idle time of CPU."; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + EnvironmentFile = "${cfg.package}/etc/conf.d/preload"; + ExecStart = "${getExe cfg.package} --foreground $PRELOAD_OPTS"; + Type = "simple"; + # Only preload data during CPU idle time + IOSchedulingClass = 3; + DynamicUser = true; + StateDirectory = "preload"; + }; + }; + }; +} diff --git a/nixpkgs/nixos/modules/services/misc/prowlarr.nix b/nixpkgs/nixos/modules/services/misc/prowlarr.nix index 836280d3e5fe..84d365003992 100644 --- a/nixpkgs/nixos/modules/services/misc/prowlarr.nix +++ b/nixpkgs/nixos/modules/services/misc/prowlarr.nix @@ -11,7 +11,7 @@ in services.prowlarr = { enable = mkEnableOption (lib.mdDoc "Prowlarr"); - package = mkPackageOptionMD pkgs "prowlarr" { }; + package = mkPackageOption pkgs "prowlarr" { }; openFirewall = mkOption { type = types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/pufferpanel.nix b/nixpkgs/nixos/modules/services/misc/pufferpanel.nix index 2022406c8325..b951d60cc5b9 100644 --- a/nixpkgs/nixos/modules/services/misc/pufferpanel.nix +++ b/nixpkgs/nixos/modules/services/misc/pufferpanel.nix @@ -33,7 +33,7 @@ in ''; }; - package = lib.mkPackageOptionMD pkgs "pufferpanel" { }; + package = lib.mkPackageOption pkgs "pufferpanel" { }; extraGroups = lib.mkOption { type = lib.types.listOf lib.types.str; diff --git a/nixpkgs/nixos/modules/services/misc/radarr.nix b/nixpkgs/nixos/modules/services/misc/radarr.nix index 834b092c0d14..618341cf614f 100644 --- a/nixpkgs/nixos/modules/services/misc/radarr.nix +++ b/nixpkgs/nixos/modules/services/misc/radarr.nix @@ -11,13 +11,7 @@ in services.radarr = { enable = mkEnableOption (lib.mdDoc "Radarr"); - package = mkOption { - description = lib.mdDoc "Radarr package to use"; - default = pkgs.radarr; - defaultText = literalExpression "pkgs.radarr"; - example = literalExpression "pkgs.radarr"; - type = types.package; - }; + package = mkPackageOption pkgs "radarr" { }; dataDir = mkOption { type = types.str; diff --git a/nixpkgs/nixos/modules/services/misc/readarr.nix b/nixpkgs/nixos/modules/services/misc/readarr.nix index dd4fef6e598d..3c84b13485a4 100644 --- a/nixpkgs/nixos/modules/services/misc/readarr.nix +++ b/nixpkgs/nixos/modules/services/misc/readarr.nix @@ -16,12 +16,7 @@ in description = lib.mdDoc "The directory where Readarr stores its data files."; }; - package = mkOption { - type = types.package; - default = pkgs.readarr; - defaultText = literalExpression "pkgs.readarr"; - description = lib.mdDoc "The Readarr package to use"; - }; + package = mkPackageOption pkgs "readarr" { }; openFirewall = mkOption { type = types.bool; diff --git a/nixpkgs/nixos/modules/services/misc/redmine.nix b/nixpkgs/nixos/modules/services/misc/redmine.nix index 20fa71507b6b..e3941d2e29de 100644 --- a/nixpkgs/nixos/modules/services/misc/redmine.nix +++ b/nixpkgs/nixos/modules/services/misc/redmine.nix @@ -1,7 +1,8 @@ { config, lib, pkgs, ... }: let - inherit (lib) mkBefore mkDefault mkEnableOption mkIf mkOption mkRemovedOptionModule types; + inherit (lib) mkBefore mkDefault mkEnableOption mkPackageOption + mkIf mkOption mkRemovedOptionModule types; inherit (lib) concatStringsSep literalExpression mapAttrsToList; inherit (lib) optional optionalAttrs optionalString; @@ -51,12 +52,8 @@ in services.redmine = { enable = mkEnableOption (lib.mdDoc "Redmine"); - package = mkOption { - type = types.package; - default = pkgs.redmine; - defaultText = literalExpression "pkgs.redmine"; - description = lib.mdDoc "Which Redmine package to use."; - example = literalExpression "pkgs.redmine.override { ruby = pkgs.ruby_2_7; }"; + package = mkPackageOption pkgs "redmine" { + example = "redmine.override { ruby = pkgs.ruby_2_7; }"; }; user = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/rippled.nix b/nixpkgs/nixos/modules/services/misc/rippled.nix index d14b6421b742..68a831894250 100644 --- a/nixpkgs/nixos/modules/services/misc/rippled.nix +++ b/nixpkgs/nixos/modules/services/misc/rippled.nix @@ -209,12 +209,7 @@ in services.rippled = { enable = mkEnableOption (lib.mdDoc "rippled"); - package = mkOption { - description = lib.mdDoc "Which rippled package to use."; - type = types.package; - default = pkgs.rippled; - defaultText = literalExpression "pkgs.rippled"; - }; + package = mkPackageOption pkgs "rippled" { }; ports = mkOption { description = lib.mdDoc "Ports exposed by rippled"; diff --git a/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix b/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix index 1cdfdeceabcd..979f4f14d383 100644 --- a/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix +++ b/nixpkgs/nixos/modules/services/misc/rmfakecloud.nix @@ -11,14 +11,11 @@ in { services.rmfakecloud = { enable = mkEnableOption (lib.mdDoc "rmfakecloud remarkable self-hosted cloud"); - package = mkOption { - type = types.package; - default = pkgs.rmfakecloud; - defaultText = literalExpression "pkgs.rmfakecloud"; - description = lib.mdDoc '' - rmfakecloud package to use. - + package = mkPackageOption pkgs "rmfakecloud" { + extraDescription = '' + ::: {.note} The default does not include the web user interface. + ::: ''; }; diff --git a/nixpkgs/nixos/modules/services/misc/rshim.nix b/nixpkgs/nixos/modules/services/misc/rshim.nix index 706cf9136b00..ae13f7d208f6 100644 --- a/nixpkgs/nixos/modules/services/misc/rshim.nix +++ b/nixpkgs/nixos/modules/services/misc/rshim.nix @@ -14,7 +14,7 @@ in options.services.rshim = { enable = lib.mkEnableOption (lib.mdDoc "user-space rshim driver for the BlueField SoC"); - package = lib.mkPackageOptionMD pkgs "rshim-user-space" { }; + package = lib.mkPackageOption pkgs "rshim-user-space" { }; backend = lib.mkOption { type = with lib.types; nullOr (enum [ "usb" "pcie" "pcie_lf" ]); diff --git a/nixpkgs/nixos/modules/services/misc/sickbeard.nix b/nixpkgs/nixos/modules/services/misc/sickbeard.nix index bd8d8d8fa7cc..f141660ced86 100644 --- a/nixpkgs/nixos/modules/services/misc/sickbeard.nix +++ b/nixpkgs/nixos/modules/services/misc/sickbeard.nix @@ -22,12 +22,9 @@ in default = false; description = lib.mdDoc "Whether to enable the sickbeard server."; }; - package = mkOption { - type = types.package; - default = pkgs.sickbeard; - defaultText = literalExpression "pkgs.sickbeard"; - example = literalExpression "pkgs.sickrage"; - description =lib.mdDoc '' + package = mkPackageOption pkgs "sickbeard" { + example = "sickrage"; + extraDescription = '' Enable `pkgs.sickrage` or `pkgs.sickgear` as an alternative to SickBeard ''; diff --git a/nixpkgs/nixos/modules/services/misc/sonarr.nix b/nixpkgs/nixos/modules/services/misc/sonarr.nix index 65c51d9677d9..ec59988d2b9a 100644 --- a/nixpkgs/nixos/modules/services/misc/sonarr.nix +++ b/nixpkgs/nixos/modules/services/misc/sonarr.nix @@ -36,14 +36,7 @@ in description = lib.mdDoc "Group under which Sonaar runs."; }; - package = mkOption { - type = types.package; - default = pkgs.sonarr; - defaultText = literalExpression "pkgs.sonarr"; - description = lib.mdDoc '' - Sonarr package to use. - ''; - }; + package = mkPackageOption pkgs "sonarr" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix index f2b09f4bc4b6..aa803d3bb693 100644 --- a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix +++ b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix @@ -1,6 +1,15 @@ { config, pkgs, lib, ... }: -with lib; + let + inherit (builtins) head tail; + inherit (lib) generators maintainers types; + inherit (lib.attrsets) attrValues filterAttrs mapAttrs mapAttrsToList recursiveUpdate; + inherit (lib.lists) flatten optional optionals; + inherit (lib.options) literalExpression mkEnableOption mkOption mkPackageOption; + inherit (lib.strings) concatMapStringsSep concatStringsSep optionalString versionOlder; + inherit (lib.trivial) mapNullable; + inherit (lib.modules) mkBefore mkDefault mkForce mkIf mkMerge + mkRemovedOptionModule mkRenamedOptionModule; inherit (config.services) nginx postfix postgresql redis; inherit (config.users) users groups; cfg = config.services.sourcehut; @@ -671,14 +680,8 @@ in }; git = { - package = mkOption { - type = types.package; - default = pkgs.git; - defaultText = literalExpression "pkgs.git"; - example = literalExpression "pkgs.gitFull"; - description = lib.mdDoc '' - Git package for git.sr.ht. This can help silence collisions. - ''; + package = mkPackageOption pkgs "git" { + example = "gitFull"; }; fcgiwrap.preforkProcess = mkOption { description = lib.mdDoc "Number of fcgiwrap processes to prefork."; @@ -688,14 +691,7 @@ in }; hg = { - package = mkOption { - type = types.package; - default = pkgs.mercurial; - defaultText = literalExpression "pkgs.mercurial"; - description = lib.mdDoc '' - Mercurial package for hg.sr.ht. This can help silence collisions. - ''; - }; + package = mkPackageOption pkgs "mercurial" { }; cloneBundles = mkOption { type = types.bool; default = false; @@ -1316,6 +1312,11 @@ in (import ./service.nix "paste" { inherit configIniOfService; port = 5011; + extraServices.pastesrht-api = { + serviceConfig.Restart = "always"; + serviceConfig.RestartSec = "5s"; + serviceConfig.ExecStart = "${pkgs.sourcehut.pastesrht}/bin/pastesrht-api -b ${cfg.listenAddress}:${toString (cfg.paste.port + 100)}"; + }; }) (import ./service.nix "todo" { @@ -1369,5 +1370,5 @@ in ]; meta.doc = ./default.md; - meta.maintainers = with maintainers; [ tomberek ]; + meta.maintainers = with maintainers; [ tomberek nessdoor ]; } diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix index f08d5eb46871..4a8289b4d403 100644 --- a/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix +++ b/nixpkgs/nixos/modules/services/misc/sourcehut/service.nix @@ -3,117 +3,133 @@ srv: , srvsrht ? "${srv}srht" # Because "buildsrht" does not follow that pattern (missing an "s"). , iniKey ? "${srv}.sr.ht" , webhooks ? false -, extraTimers ? {} -, mainService ? {} -, extraServices ? {} -, extraConfig ? {} +, extraTimers ? { } +, mainService ? { } +, extraServices ? { } +, extraConfig ? { } , port }: { config, lib, pkgs, ... }: -with lib; let + inherit (lib) types; + inherit (lib.attrsets) mapAttrs optionalAttrs; + inherit (lib.lists) optional; + inherit (lib.modules) mkBefore mkDefault mkForce mkIf mkMerge; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.strings) concatStringsSep hasSuffix optionalString; inherit (config.services) postgresql; redis = config.services.redis.servers."sourcehut-${srvsrht}"; inherit (config.users) users; cfg = config.services.sourcehut; configIni = configIniOfService srv; srvCfg = cfg.${srv}; - baseService = serviceName: { allowStripe ? false }: extraService: let - runDir = "/run/sourcehut/${serviceName}"; - rootDir = "/run/sourcehut/chroots/${serviceName}"; + baseService = serviceName: { allowStripe ? false }: extraService: + let + runDir = "/run/sourcehut/${serviceName}"; + rootDir = "/run/sourcehut/chroots/${serviceName}"; in - mkMerge [ extraService { - after = [ "network.target" ] ++ - optional cfg.postgresql.enable "postgresql.service" ++ - optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; - requires = - optional cfg.postgresql.enable "postgresql.service" ++ - optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; - path = [ pkgs.gawk ]; - environment.HOME = runDir; - serviceConfig = { - User = mkDefault srvCfg.user; - Group = mkDefault srvCfg.group; - RuntimeDirectory = [ - "sourcehut/${serviceName}" - # Used by *srht-keys which reads ../config.ini - "sourcehut/${serviceName}/subdir" - "sourcehut/chroots/${serviceName}" - ]; - RuntimeDirectoryMode = "2750"; - # No need for the chroot path once inside the chroot - InaccessiblePaths = [ "-+${rootDir}" ]; - # g+rx is for group members (eg. fcgiwrap or nginx) - # to read Git/Mercurial repositories, buildlogs, etc. - # o+x is for intermediate directories created by BindPaths= and like, - # as they're owned by root:root. - UMask = "0026"; - RootDirectory = rootDir; - RootDirectoryStartOnly = true; - PrivateTmp = true; - MountAPIVFS = true; - # config.ini is looked up in there, before /etc/srht/config.ini - # Note that it fails to be set in ExecStartPre= - WorkingDirectory = mkDefault ("-"+runDir); - BindReadOnlyPaths = [ - builtins.storeDir - "/etc" - "/run/booted-system" - "/run/current-system" - "/run/systemd" - ] ++ - optional cfg.postgresql.enable "/run/postgresql" ++ - optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}"; - # LoadCredential= are unfortunately not available in ExecStartPre= - # Hence this one is run as root (the +) with RootDirectoryStartOnly= - # to reach credentials wherever they are. - # Note that each systemd service gets its own ${runDir}/config.ini file. - ExecStartPre = mkBefore [("+"+pkgs.writeShellScript "${serviceName}-credentials" '' - set -x - # Replace values beginning with a '<' by the content of the file whose name is after. - gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} | - ${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"} - install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini - '')]; - # The following options are only for optimizing: - # systemd-analyze security - AmbientCapabilities = ""; - CapabilityBoundingSet = ""; - # ProtectClock= adds DeviceAllow=char-rtc r - DeviceAllow = ""; - LockPersonality = true; - MemoryDenyWriteExecute = true; - NoNewPrivileges = true; - PrivateDevices = true; - PrivateMounts = true; - PrivateNetwork = mkDefault false; - PrivateUsers = true; - ProcSubset = "pid"; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectProc = "invisible"; - ProtectSystem = "strict"; - RemoveIPC = true; - RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - #SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ]; - #SocketBindDeny = "any"; - SystemCallFilter = [ - "@system-service" - "~@aio" "~@keyring" "~@memlock" "~@privileged" "~@timer" - "@chown" "@setuid" - ]; - SystemCallArchitectures = "native"; - }; - } ]; + mkMerge [ + extraService + { + after = [ "network.target" ] ++ + optional cfg.postgresql.enable "postgresql.service" ++ + optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; + requires = + optional cfg.postgresql.enable "postgresql.service" ++ + optional cfg.redis.enable "redis-sourcehut-${srvsrht}.service"; + path = [ pkgs.gawk ]; + environment.HOME = runDir; + serviceConfig = { + User = mkDefault srvCfg.user; + Group = mkDefault srvCfg.group; + RuntimeDirectory = [ + "sourcehut/${serviceName}" + # Used by *srht-keys which reads ../config.ini + "sourcehut/${serviceName}/subdir" + "sourcehut/chroots/${serviceName}" + ]; + RuntimeDirectoryMode = "2750"; + # No need for the chroot path once inside the chroot + InaccessiblePaths = [ "-+${rootDir}" ]; + # g+rx is for group members (eg. fcgiwrap or nginx) + # to read Git/Mercurial repositories, buildlogs, etc. + # o+x is for intermediate directories created by BindPaths= and like, + # as they're owned by root:root. + UMask = "0026"; + RootDirectory = rootDir; + RootDirectoryStartOnly = true; + PrivateTmp = true; + MountAPIVFS = true; + # config.ini is looked up in there, before /etc/srht/config.ini + # Note that it fails to be set in ExecStartPre= + WorkingDirectory = mkDefault ("-" + runDir); + BindReadOnlyPaths = [ + builtins.storeDir + "/etc" + "/run/booted-system" + "/run/current-system" + "/run/systemd" + ] ++ + optional cfg.postgresql.enable "/run/postgresql" ++ + optional cfg.redis.enable "/run/redis-sourcehut-${srvsrht}"; + # LoadCredential= are unfortunately not available in ExecStartPre= + # Hence this one is run as root (the +) with RootDirectoryStartOnly= + # to reach credentials wherever they are. + # Note that each systemd service gets its own ${runDir}/config.ini file. + ExecStartPre = mkBefore [ + ("+" + pkgs.writeShellScript "${serviceName}-credentials" '' + set -x + # Replace values beginning with a '<' by the content of the file whose name is after. + gawk '{ if (match($0,/^([^=]+=)<(.+)/,m)) { getline f < m[2]; print m[1] f } else print $0 }' ${configIni} | + ${optionalString (!allowStripe) "gawk '!/^stripe-secret-key=/' |"} + install -o ${srvCfg.user} -g root -m 400 /dev/stdin ${runDir}/config.ini + '') + ]; + # The following options are only for optimizing: + # systemd-analyze security + AmbientCapabilities = ""; + CapabilityBoundingSet = ""; + # ProtectClock= adds DeviceAllow=char-rtc r + DeviceAllow = ""; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateNetwork = mkDefault false; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + #SocketBindAllow = [ "tcp:${toString srvCfg.port}" "tcp:${toString srvCfg.prometheusPort}" ]; + #SocketBindDeny = "any"; + SystemCallFilter = [ + "@system-service" + "~@aio" + "~@keyring" + "~@memlock" + "~@privileged" + "~@timer" + "@chown" + "@setuid" + ]; + SystemCallArchitectures = "native"; + }; + } + ]; in { options.services.sourcehut.${srv} = { @@ -173,7 +189,7 @@ in gunicorn = { extraArgs = mkOption { type = with types; listOf str; - default = ["--timeout 120" "--workers 1" "--log-level=info"]; + default = [ "--timeout 120" "--workers 1" "--log-level=info" ]; description = lib.mdDoc "Extra arguments passed to Gunicorn."; }; }; @@ -181,7 +197,7 @@ in webhooks = { extraArgs = mkOption { type = with types; listOf str; - default = ["--loglevel DEBUG" "--pool eventlet" "--without-heartbeat"]; + default = [ "--loglevel DEBUG" "--pool eventlet" "--without-heartbeat" ]; description = lib.mdDoc "Extra arguments passed to the Celery responsible for webhooks."; }; celeryConfig = mkOption { @@ -192,216 +208,237 @@ in }; }; - config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [ extraConfig { - users = { + config = lib.mkIf (cfg.enable && srvCfg.enable) (mkMerge [ + extraConfig + { users = { - "${srvCfg.user}" = { - isSystemUser = true; - group = mkDefault srvCfg.group; - description = mkDefault "sourcehut user for ${srv}.sr.ht"; + users = { + "${srvCfg.user}" = { + isSystemUser = true; + group = mkDefault srvCfg.group; + description = mkDefault "sourcehut user for ${srv}.sr.ht"; + }; }; + groups = { + "${srvCfg.group}" = { }; + } // optionalAttrs + (cfg.postgresql.enable + && hasSuffix "0" (postgresql.settings.unix_socket_permissions or "")) + { + "postgres".members = [ srvCfg.user ]; + } // optionalAttrs + (cfg.redis.enable + && hasSuffix "0" (redis.settings.unixsocketperm or "")) + { + "redis-sourcehut-${srvsrht}".members = [ srvCfg.user ]; + }; }; - groups = { - "${srvCfg.group}" = { }; - } // optionalAttrs (cfg.postgresql.enable - && hasSuffix "0" (postgresql.settings.unix_socket_permissions or "")) { - "postgres".members = [ srvCfg.user ]; - } // optionalAttrs (cfg.redis.enable - && hasSuffix "0" (redis.settings.unixsocketperm or "")) { - "redis-sourcehut-${srvsrht}".members = [ srvCfg.user ]; - }; - }; - services.nginx = mkIf cfg.nginx.enable { - virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [ { - forceSSL = mkDefault true; - locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}"; - locations."/static" = { - root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}"; - extraConfig = mkDefault '' - expires 30d; - ''; - }; - locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) { - proxyPass = cfg.settings.${iniKey}.api-origin; - extraConfig = '' - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + services.nginx = mkIf cfg.nginx.enable { + virtualHosts."${srv}.${cfg.settings."sr.ht".global-domain}" = mkMerge [{ + forceSSL = mkDefault true; + locations."/".proxyPass = "http://${cfg.listenAddress}:${toString srvCfg.port}"; + locations."/static" = { + root = "${pkgs.sourcehut.${srvsrht}}/${pkgs.sourcehut.python.sitePackages}/${srvsrht}"; + extraConfig = mkDefault '' + expires 30d; + ''; + }; + locations."/query" = mkIf (cfg.settings.${iniKey} ? api-origin) { + proxyPass = cfg.settings.${iniKey}.api-origin; + extraConfig = '' + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain; charset=utf-8'; - add_header 'Content-Length' 0; - return 204; - } + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } - add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; - ''; - }; - } cfg.nginx.virtualHost ]; - }; + add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; + ''; + }; + } + cfg.nginx.virtualHost]; + }; - services.postgresql = mkIf cfg.postgresql.enable { - authentication = '' - local ${srvCfg.postgresql.database} ${srvCfg.user} trust - ''; - ensureDatabases = [ srvCfg.postgresql.database ]; - ensureUsers = map (name: { - inherit name; - # We don't use it because we have a special default database name with dots. - # TODO(for maintainers of sourcehut): migrate away from custom preStart script. - ensureDBOwnership = false; - }) [srvCfg.user]; - }; + services.postgresql = mkIf cfg.postgresql.enable { + authentication = '' + local ${srvCfg.postgresql.database} ${srvCfg.user} trust + ''; + ensureDatabases = [ srvCfg.postgresql.database ]; + ensureUsers = map + (name: { + inherit name; + # We don't use it because we have a special default database name with dots. + # TODO(for maintainers of sourcehut): migrate away from custom preStart script. + ensureDBOwnership = false; + }) [ srvCfg.user ]; + }; - services.sourcehut.settings = mkMerge [ - { - "${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}"; - } + services.sourcehut.settings = mkMerge [ + { + "${srv}.sr.ht".origin = mkDefault "https://${srv}.${cfg.settings."sr.ht".global-domain}"; + } - (mkIf cfg.postgresql.enable { - "${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql"; - }) - ]; + (mkIf cfg.postgresql.enable { + "${srv}.sr.ht".connection-string = mkDefault "postgresql:///${srvCfg.postgresql.database}?user=${srvCfg.user}&host=/run/postgresql"; + }) + ]; - services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable { - enable = true; - databases = 3; - syslog = true; - # TODO: set a more informed value - save = mkDefault [ [1800 10] [300 100] ]; - settings = { + services.redis.servers."sourcehut-${srvsrht}" = mkIf cfg.redis.enable { + enable = true; + databases = 3; + syslog = true; # TODO: set a more informed value - maxmemory = "128MB"; - maxmemory-policy = "volatile-ttl"; + save = mkDefault [ [ 1800 10 ] [ 300 100 ] ]; + settings = { + # TODO: set a more informed value + maxmemory = "128MB"; + maxmemory-policy = "volatile-ttl"; + }; }; - }; - systemd.services = mkMerge [ - { - "${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [ + systemd.services = mkMerge [ { - description = "sourcehut ${srv}.sr.ht website service"; - before = optional cfg.nginx.enable "nginx.service"; - wants = optional cfg.nginx.enable "nginx.service"; - wantedBy = [ "multi-user.target" ]; - path = optional cfg.postgresql.enable postgresql.package; - # Beware: change in credentials' content will not trigger restart. - restartTriggers = [ configIni ]; - serviceConfig = { - Type = "simple"; - Restart = mkDefault "always"; - #RestartSec = mkDefault "2min"; - StateDirectory = [ "sourcehut/${srvsrht}" ]; - StateDirectoryMode = "2750"; - ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs; - }; - preStart = let - version = pkgs.sourcehut.${srvsrht}.version; - stateDir = "/var/lib/sourcehut/${srvsrht}"; - in mkBefore '' - set -x - # Use the /run/sourcehut/${srvsrht}/config.ini - # installed by a previous ExecStartPre= in baseService - cd /run/sourcehut/${srvsrht} + "${srvsrht}" = baseService srvsrht { allowStripe = srv == "meta"; } (mkMerge [ + { + description = "sourcehut ${srv}.sr.ht website service"; + before = optional cfg.nginx.enable "nginx.service"; + wants = optional cfg.nginx.enable "nginx.service"; + wantedBy = [ "multi-user.target" ]; + path = optional cfg.postgresql.enable postgresql.package; + # Beware: change in credentials' content will not trigger restart. + restartTriggers = [ configIni ]; + serviceConfig = { + Type = "simple"; + Restart = mkDefault "always"; + #RestartSec = mkDefault "2min"; + StateDirectory = [ "sourcehut/${srvsrht}" ]; + StateDirectoryMode = "2750"; + ExecStart = "${cfg.python}/bin/gunicorn ${srvsrht}.app:app --name ${srvsrht} --bind ${cfg.listenAddress}:${toString srvCfg.port} " + concatStringsSep " " srvCfg.gunicorn.extraArgs; + }; + preStart = + let + version = pkgs.sourcehut.${srvsrht}.version; + stateDir = "/var/lib/sourcehut/${srvsrht}"; + in + mkBefore '' + set -x + # Use the /run/sourcehut/${srvsrht}/config.ini + # installed by a previous ExecStartPre= in baseService + cd /run/sourcehut/${srvsrht} - if test ! -e ${stateDir}/db; then - # Setup the initial database. - # Note that it stamps the alembic head afterward - ${cfg.python}/bin/${srvsrht}-initdb - echo ${version} >${stateDir}/db - fi + if test ! -e ${stateDir}/db; then + # Setup the initial database. + # Note that it stamps the alembic head afterward + ${cfg.python}/bin/${srvsrht}-initdb + echo ${version} >${stateDir}/db + fi - ${optionalString cfg.settings.${iniKey}.migrate-on-upgrade '' - if [ "$(cat ${stateDir}/db)" != "${version}" ]; then - # Manage schema migrations using alembic - ${cfg.python}/bin/${srvsrht}-migrate -a upgrade head - echo ${version} >${stateDir}/db - fi - ''} + ${optionalString cfg.settings.${iniKey}.migrate-on-upgrade '' + if [ "$(cat ${stateDir}/db)" != "${version}" ]; then + # Manage schema migrations using alembic + ${cfg.python}/bin/${srvsrht}-migrate -a upgrade head + echo ${version} >${stateDir}/db + fi + ''} - # Update copy of each users' profile to the latest - # See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain> - if test ! -e ${stateDir}/webhook; then - # Update ${iniKey}'s users' profile copy to the latest - ${cfg.python}/bin/srht-update-profiles ${iniKey} - touch ${stateDir}/webhook - fi - ''; - } mainService ]); - } + # Update copy of each users' profile to the latest + # See https://lists.sr.ht/~sircmpwn/sr.ht-admins/<20190302181207.GA13778%40cirno.my.domain> + if test ! -e ${stateDir}/webhook; then + # Update ${iniKey}'s users' profile copy to the latest + ${cfg.python}/bin/srht-update-profiles ${iniKey} + touch ${stateDir}/webhook + fi + ''; + } + mainService + ]); + } - (mkIf webhooks { - "${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" {} - { - description = "sourcehut ${srv}.sr.ht webhooks service"; - after = [ "${srvsrht}.service" ]; - wantedBy = [ "${srvsrht}.service" ]; - partOf = [ "${srvsrht}.service" ]; - preStart = '' - cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \ - /run/sourcehut/${srvsrht}-webhooks/celeryconfig.py - ''; - serviceConfig = { - Type = "simple"; - Restart = "always"; - ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs; - # Avoid crashing: os.getloadavg() - ProcSubset = mkForce "all"; + (mkIf webhooks { + "${srvsrht}-webhooks" = baseService "${srvsrht}-webhooks" { } + { + description = "sourcehut ${srv}.sr.ht webhooks service"; + after = [ "${srvsrht}.service" ]; + wantedBy = [ "${srvsrht}.service" ]; + partOf = [ "${srvsrht}.service" ]; + preStart = '' + cp ${pkgs.writeText "${srvsrht}-webhooks-celeryconfig.py" srvCfg.webhooks.celeryConfig} \ + /run/sourcehut/${srvsrht}-webhooks/celeryconfig.py + ''; + serviceConfig = { + Type = "simple"; + Restart = "always"; + ExecStart = "${cfg.python}/bin/celery --app ${srvsrht}.webhooks worker --hostname ${srvsrht}-webhooks@%%h " + concatStringsSep " " srvCfg.webhooks.extraArgs; + # Avoid crashing: os.getloadavg() + ProcSubset = mkForce "all"; + }; }; - }; - }) + }) - (mapAttrs (timerName: timer: (baseService timerName {} (mkMerge [ - { - description = "sourcehut ${timerName} service"; - after = [ "network.target" "${srvsrht}.service" ]; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${cfg.python}/bin/${timerName}"; - }; - } - (timer.service or {}) - ]))) extraTimers) + (mapAttrs + (timerName: timer: (baseService timerName { } (mkMerge [ + { + description = "sourcehut ${timerName} service"; + after = [ "network.target" "${srvsrht}.service" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${cfg.python}/bin/${timerName}"; + }; + } + (timer.service or { }) + ]))) + extraTimers) - (mapAttrs (serviceName: extraService: baseService serviceName {} (mkMerge [ - { - description = "sourcehut ${serviceName} service"; - # So that extraServices have the PostgreSQL database initialized. - after = [ "${srvsrht}.service" ]; - wantedBy = [ "${srvsrht}.service" ]; - partOf = [ "${srvsrht}.service" ]; - serviceConfig = { - Type = "simple"; - Restart = mkDefault "always"; - }; - } - extraService - ])) extraServices) + (mapAttrs + (serviceName: extraService: baseService serviceName { } (mkMerge [ + { + description = "sourcehut ${serviceName} service"; + # So that extraServices have the PostgreSQL database initialized. + after = [ "${srvsrht}.service" ]; + wantedBy = [ "${srvsrht}.service" ]; + partOf = [ "${srvsrht}.service" ]; + serviceConfig = { + Type = "simple"; + Restart = mkDefault "always"; + }; + } + extraService + ])) + extraServices) - # Work around 'pq: permission denied for schema public' with postgres v15. - # See https://github.com/NixOS/nixpkgs/issues/216989 - # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741 - # TODO(to maintainers of sourcehut): please migrate away from this workaround - # by migrating away from database name defaults with dots. - (lib.mkIf ( - cfg.postgresql.enable - && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0" - ) { - postgresql.postStart = (lib.mkAfter '' - $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";' - ''); - } - ) - ]; + # Work around 'pq: permission denied for schema public' with postgres v15. + # See https://github.com/NixOS/nixpkgs/issues/216989 + # Workaround taken from nixos/forgejo: https://github.com/NixOS/nixpkgs/pull/262741 + # TODO(to maintainers of sourcehut): please migrate away from this workaround + # by migrating away from database name defaults with dots. + (lib.mkIf + ( + cfg.postgresql.enable + && lib.strings.versionAtLeast config.services.postgresql.package.version "15.0" + ) + { + postgresql.postStart = (lib.mkAfter '' + $PSQL -tAc 'ALTER DATABASE "${srvCfg.postgresql.database}" OWNER TO "${srvCfg.user}";' + ''); + } + ) + ]; - systemd.timers = mapAttrs (timerName: timer: - { - description = "sourcehut timer for ${timerName}"; - wantedBy = [ "timers.target" ]; - inherit (timer) timerConfig; - }) extraTimers; - } ]); + systemd.timers = mapAttrs + (timerName: timer: + { + description = "sourcehut timer for ${timerName}"; + wantedBy = [ "timers.target" ]; + inherit (timer) timerConfig; + }) + extraTimers; + } + ]); } diff --git a/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix b/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix index 8437441c752a..0d8830dbd5be 100644 --- a/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix +++ b/nixpkgs/nixos/modules/services/misc/spice-autorandr.nix @@ -7,7 +7,7 @@ in options = { services.spice-autorandr = { enable = lib.mkEnableOption (lib.mdDoc "spice-autorandr service that will automatically resize display to match SPICE client window size."); - package = lib.mkPackageOptionMD pkgs "spice-autorandr" { }; + package = lib.mkPackageOption pkgs "spice-autorandr" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix b/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix index 6c817e429ac6..2b4304365618 100644 --- a/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix +++ b/nixpkgs/nixos/modules/services/misc/spice-webdavd.nix @@ -9,12 +9,7 @@ in services.spice-webdavd = { enable = mkEnableOption (lib.mdDoc "the spice guest webdav proxy daemon"); - package = mkOption { - default = pkgs.phodav; - defaultText = literalExpression "pkgs.phodav"; - type = types.package; - description = lib.mdDoc "spice-webdavd provider package to use."; - }; + package = mkPackageOption pkgs "phodav" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix index 63d3e3d2a857..2d7d29b2e717 100644 --- a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix +++ b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix @@ -71,12 +71,7 @@ in }; }; - package = mkOption { - type = types.package; - default = pkgs.tandoor-recipes; - defaultText = literalExpression "pkgs.tandoor-recipes"; - description = lib.mdDoc "The Tandoor Recipes package to use."; - }; + package = mkPackageOption pkgs "tandoor-recipes" { }; }; config = mkIf cfg.enable { diff --git a/nixpkgs/nixos/modules/services/misc/tautulli.nix b/nixpkgs/nixos/modules/services/misc/tautulli.nix index b29e9dc0c8d5..e379628c8ce6 100644 --- a/nixpkgs/nixos/modules/services/misc/tautulli.nix +++ b/nixpkgs/nixos/modules/services/misc/tautulli.nix @@ -50,14 +50,7 @@ in description = lib.mdDoc "Group under which Tautulli runs."; }; - package = mkOption { - type = types.package; - default = pkgs.tautulli; - defaultText = literalExpression "pkgs.tautulli"; - description = lib.mdDoc '' - The Tautulli package to use. - ''; - }; + package = mkPackageOption pkgs "tautulli" { }; }; }; diff --git a/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix b/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix index 1076c814e86c..f6f2d49733e6 100644 --- a/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix +++ b/nixpkgs/nixos/modules/services/misc/tp-auto-kbbl.nix @@ -11,12 +11,7 @@ in { services.tp-auto-kbbl = { enable = mkEnableOption (lib.mdDoc "auto toggle keyboard back-lighting on Thinkpads (and maybe other laptops) for Linux"); - package = mkOption { - type = types.package; - default = pkgs.tp-auto-kbbl; - defaultText = literalExpression "pkgs.tp-auto-kbbl"; - description = lib.mdDoc "Package providing {command}`tp-auto-kbbl`."; - }; + package = mkPackageOption pkgs "tp-auto-kbbl" { }; arguments = mkOption { type = types.listOf types.str; diff --git a/nixpkgs/nixos/modules/services/misc/xmrig.nix b/nixpkgs/nixos/modules/services/misc/xmrig.nix index f75b47ffeced..8ad2d049f8a9 100644 --- a/nixpkgs/nixos/modules/services/misc/xmrig.nix +++ b/nixpkgs/nixos/modules/services/misc/xmrig.nix @@ -15,12 +15,8 @@ with lib; services.xmrig = { enable = mkEnableOption (lib.mdDoc "XMRig Mining Software"); - package = mkOption { - type = types.package; - default = pkgs.xmrig; - defaultText = literalExpression "pkgs.xmrig"; - example = literalExpression "pkgs.xmrig-mo"; - description = lib.mdDoc "XMRig package to use."; + package = mkPackageOption pkgs "xmrig" { + example = "xmrig-mo"; }; settings = mkOption { diff --git a/nixpkgs/nixos/modules/services/misc/zookeeper.nix b/nixpkgs/nixos/modules/services/misc/zookeeper.nix index fb51be698e72..b1c0b80648c6 100644 --- a/nixpkgs/nixos/modules/services/misc/zookeeper.nix +++ b/nixpkgs/nixos/modules/services/misc/zookeeper.nix @@ -103,12 +103,7 @@ in { ''; }; - package = mkOption { - description = lib.mdDoc "The zookeeper package to use"; - default = pkgs.zookeeper; - defaultText = literalExpression "pkgs.zookeeper"; - type = types.package; - }; + package = mkPackageOption pkgs "zookeeper" { }; jre = mkOption { description = lib.mdDoc "The JRE with which to run Zookeeper"; |