diff options
Diffstat (limited to 'nixpkgs/nixos/modules')
27 files changed, 274 insertions, 304 deletions
diff --git a/nixpkgs/nixos/modules/hardware/decklink.nix b/nixpkgs/nixos/modules/hardware/decklink.nix new file mode 100644 index 000000000000..d179e1d7634f --- /dev/null +++ b/nixpkgs/nixos/modules/hardware/decklink.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.hardware.decklink; + kernelPackages = config.boot.kernelPackages; +in +{ + options.hardware.decklink.enable = lib.mkEnableOption "hardware support for the Blackmagic Design Decklink audio/video interfaces"; + + config = lib.mkIf cfg.enable { + boot.kernelModules = [ "blackmagic" "blackmagic-io" "snd_blackmagic-io" ]; + boot.extraModulePackages = [ kernelPackages.decklink ]; + systemd.packages = [ pkgs.blackmagic-desktop-video ]; + systemd.services.DesktopVideoHelper.wantedBy = [ "multi-user.target" ]; + }; +} diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix index 9e5d417046b8..c0abfaa08817 100644 --- a/nixpkgs/nixos/modules/module-list.nix +++ b/nixpkgs/nixos/modules/module-list.nix @@ -55,6 +55,7 @@ ./hardware/cpu/amd-sev.nix ./hardware/cpu/intel-microcode.nix ./hardware/cpu/intel-sgx.nix + ./hardware/decklink.nix ./hardware/device-tree.nix ./hardware/digitalbitbox.nix ./hardware/flipperzero.nix @@ -395,7 +396,6 @@ ./services/continuous-integration/gitlab-runner.nix ./services/continuous-integration/gocd-agent/default.nix ./services/continuous-integration/gocd-server/default.nix - ./services/continuous-integration/hail.nix ./services/continuous-integration/hercules-ci-agent/default.nix ./services/continuous-integration/hydra/default.nix ./services/continuous-integration/jenkins/default.nix diff --git a/nixpkgs/nixos/modules/security/acme/default.nix b/nixpkgs/nixos/modules/security/acme/default.nix index 8aee71c864d0..222a25cf11dc 100644 --- a/nixpkgs/nixos/modules/security/acme/default.nix +++ b/nixpkgs/nixos/modules/security/acme/default.nix @@ -1,6 +1,8 @@ { config, lib, pkgs, options, ... }: with lib; let + + cfg = config.security.acme; opt = options.security.acme; user = if cfg.useRoot then "root" else "acme"; @@ -14,6 +16,36 @@ let mkAccountHash = acmeServer: data: mkHash "${toString acmeServer} ${data.keyType} ${data.email}"; accountDirRoot = "/var/lib/acme/.lego/accounts/"; + lockdir = "/run/acme/"; + concurrencyLockfiles = map (n: "${toString n}.lock") (lib.range 1 cfg.maxConcurrentRenewals); + # Assign elements of `baseList` to each element of `needAssignmentList`, until the latter is exhausted. + # returns: [{fst = "element of baseList"; snd = "element of needAssignmentList"}] + roundRobinAssign = baseList: needAssignmentList: + if baseList == [] then [] + else _rrCycler baseList baseList needAssignmentList; + _rrCycler = with builtins; origBaseList: workingBaseList: needAssignmentList: + if (workingBaseList == [] || needAssignmentList == []) + then [] + else + [{ fst = head workingBaseList; snd = head needAssignmentList;}] ++ + _rrCycler origBaseList (if (tail workingBaseList == []) then origBaseList else tail workingBaseList) (tail needAssignmentList); + attrsToList = mapAttrsToList (attrname: attrval: {name = attrname; value = attrval;}); + # for an AttrSet `funcsAttrs` having functions as values, apply single arguments from + # `argsList` to them in a round-robin manner. + # Returns an attribute set with the applied functions as values. + roundRobinApplyAttrs = funcsAttrs: argsList: lib.listToAttrs (map (x: {inherit (x.snd) name; value = x.snd.value x.fst;}) (roundRobinAssign argsList (attrsToList funcsAttrs))); + wrapInFlock = lockfilePath: script: + # explainer: https://stackoverflow.com/a/60896531 + '' + exec {LOCKFD}> ${lockfilePath} + echo "Waiting to acquire lock ${lockfilePath}" + ${pkgs.flock}/bin/flock ''${LOCKFD} || exit 1 + echo "Acquired lock ${lockfilePath}" + '' + + script + "\n" + + ''echo "Releasing lock ${lockfilePath}" # only released after process exit''; + + # There are many services required to make cert renewals work. # They all follow a common structure: # - They inherit this commonServiceConfig @@ -31,6 +63,7 @@ let ProtectSystem = "strict"; ReadWritePaths = [ "/var/lib/acme" + lockdir ]; PrivateTmp = true; @@ -118,7 +151,8 @@ let # We don't want this to run every time a renewal happens RemainAfterExit = true; - # These StateDirectory entries negate the need for tmpfiles + # StateDirectory entries are a cleaner, service-level mechanism + # for dealing with persistent service data StateDirectory = [ "acme" "acme/.lego" "acme/.lego/accounts" ]; StateDirectoryMode = 755; WorkingDirectory = "/var/lib/acme"; @@ -127,6 +161,25 @@ let ExecStart = "+" + (pkgs.writeShellScript "acme-fixperms" script); }; }; + lockfilePrepareService = { + description = "Manage lock files for acme services"; + + # ensure all required lock files exist, but none more + script = '' + GLOBIGNORE="${concatStringsSep ":" concurrencyLockfiles}" + rm -f * + unset GLOBIGNORE + + xargs touch <<< "${toString concurrencyLockfiles}" + ''; + + serviceConfig = commonServiceConfig // { + # We don't want this to run every time a renewal happens + RemainAfterExit = true; + WorkingDirectory = lockdir; + }; + }; + certToConfig = cert: data: let acmeServer = data.server; @@ -229,10 +282,10 @@ let }; }; - selfsignService = { + selfsignService = lockfileName: { description = "Generate self-signed certificate for ${cert}"; - after = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ]; - requires = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ]; + after = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service"; + requires = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ] ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service"; path = with pkgs; [ minica ]; @@ -256,7 +309,7 @@ let # Working directory will be /tmp # minica will output to a folder sharing the name of the first domain # in the list, which will be ${data.domain} - script = '' + script = (if (lockfileName == null) then lib.id else wrapInFlock "${lockdir}${lockfileName}") '' minica \ --ca-key ca/key.pem \ --ca-cert ca/cert.pem \ @@ -277,10 +330,10 @@ let ''; }; - renewService = { + renewService = lockfileName: { description = "Renew ACME certificate for ${cert}"; - after = [ "network.target" "network-online.target" "acme-fixperms.service" "nss-lookup.target" ] ++ selfsignedDeps; - wants = [ "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps; + after = [ "network.target" "network-online.target" "acme-fixperms.service" "nss-lookup.target" ] ++ selfsignedDeps ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service"; + wants = [ "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps ++ optional (cfg.maxConcurrentRenewals > 0) "acme-lockfiles.service"; # https://github.com/NixOS/nixpkgs/pull/81371#issuecomment-605526099 wantedBy = optionals (!config.boot.isContainer) [ "multi-user.target" ]; @@ -329,7 +382,7 @@ let }; # Working directory will be /tmp - script = '' + script = (if (lockfileName == null) then lib.id else wrapInFlock "${lockdir}${lockfileName}") '' ${optionalString data.enableDebugLogs "set -x"} set -euo pipefail @@ -755,6 +808,17 @@ in { } ''; }; + maxConcurrentRenewals = mkOption { + default = 5; + type = types.int; + description = lib.mdDoc '' + Maximum number of concurrent certificate generation or renewal jobs. All other + jobs will queue and wait running jobs to finish. Reduces the system load of + certificate generation. + + Set to `0` to allow unlimited number of concurrent job runs." + ''; + }; }; }; @@ -875,12 +939,28 @@ in { users.groups.acme = {}; - systemd.services = { - "acme-fixperms" = userMigrationService; - } // (mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewService) certConfigs) + # for lock files, still use tmpfiles as they should better reside in /run + systemd.tmpfiles.rules = [ + "d ${lockdir} 0700 ${user} - - -" + "Z ${lockdir} 0700 ${user} - - -" + ]; + + systemd.services = let + renewServiceFunctions = mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewService) certConfigs; + renewServices = if cfg.maxConcurrentRenewals > 0 + then roundRobinApplyAttrs renewServiceFunctions concurrencyLockfiles + else mapAttrs (_: f: f null) renewServiceFunctions; + selfsignServiceFunctions = mapAttrs' (cert: conf: nameValuePair "acme-selfsigned-${cert}" conf.selfsignService) certConfigs; + selfsignServices = if cfg.maxConcurrentRenewals > 0 + then roundRobinApplyAttrs selfsignServiceFunctions concurrencyLockfiles + else mapAttrs (_: f: f null) selfsignServiceFunctions; + in + { "acme-fixperms" = userMigrationService; } + // (optionalAttrs (cfg.maxConcurrentRenewals > 0) {"acme-lockfiles" = lockfilePrepareService; }) + // renewServices // (optionalAttrs (cfg.preliminarySelfsigned) ({ "acme-selfsigned-ca" = selfsignCAService; - } // (mapAttrs' (cert: conf: nameValuePair "acme-selfsigned-${cert}" conf.selfsignService) certConfigs))); + } // selfsignServices)); systemd.timers = mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewTimer) certConfigs; diff --git a/nixpkgs/nixos/modules/security/wrappers/default.nix b/nixpkgs/nixos/modules/security/wrappers/default.nix index 12255d8392fe..ad65f80bb2ca 100644 --- a/nixpkgs/nixos/modules/security/wrappers/default.nix +++ b/nixpkgs/nixos/modules/security/wrappers/default.nix @@ -5,8 +5,8 @@ let parentWrapperDir = dirOf wrapperDir; - securityWrapper = pkgs.callPackage ./wrapper.nix { - inherit parentWrapperDir; + securityWrapper = sourceProg : pkgs.callPackage ./wrapper.nix { + inherit sourceProg; }; fileModeType = @@ -91,8 +91,7 @@ let , ... }: '' - cp ${securityWrapper}/bin/security-wrapper "$wrapperDir/${program}" - echo -n "${source}" > "$wrapperDir/${program}.real" + cp ${securityWrapper source}/bin/security-wrapper "$wrapperDir/${program}" # Prevent races chmod 0000 "$wrapperDir/${program}" @@ -119,8 +118,7 @@ let , ... }: '' - cp ${securityWrapper}/bin/security-wrapper "$wrapperDir/${program}" - echo -n "${source}" > "$wrapperDir/${program}.real" + cp ${securityWrapper source}/bin/security-wrapper "$wrapperDir/${program}" # Prevent races chmod 0000 "$wrapperDir/${program}" @@ -248,11 +246,13 @@ in export PATH="${wrapperDir}:$PATH" ''; - security.apparmor.includes."nixos/security.wrappers" = '' - include "${pkgs.apparmorRulesFromClosure { name="security.wrappers"; } [ - securityWrapper + security.apparmor.includes = lib.mapAttrs' (wrapName: wrap: lib.nameValuePair + "nixos/security.wrappers/${wrapName}" '' + include "${pkgs.apparmorRulesFromClosure { name="security.wrappers.${wrapName}"; } [ + (securityWrapper wrap.source) ]}" - ''; + mrpx ${wrap.source}, + '') wrappers; ###### wrappers activation script system.activationScripts.wrappers = diff --git a/nixpkgs/nixos/modules/security/wrappers/wrapper.c b/nixpkgs/nixos/modules/security/wrappers/wrapper.c index 17776a97af81..2cf1727a31c8 100644 --- a/nixpkgs/nixos/modules/security/wrappers/wrapper.c +++ b/nixpkgs/nixos/modules/security/wrappers/wrapper.c @@ -17,6 +17,10 @@ #include <syscall.h> #include <byteswap.h> +#ifndef SOURCE_PROG +#error SOURCE_PROG should be defined via preprocessor commandline +#endif + // aborts when false, printing the failed expression #define ASSERT(expr) ((expr) ? (void) 0 : assert_failure(#expr)) // aborts when returns non-zero, printing the failed expression and errno @@ -24,10 +28,6 @@ extern char **environ; -// The WRAPPER_DIR macro is supplied at compile time so that it cannot -// be changed at runtime -static char *wrapper_dir = WRAPPER_DIR; - // Wrapper debug variable name static char *wrapper_debug = "WRAPPER_DEBUG"; @@ -151,115 +151,20 @@ static int make_caps_ambient(const char *self_path) { return 0; } -int readlink_malloc(const char *p, char **ret) { - size_t l = FILENAME_MAX+1; - int r; - - for (;;) { - char *c = calloc(l, sizeof(char)); - if (!c) { - return -ENOMEM; - } - - ssize_t n = readlink(p, c, l-1); - if (n < 0) { - r = -errno; - free(c); - return r; - } - - if ((size_t) n < l-1) { - c[n] = 0; - *ret = c; - return 0; - } - - free(c); - l *= 2; - } -} - int main(int argc, char **argv) { ASSERT(argc >= 1); - char *self_path = NULL; - int self_path_size = readlink_malloc("/proc/self/exe", &self_path); - if (self_path_size < 0) { - fprintf(stderr, "cannot readlink /proc/self/exe: %s", strerror(-self_path_size)); - } - - unsigned int ruid, euid, suid, rgid, egid, sgid; - MUSTSUCCEED(getresuid(&ruid, &euid, &suid)); - MUSTSUCCEED(getresgid(&rgid, &egid, &sgid)); - - // If true, then we did not benefit from setuid privilege escalation, - // where the original uid is still in ruid and different from euid == suid. - int didnt_suid = (ruid == euid) && (euid == suid); - // If true, then we did not benefit from setgid privilege escalation - int didnt_sgid = (rgid == egid) && (egid == sgid); - - - // Make sure that we are being executed from the right location, - // i.e., `safe_wrapper_dir'. This is to prevent someone from creating - // hard link `X' from some other location, along with a false - // `X.real' file, to allow arbitrary programs from being executed - // with elevated capabilities. - int len = strlen(wrapper_dir); - if (len > 0 && '/' == wrapper_dir[len - 1]) - --len; - ASSERT(!strncmp(self_path, wrapper_dir, len)); - ASSERT('/' == wrapper_dir[0]); - ASSERT('/' == self_path[len]); - - // If we got privileges with the fs set[ug]id bit, check that the privilege we - // got matches the one one we expected, ie that our effective uid/gid - // matches the uid/gid of `self_path`. This ensures that we were executed as - // `self_path', and not, say, as some other setuid program. - // We don't check that if we did not benefit from the set[ug]id bit, as - // can be the case in nosuid mounts or user namespaces. - struct stat st; - ASSERT(lstat(self_path, &st) != -1); - - // if the wrapper gained privilege with suid, check that we got the uid of the file owner - ASSERT(!((st.st_mode & S_ISUID) && !didnt_suid) || (st.st_uid == euid)); - // if the wrapper gained privilege with sgid, check that we got the gid of the file group - ASSERT(!((st.st_mode & S_ISGID) && !didnt_sgid) || (st.st_gid == egid)); - // same, but with suid instead of euid - ASSERT(!((st.st_mode & S_ISUID) && !didnt_suid) || (st.st_uid == suid)); - ASSERT(!((st.st_mode & S_ISGID) && !didnt_sgid) || (st.st_gid == sgid)); - - // And, of course, we shouldn't be writable. - ASSERT(!(st.st_mode & (S_IWGRP | S_IWOTH))); - - // Read the path of the real (wrapped) program from <self>.real. - char real_fn[PATH_MAX + 10]; - int real_fn_size = snprintf(real_fn, sizeof(real_fn), "%s.real", self_path); - ASSERT(real_fn_size < sizeof(real_fn)); - - int fd_self = open(real_fn, O_RDONLY); - ASSERT(fd_self != -1); - - char source_prog[PATH_MAX]; - len = read(fd_self, source_prog, PATH_MAX); - ASSERT(len != -1); - ASSERT(len < sizeof(source_prog)); - ASSERT(len > 0); - source_prog[len] = 0; - - close(fd_self); // Read the capabilities set on the wrapper and raise them in to // the ambient set so the program we're wrapping receives the // capabilities too! - if (make_caps_ambient(self_path) != 0) { - free(self_path); + if (make_caps_ambient("/proc/self/exe") != 0) { return 1; } - free(self_path); - execve(source_prog, argv, environ); + execve(SOURCE_PROG, argv, environ); fprintf(stderr, "%s: cannot run `%s': %s\n", - argv[0], source_prog, strerror(errno)); + argv[0], SOURCE_PROG, strerror(errno)); return 1; } diff --git a/nixpkgs/nixos/modules/security/wrappers/wrapper.nix b/nixpkgs/nixos/modules/security/wrappers/wrapper.nix index e3620fb222d2..aec43412404e 100644 --- a/nixpkgs/nixos/modules/security/wrappers/wrapper.nix +++ b/nixpkgs/nixos/modules/security/wrappers/wrapper.nix @@ -1,4 +1,4 @@ -{ stdenv, linuxHeaders, parentWrapperDir, debug ? false }: +{ stdenv, linuxHeaders, sourceProg, debug ? false }: # For testing: # $ nix-build -E 'with import <nixpkgs> {}; pkgs.callPackage ./wrapper.nix { parentWrapperDir = "/run/wrappers"; debug = true; }' stdenv.mkDerivation { @@ -7,7 +7,7 @@ stdenv.mkDerivation { dontUnpack = true; hardeningEnable = [ "pie" ]; CFLAGS = [ - ''-DWRAPPER_DIR="${parentWrapperDir}"'' + ''-DSOURCE_PROG="${sourceProg}"'' ] ++ (if debug then [ "-Werror" "-Og" "-g" ] else [ diff --git a/nixpkgs/nixos/modules/services/backup/restic.nix b/nixpkgs/nixos/modules/services/backup/restic.nix index 6f4cbab81726..78220e99c3d1 100644 --- a/nixpkgs/nixos/modules/services/backup/restic.nix +++ b/nixpkgs/nixos/modules/services/backup/restic.nix @@ -260,6 +260,16 @@ in Restic package to use. ''; }; + + createWrapper = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to generate and add a script to the system path, that has the same environment variables set + as the systemd service. This can be used to e.g. mount snapshots or perform other opterations, without + having to manually specify most options. + ''; + }; }; })); default = { }; @@ -316,7 +326,8 @@ in in nameValuePair "restic-backups-${name}" ({ environment = { - RESTIC_CACHE_DIR = "%C/restic-backups-${name}"; + # not %C, because that wouldn't work in the wrapper script + RESTIC_CACHE_DIR = "/var/cache/restic-backups-${name}"; RESTIC_PASSWORD_FILE = backup.passwordFile; RESTIC_REPOSITORY = backup.repository; RESTIC_REPOSITORY_FILE = backup.repositoryFile; @@ -331,7 +342,7 @@ in nameValuePair (rcloneAttrToConf name) (toRcloneVal value) ) backup.rcloneConfig); - path = [ pkgs.openssh ]; + path = [ config.programs.ssh.package ]; restartIfChanged = false; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; @@ -378,5 +389,22 @@ in timerConfig = backup.timerConfig; }) config.services.restic.backups; + + # generate wrapper scripts, as described in the createWrapper option + environment.systemPackages = lib.mapAttrsToList (name: backup: let + extraOptions = lib.concatMapStrings (arg: " -o ${arg}") backup.extraOptions; + resticCmd = "${backup.package}/bin/restic${extraOptions}"; + in pkgs.writeShellScriptBin "restic-${name}" '' + set -a # automatically export variables + ${lib.optionalString (backup.environmentFile != null) "source ${backup.environmentFile}"} + # set same environment variables as the systemd service + ${lib.pipe config.systemd.services."restic-backups-${name}".environment [ + (lib.filterAttrs (_: v: v != null)) + (lib.mapAttrsToList (n: v: "${n}=${v}")) + (lib.concatStringsSep "\n") + ]} + + exec ${resticCmd} $@ + '') (lib.filterAttrs (_: v: v.createWrapper) config.services.restic.backups); }; } diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix index 595374ea1e5b..b4b997201c8f 100644 --- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix +++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix @@ -272,7 +272,13 @@ in { Group = cfg.group; WorkingDirectory = cfg.home; # NOTE: call twistd directly with stdout logging for systemd - ExecStart = "${python.pkgs.twisted}/bin/twistd -o --nodaemon --pidfile= --logfile - --python ${tacFile}"; + ExecStart = "${python.pkgs.twisted}/bin/twistd -o --nodaemon --pidfile= --logfile - --python ${cfg.buildbotDir}/buildbot.tac"; + # To reload on upgrade, set the following in your configuration: + # systemd.services.buildbot-master.reloadIfChanged = true; + ExecReload = [ + "${pkgs.coreutils}/bin/ln -sf ${tacFile} ${cfg.buildbotDir}/buildbot.tac" + "${pkgs.coreutils}/bin/kill -HUP $MAINPID" + ]; }; }; }; diff --git a/nixpkgs/nixos/modules/services/continuous-integration/hail.nix b/nixpkgs/nixos/modules/services/continuous-integration/hail.nix deleted file mode 100644 index 62e8b8077c07..000000000000 --- a/nixpkgs/nixos/modules/services/continuous-integration/hail.nix +++ /dev/null @@ -1,61 +0,0 @@ -{ config, lib, pkgs, ...}: - -with lib; - -let - cfg = config.services.hail; -in { - - - ###### interface - - options.services.hail = { - enable = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Enables the Hail Auto Update Service. Hail can automatically deploy artifacts - built by a Hydra Continuous Integration server. A common use case is to provide - continuous deployment for single services or a full NixOS configuration.''; - }; - profile = mkOption { - type = types.str; - default = "hail-profile"; - description = lib.mdDoc "The name of the Nix profile used by Hail."; - }; - hydraJobUri = mkOption { - type = types.str; - description = lib.mdDoc "The URI of the Hydra Job."; - }; - netrc = mkOption { - type = types.nullOr types.path; - description = lib.mdDoc "The netrc file to use when fetching data from Hydra."; - default = null; - }; - package = mkOption { - type = types.package; - default = pkgs.haskellPackages.hail; - defaultText = literalExpression "pkgs.haskellPackages.hail"; - description = lib.mdDoc "Hail package to use."; - }; - }; - - - ###### implementation - - config = mkIf cfg.enable { - systemd.services.hail = { - description = "Hail Auto Update Service"; - wants = [ "network-online.target" ]; - wantedBy = [ "multi-user.target" ]; - path = with pkgs; [ nix ]; - environment = { - HOME = "/var/lib/empty"; - }; - serviceConfig = { - ExecStart = "${cfg.package}/bin/hail --profile ${cfg.profile} --job-uri ${cfg.hydraJobUri}" - + lib.optionalString (cfg.netrc != null) " --netrc-file ${cfg.netrc}"; - }; - }; - }; -} diff --git a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix index cc5b903afd59..3b883c72ff07 100644 --- a/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix +++ b/nixpkgs/nixos/modules/services/continuous-integration/woodpecker/agents.nix @@ -35,6 +35,16 @@ let ''; }; + path = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = [ ]; + example = [ "" ]; + description = lib.mdDoc '' + Additional packages that should be added to the agent's `PATH`. + Mostly useful for the `local` backend. + ''; + }; + environmentFile = lib.mkOption { type = lib.types.listOf lib.types.path; default = [ ]; @@ -94,7 +104,7 @@ let "-/etc/localtime" ]; }; - inherit (agentCfg) environment; + inherit (agentCfg) environment path; }; }; in @@ -106,28 +116,41 @@ in agents = lib.mkOption { default = { }; type = lib.types.attrsOf agentModule; - example = { - docker = { - environment = { - WOODPECKER_SERVER = "localhost:9000"; - WOODPECKER_BACKEND = "docker"; - DOCKER_HOST = "unix:///run/podman/podman.sock"; + example = lib.literalExpression '' + { + podman = { + environment = { + WOODPECKER_SERVER = "localhost:9000"; + WOODPECKER_BACKEND = "docker"; + DOCKER_HOST = "unix:///run/podman/podman.sock"; + }; + + extraGroups = [ "podman" ]; + + environmentFile = [ "/run/secrets/woodpecker/agent-secret.txt" ]; }; - extraGroups = [ "docker" ]; + exec = { + environment = { + WOODPECKER_SERVER = "localhost:9000"; + WOODPECKER_BACKEND = "local"; + }; - environmentFile = "/run/secrets/woodpecker/agent-secret.txt"; - }; + environmentFile = [ "/run/secrets/woodpecker/agent-secret.txt" ]; - exec = { - environment = { - WOODPECKER_SERVER = "localhost:9000"; - WOODPECKER_BACKEND = "exec"; + path = [ + # Needed to clone repos + git + git-lfs + woodpecker-plugin-git + # Used by the runner as the default shell + bash + # Most likely to be used in pipeline definitions + coreutils + ]; }; - - environmentFile = "/run/secrets/woodpecker/agent-secret.txt"; - }; - }; + } + ''; description = lib.mdDoc "woodpecker-agents configurations"; }; }; diff --git a/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix b/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix index 796de3a491e4..6b5bd8a0d9bb 100644 --- a/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix +++ b/nixpkgs/nixos/modules/services/home-automation/zigbee2mqtt.nix @@ -66,9 +66,10 @@ in server = mkDefault "mqtt://localhost:1883"; }; serial.port = mkDefault "/dev/ttyACM0"; - # reference device configuration, that is kept in a separate file + # reference device/group configuration, that is kept in a separate file # to prevent it being overwritten in the units ExecStartPre script devices = mkDefault "devices.yaml"; + groups = mkDefault "groups.yaml"; }; systemd.services.zigbee2mqtt = { diff --git a/nixpkgs/nixos/modules/services/logging/logrotate.nix b/nixpkgs/nixos/modules/services/logging/logrotate.nix index 342ac5ec6e04..ba1445f08397 100644 --- a/nixpkgs/nixos/modules/services/logging/logrotate.nix +++ b/nixpkgs/nixos/modules/services/logging/logrotate.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, utils, ... }: with lib; @@ -220,6 +220,12 @@ in in this case you can disable the failing check with this option. ''; }; + + extraArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "Additional command line arguments to pass on logrotate invocation"; + }; }; }; @@ -231,7 +237,7 @@ in serviceConfig = { Restart = "no"; User = "root"; - ExecStart = "${pkgs.logrotate}/sbin/logrotate ${mailOption} ${cfg.configFile}"; + ExecStart = "${pkgs.logrotate}/sbin/logrotate ${utils.escapeSystemdExecArgs cfg.extraArgs} ${mailOption} ${cfg.configFile}"; }; }; systemd.services.logrotate-checkconf = { @@ -240,7 +246,7 @@ in serviceConfig = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = "${pkgs.logrotate}/sbin/logrotate --debug ${cfg.configFile}"; + ExecStart = "${pkgs.logrotate}/sbin/logrotate ${utils.escapeSystemdExecArgs cfg.extraArgs} --debug ${cfg.configFile}"; }; }; }; diff --git a/nixpkgs/nixos/modules/services/mail/listmonk.nix b/nixpkgs/nixos/modules/services/mail/listmonk.nix index 251362fdd89d..11b2a5186229 100644 --- a/nixpkgs/nixos/modules/services/mail/listmonk.nix +++ b/nixpkgs/nixos/modules/services/mail/listmonk.nix @@ -54,7 +54,7 @@ let smtp = mkOption { type = listOf (submodule { - freeformType = with types; attrsOf (oneOf [ str int bool ]); + freeformType = with types; attrsOf anything; options = { enabled = mkEnableOption (lib.mdDoc "this SMTP server for listmonk"); @@ -86,7 +86,7 @@ let # TODO: refine this type based on the smtp one. "bounce.mailboxes" = mkOption { type = listOf - (submodule { freeformType = with types; oneOf [ str int bool ]; }); + (submodule { freeformType = with types; listOf (attrsOf anything); }); default = [ ]; description = lib.mdDoc "List of bounce mailboxes"; }; diff --git a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix index fdbdc99070b9..eb87d9f6f695 100644 --- a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix +++ b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix @@ -18,7 +18,7 @@ in { default = { }; description = mdDoc '' Configuration options for the Stalwart email server. - See <https://stalw.art/docs/> for available options. + See <https://stalw.art/docs/category/configuration> for available options. By default, the module is configured to store everything locally. ''; diff --git a/nixpkgs/nixos/modules/services/misc/cfdyndns.nix b/nixpkgs/nixos/modules/services/misc/cfdyndns.nix index 9cd8b188ffae..5a02de2aad21 100644 --- a/nixpkgs/nixos/modules/services/misc/cfdyndns.nix +++ b/nixpkgs/nixos/modules/services/misc/cfdyndns.nix @@ -23,6 +23,15 @@ in ''; }; + apiTokenFile = mkOption { + default = null; + type = types.nullOr types.str; + description = lib.mdDoc '' + The path to a file containing the API Token + used to authenticate with CloudFlare. + ''; + }; + apikeyFile = mkOption { default = null; type = types.nullOr types.str; @@ -55,12 +64,15 @@ in Group = config.ids.gids.cfdyndns; }; environment = { - CLOUDFLARE_EMAIL="${cfg.email}"; CLOUDFLARE_RECORDS="${concatStringsSep "," cfg.records}"; }; script = '' ${optionalString (cfg.apikeyFile != null) '' export CLOUDFLARE_APIKEY="$(cat ${escapeShellArg cfg.apikeyFile})" + export CLOUDFLARE_EMAIL="${cfg.email}" + ''} + ${optionalString (cfg.apiTokenFile != null) '' + export CLOUDFLARE_APITOKEN="$(cat ${escapeShellArg cfg.apiTokenFile})" ''} ${pkgs.cfdyndns}/bin/cfdyndns ''; diff --git a/nixpkgs/nixos/modules/services/networking/wstunnel.nix b/nixpkgs/nixos/modules/services/networking/wstunnel.nix index 067d5df48725..3c3ecc3e04d7 100644 --- a/nixpkgs/nixos/modules/services/networking/wstunnel.nix +++ b/nixpkgs/nixos/modules/services/networking/wstunnel.nix @@ -86,12 +86,12 @@ let description = mdDoc "Address and port to listen on. Setting the port to a value below 1024 will also give the process the required `CAP_NET_BIND_SERVICE` capability."; type = types.submodule hostPortSubmodule; default = { - address = "0.0.0.0"; + host = "0.0.0.0"; port = if config.enableHTTPS then 443 else 80; }; defaultText = literalExpression '' { - address = "0.0.0.0"; + host = "0.0.0.0"; port = if enableHTTPS then 443 else 80; } ''; diff --git a/nixpkgs/nixos/modules/services/web-apps/galene.nix b/nixpkgs/nixos/modules/services/web-apps/galene.nix index 747b85f94c65..81fed8a0b99a 100644 --- a/nixpkgs/nixos/modules/services/web-apps/galene.nix +++ b/nixpkgs/nixos/modules/services/web-apps/galene.nix @@ -186,7 +186,7 @@ in ProtectSystem = "strict"; ReadWritePaths = cfg.recordingsDir; RemoveIPC = true; - RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; diff --git a/nixpkgs/nixos/modules/services/web-apps/plausible.nix b/nixpkgs/nixos/modules/services/web-apps/plausible.nix index 911daa53e658..4b308d2ee56e 100644 --- a/nixpkgs/nixos/modules/services/web-apps/plausible.nix +++ b/nixpkgs/nixos/modules/services/web-apps/plausible.nix @@ -248,6 +248,7 @@ in { # setup ${cfg.package}/createdb.sh ${cfg.package}/migrate.sh + ${cfg.package}/bin/plausible eval "(Plausible.Release.prepare() ; Plausible.Auth.create_user(\"$ADMIN_USER_NAME\", \"$ADMIN_USER_EMAIL\", \"$ADMIN_USER_PWD\"))" ${optionalString cfg.adminUser.activate '' if ! ${cfg.package}/init-admin.sh | grep 'already exists'; then psql -d plausible <<< "UPDATE users SET email_verified=true;" diff --git a/nixpkgs/nixos/modules/services/web-apps/tt-rss.nix b/nixpkgs/nixos/modules/services/web-apps/tt-rss.nix index 3102e6a46953..592ab253f7da 100644 --- a/nixpkgs/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixpkgs/nixos/modules/services/web-apps/tt-rss.nix @@ -595,47 +595,9 @@ let tt-rss = { description = "Tiny Tiny RSS feeds update daemon"; - preStart = let - callSql = e: - if cfg.database.type == "pgsql" then '' - ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \ - ${optionalString (cfg.database.passwordFile != null) "PGPASSWORD=$(cat ${cfg.database.passwordFile})"} \ - ${config.services.postgresql.package}/bin/psql \ - -U ${cfg.database.user} \ - ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \ - -c '${e}' \ - ${cfg.database.name}'' - - else if cfg.database.type == "mysql" then '' - echo '${e}' | ${config.services.mysql.package}/bin/mysql \ - -u ${cfg.database.user} \ - ${optionalString (cfg.database.password != null) "-p${cfg.database.password}"} \ - ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} -P ${toString dbPort}"} \ - ${cfg.database.name}'' - - else ""; - - in (optionalString (cfg.database.type == "pgsql") '' - exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ - | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') - - if [ "$exists" == 'f' ]; then - ${callSql "\\i ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} - else - echo 'The database contains some data. Leaving it as it is.' - fi; - '') - - + (optionalString (cfg.database.type == "mysql") '' - exists=$(${callSql "select count(*) > 0 from information_schema.tables where table_schema = schema()"} \ - | tail -n+2 | sed -e 's/[ \n\t]*//') - - if [ "$exists" == '0' ]; then - ${callSql "\\. ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} - else - echo 'The database contains some data. Leaving it as it is.' - fi; - ''); + preStart = '' + ${pkgs.php81}/bin/php ${cfg.root}/www/update.php --update-schema + ''; serviceConfig = { User = "${cfg.user}"; diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix b/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix deleted file mode 100644 index 654b8708e48f..000000000000 --- a/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.xserver.windowManager.oroborus; -in -{ - ###### interface - options = { - services.xserver.windowManager.oroborus.enable = mkEnableOption (lib.mdDoc "oroborus"); - }; - - ###### implementation - config = mkIf cfg.enable { - services.xserver.windowManager.session = singleton { - name = "oroborus"; - start = '' - ${pkgs.oroborus}/bin/oroborus & - waitPID=$! - ''; - }; - environment.systemPackages = [ pkgs.oroborus ]; - }; -} diff --git a/nixpkgs/nixos/modules/system/boot/binfmt.nix b/nixpkgs/nixos/modules/system/boot/binfmt.nix index fb7afce4a580..8c9483f01c10 100644 --- a/nixpkgs/nixos/modules/system/boot/binfmt.nix +++ b/nixpkgs/nixos/modules/system/boot/binfmt.nix @@ -279,7 +279,7 @@ in { support your new systems. Warning: the builder can execute all emulated systems within the same build, which introduces impurities in the case of cross compilation. ''; - type = types.listOf types.str; + type = types.listOf (types.enum (builtins.attrNames magics)); }; }; }; diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix index 6d0afcc57fcc..87afc5023253 100644 --- a/nixpkgs/nixos/modules/system/boot/networkd.nix +++ b/nixpkgs/nixos/modules/system/boot/networkd.nix @@ -2812,9 +2812,15 @@ let environment.etc."systemd/networkd.conf" = renderConfig cfg.config; - systemd.services.systemd-networkd = { + systemd.services.systemd-networkd = let + isReloadableUnitFileName = unitFileName: strings.hasSuffix ".network" unitFileName; + reloadableUnitFiles = attrsets.filterAttrs (k: v: isReloadableUnitFileName k) unitFiles; + nonReloadableUnitFiles = attrsets.filterAttrs (k: v: !isReloadableUnitFileName k) unitFiles; + unitFileSources = unitFiles: map (x: x.source) (attrValues unitFiles); + in { wantedBy = [ "multi-user.target" ]; - restartTriggers = map (x: x.source) (attrValues unitFiles) ++ [ + reloadTriggers = unitFileSources reloadableUnitFiles; + restartTriggers = unitFileSources nonReloadableUnitFiles ++ [ config.environment.etc."systemd/networkd.conf".source ]; aliases = [ "dbus-org.freedesktop.network1.service" ]; diff --git a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh index c0af29e3b990..5a2133f960e2 100755 --- a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh +++ b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh @@ -105,7 +105,7 @@ fi # Required by the activation script install -m 0755 -d /etc -if [ -d "/etc/nixos" ]; then +if [ ! -h "/etc/nixos" ]; then install -m 0755 -d /etc/nixos fi install -m 01777 -d /tmp diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix index ac55461107fb..b6c3085c4f16 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd.nix @@ -395,7 +395,9 @@ in description = lib.mdDoc '' The amount of time which can elapse after a reboot has been triggered before a watchdog hardware device will automatically reboot the system. - Valid time units include "ms", "s", "min", "h", "d", and "w". + Valid time units include "ms", "s", "min", "h", "d", and "w". If left + `null`, systemd will use its default of `10min`; see also {command}`man + 5 systemd-system.conf`. ''; }; diff --git a/nixpkgs/nixos/modules/tasks/bcache.nix b/nixpkgs/nixos/modules/tasks/bcache.nix index 35b922dc8a1d..68531a4d2fed 100644 --- a/nixpkgs/nixos/modules/tasks/bcache.nix +++ b/nixpkgs/nixos/modules/tasks/bcache.nix @@ -1,6 +1,10 @@ -{ config, lib, pkgs, ... }: - -{ +{ config, lib, pkgs, ... }: let + cfg = config.boot.bcache; +in { + options.boot.bcache.enable = lib.mkEnableOption (lib.mdDoc "bcache mount support") // { + default = true; + example = false; + }; options.boot.initrd.services.bcache.enable = lib.mkEnableOption (lib.mdDoc "bcache support in the initrd") // { description = lib.mdDoc '' *This will only be used when systemd is used in stage 1.* @@ -9,7 +13,7 @@ ''; }; - config = { + config = lib.mkIf cfg.enable { environment.systemPackages = [ pkgs.bcache-tools ]; diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces.nix b/nixpkgs/nixos/modules/tasks/network-interfaces.nix index eb1c7512d920..0d4033ca9430 100644 --- a/nixpkgs/nixos/modules/tasks/network-interfaces.nix +++ b/nixpkgs/nixos/modules/tasks/network-interfaces.nix @@ -1396,14 +1396,12 @@ in security.apparmor.policies."bin.ping".profile = lib.mkIf config.security.apparmor.policies."bin.ping".enable (lib.mkAfter '' /run/wrappers/bin/ping { include <abstractions/base> - include <nixos/security.wrappers> + include <nixos/security.wrappers/ping> rpx /run/wrappers/wrappers.*/ping, } /run/wrappers/wrappers.*/ping { include <abstractions/base> - include <nixos/security.wrappers> - r /run/wrappers/wrappers.*/ping.real, - mrpx ${config.security.wrappers.ping.source}, + include <nixos/security.wrappers/ping> capability net_raw, capability setpcap, } diff --git a/nixpkgs/nixos/modules/tasks/swraid.nix b/nixpkgs/nixos/modules/tasks/swraid.nix index f624294565b0..1174187062d7 100644 --- a/nixpkgs/nixos/modules/tasks/swraid.nix +++ b/nixpkgs/nixos/modules/tasks/swraid.nix @@ -2,6 +2,8 @@ cfg = config.boot.swraid; + mdadm_conf = config.environment.etc."mdadm.conf"; + in { imports = [ (lib.mkRenamedOptionModule [ "boot" "initrd" "services" "swraid" "enable" ] [ "boot" "swraid" "enable" ]) @@ -36,8 +38,14 @@ in { }; config = lib.mkIf cfg.enable { + warnings = lib.mkIf + ((builtins.match ".*(MAILADDR|PROGRAM).*" mdadm_conf.text) == null) + [ "mdadm: Neither MAILADDR nor PROGRAM has been set. This will cause the `mdmon` service to crash." ]; + environment.systemPackages = [ pkgs.mdadm ]; + environment.etc."mdadm.conf".text = lib.mkAfter cfg.mdadmConf; + services.udev.packages = [ pkgs.mdadm ]; systemd.packages = [ pkgs.mdadm ]; @@ -59,12 +67,10 @@ in { $out/bin/mdadm --version ''; - extraFiles."/etc/mdadm.conf".source = pkgs.writeText "mdadm.conf" config.boot.swraid.mdadmConf; + extraFiles."/etc/mdadm.conf".source = pkgs.writeText "mdadm.conf" mdadm_conf.text; systemd = { - contents."/etc/mdadm.conf" = lib.mkIf (cfg.mdadmConf != "") { - text = cfg.mdadmConf; - }; + contents."/etc/mdadm.conf".text = mdadm_conf.text; packages = [ pkgs.mdadm ]; initrdBin = [ pkgs.mdadm ]; |