diff options
Diffstat (limited to 'nixpkgs/nixos/modules')
42 files changed, 818 insertions, 225 deletions
diff --git a/nixpkgs/nixos/modules/config/ldso.nix b/nixpkgs/nixos/modules/config/ldso.nix index 72ae3958d886..bd6f0dc5a83b 100644 --- a/nixpkgs/nixos/modules/config/ldso.nix +++ b/nixpkgs/nixos/modules/config/ldso.nix @@ -6,9 +6,9 @@ let libDir = pkgs.stdenv.hostPlatform.libDir; ldsoBasename = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs.stdenv.cc.bintools.dynamicLinker)); - pkgs32 = pkgs.pkgsi686Linux; - libDir32 = pkgs32.stdenv.hostPlatform.libDir; - ldsoBasename32 = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs32.stdenv.cc.bintools.dynamicLinker)); + # Hard-code to avoid creating another instance of nixpkgs. Also avoids eval errors in some cases. + libDir32 = "lib"; # pkgs.pkgsi686Linux.stdenv.hostPlatform.libDir + ldsoBasename32 = "ld-linux.so.2"; # last (splitString "/" pkgs.pkgsi686Linux.stdenv.cc.bintools.dynamicLinker) in { options = { environment.ldso = mkOption { diff --git a/nixpkgs/nixos/modules/config/no-x-libs.nix b/nixpkgs/nixos/modules/config/no-x-libs.nix index 2f763290e32d..32b17f6059ef 100644 --- a/nixpkgs/nixos/modules/config/no-x-libs.nix +++ b/nixpkgs/nixos/modules/config/no-x-libs.nix @@ -83,6 +83,7 @@ with lib; # translateManpages -> perlPackages.po4a -> texlive-combined-basic -> texlive-core-big -> libX11 util-linux = super.util-linux.override { translateManpages = false; }; vim-full = super.vim-full.override { guiSupport = false; }; + vte = super.vte.override { gtkVersion = null; }; zbar = super.zbar.override { enableVideo = false; withXorg = false; }; })); }; diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix index 967ad0846d75..dd34771c0b42 100644 --- a/nixpkgs/nixos/modules/config/users-groups.nix +++ b/nixpkgs/nixos/modules/config/users-groups.nix @@ -649,7 +649,6 @@ in { home = "/root"; shell = mkDefault cfg.defaultUserShell; group = "root"; - initialHashedPassword = mkDefault "!"; }; nobody = { uid = ids.uids.nobody; @@ -897,7 +896,26 @@ in { )); warnings = - builtins.filter (x: x != null) ( + flip concatMap (attrValues cfg.users) (user: let + unambiguousPasswordConfiguration = 1 >= length (filter (x: x != null) ([ + user.hashedPassword + user.hashedPasswordFile + user.password + ] ++ optionals cfg.mutableUsers [ + # For immutable users, initialHashedPassword is set to hashedPassword, + # so using these options would always trigger the assertion. + user.initialHashedPassword + user.initialPassword + ])); + in optional (!unambiguousPasswordConfiguration) '' + The user '${user.name}' has multiple of the options + `hashedPassword`, `password`, `hashedPasswordFile`, `initialPassword` + & `initialHashedPassword` set to a non-null value. + The options silently discard others by the order of precedence + given above which can lead to surprising results. To resolve this warning, + set at most one of the options above to a non-`null` value. + '') + ++ builtins.filter (x: x != null) ( flip mapAttrsToList cfg.users (_: user: # This regex matches a subset of the Modular Crypto Format (MCF)[1] # informal standard. Since this depends largely on the OS or the diff --git a/nixpkgs/nixos/modules/config/vte.nix b/nixpkgs/nixos/modules/config/vte.nix index a969607f6e0b..48f85246560a 100644 --- a/nixpkgs/nixos/modules/config/vte.nix +++ b/nixpkgs/nixos/modules/config/vte.nix @@ -1,5 +1,3 @@ -# VTE - { config, pkgs, lib, ... }: with lib; @@ -9,7 +7,7 @@ let vteInitSnippet = '' # Show current working directory in VTE terminals window title. # Supports both bash and zsh, requires interactive shell. - . ${pkgs.vte}/etc/profile.d/vte.sh + . ${pkgs.vte.override { gtkVersion = null; }}/etc/profile.d/vte.sh ''; in diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix index 07d4fa76c2e8..5aa23377f9ff 100644 --- a/nixpkgs/nixos/modules/config/xdg/portal.nix +++ b/nixpkgs/nixos/modules/config/xdg/portal.nix @@ -119,19 +119,6 @@ in let cfg = config.xdg.portal; packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals; - configPackages = cfg.configPackages; - - joinedPortals = pkgs.buildEnv { - name = "xdg-portals"; - paths = packages; - pathsToLink = [ "/share/xdg-desktop-portal/portals" "/share/applications" ]; - }; - - joinedPortalConfigs = pkgs.buildEnv { - name = "xdg-portal-configs"; - paths = configPackages; - pathsToLink = [ "/share/xdg-desktop-portal" ]; - }; in mkIf cfg.enable { warnings = lib.optional (cfg.configPackages == [ ] && cfg.config == { }) '' @@ -158,17 +145,18 @@ in systemd.packages = packages; environment = { - # fixes screen sharing on plasmawayland on non-chromium apps by linking - # share/applications/*.desktop files - # see https://github.com/NixOS/nixpkgs/issues/145174 - systemPackages = [ joinedPortals ]; - pathsToLink = [ "/share/applications" ]; + systemPackages = packages ++ cfg.configPackages; + pathsToLink = [ + # Portal definitions and upstream desktop environment portal configurations. + "/share/xdg-desktop-portal" + # .desktop files to register fallback icon and app name. + "/share/applications" + ]; sessionVariables = { GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1"; NIXOS_XDG_OPEN_USE_PORTAL = mkIf cfg.xdgOpenUsePortal "1"; - XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals"; - NIXOS_XDG_DESKTOP_PORTAL_CONFIG_DIR = mkIf (cfg.configPackages != [ ]) "${joinedPortalConfigs}/share/xdg-desktop-portal"; + NIX_XDG_DESKTOP_PORTAL_DIR = "/run/current-system/sw/share/xdg-desktop-portal/portals"; }; etc = lib.concatMapAttrs diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix index e81754414ea4..a64efec046a4 100644 --- a/nixpkgs/nixos/modules/module-list.nix +++ b/nixpkgs/nixos/modules/module-list.nix @@ -241,6 +241,7 @@ ./programs/proxychains.nix ./programs/qdmr.nix ./programs/qt5ct.nix + ./programs/quark-goldleaf.nix ./programs/regreet.nix ./programs/rog-control-center.nix ./programs/rust-motd.nix @@ -963,6 +964,7 @@ ./services/networking/gns3-server.nix ./services/networking/gnunet.nix ./services/networking/go-autoconfig.nix + ./services/networking/go-camo.nix ./services/networking/go-neb.nix ./services/networking/go-shadowsocks2.nix ./services/networking/gobgpd.nix diff --git a/nixpkgs/nixos/modules/programs/chromium.nix b/nixpkgs/nixos/modules/programs/chromium.nix index 287d93c82cad..45a9e9e2a689 100644 --- a/nixpkgs/nixos/modules/programs/chromium.nix +++ b/nixpkgs/nixos/modules/programs/chromium.nix @@ -23,7 +23,7 @@ in enablePlasmaBrowserIntegration = mkEnableOption (lib.mdDoc "Native Messaging Host for Plasma Browser Integration"); - plasmaBrowserIntegrationPackage = mkPackageOption pkgs "plasma5Packages.plasma-browser-integration" { }; + plasmaBrowserIntegrationPackage = mkPackageOption pkgs [ "plasma5Packages" "plasma-browser-integration" ] { }; extensions = mkOption { type = with types; nullOr (listOf str); diff --git a/nixpkgs/nixos/modules/programs/quark-goldleaf.nix b/nixpkgs/nixos/modules/programs/quark-goldleaf.nix new file mode 100644 index 000000000000..71aadc8c594e --- /dev/null +++ b/nixpkgs/nixos/modules/programs/quark-goldleaf.nix @@ -0,0 +1,18 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.programs.quark-goldleaf; +in +{ + options = { + programs.quark-goldleaf = { + enable = lib.mkEnableOption "quark-goldleaf with udev rules applied"; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ pkgs.quark-goldleaf ]; + services.udev.packages = [ pkgs.quark-goldleaf ]; + }; + + meta.maintainers = pkgs.quark-goldleaf.meta.maintainers; +} diff --git a/nixpkgs/nixos/modules/programs/yazi.nix b/nixpkgs/nixos/modules/programs/yazi.nix index 273a7eeed05f..338eddb60d80 100644 --- a/nixpkgs/nixos/modules/programs/yazi.nix +++ b/nixpkgs/nixos/modules/programs/yazi.nix @@ -22,7 +22,7 @@ in description = lib.mdDoc '' Configuration included in `${name}.toml`. - See https://github.com/sxyazi/yazi/blob/v${cfg.package.version}/config/docs/${name}.md for documentation. + See https://yazi-rs.github.io/docs/configuration/${name}/ for documentation. ''; })) names); @@ -47,7 +47,5 @@ in }; meta = { maintainers = with lib.maintainers; [ linsui ]; - # The version of the package is used in the doc. - buildDocsInSandbox = false; }; } diff --git a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix index 3fb916c76971..a920b6cb1268 100644 --- a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix +++ b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix @@ -285,7 +285,7 @@ in { systemd.tmpfiles.rules = [ "d /opt/cni/bin 0755 root root -" "d /run/kubernetes 0755 kubernetes kubernetes -" - "d /var/lib/kubernetes 0755 kubernetes kubernetes -" + "d ${cfg.dataDir} 0755 kubernetes kubernetes -" ]; users.users.kubernetes = { @@ -294,6 +294,7 @@ in { group = "kubernetes"; home = cfg.dataDir; createHome = true; + homeMode = "755"; }; users.groups.kubernetes.gid = config.ids.gids.kubernetes; diff --git a/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix b/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix index 9a01238c2391..a4b5cb8eda86 100644 --- a/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix +++ b/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix @@ -192,7 +192,8 @@ in mkdir -p "$(dirname "${certmgrAPITokenPath}")" if [ -f "${cfsslAPITokenPath}" ]; then ln -fs "${cfsslAPITokenPath}" "${certmgrAPITokenPath}" - else + elif [ ! -f "${certmgrAPITokenPath}" ]; then + # Don't remove the token if it already exists install -m 600 /dev/null "${certmgrAPITokenPath}" fi '' diff --git a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix index 54bbe69703f9..b1d44e67658b 100644 --- a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix +++ b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix @@ -39,7 +39,7 @@ let hydra-package = let - makeWrapperArgs = concatStringsSep " " (mapAttrsToList (key: value: "--set \"${key}\" \"${value}\"") hydraEnv); + makeWrapperArgs = concatStringsSep " " (mapAttrsToList (key: value: "--set-default \"${key}\" \"${value}\"") hydraEnv); in pkgs.buildEnv rec { name = "hydra-env"; nativeBuildInputs = [ pkgs.makeWrapper ]; diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix index 128bb0862175..a6d71cca88de 100644 --- a/nixpkgs/nixos/modules/services/databases/mysql.nix +++ b/nixpkgs/nixos/modules/services/databases/mysql.nix @@ -7,6 +7,9 @@ let cfg = config.services.mysql; isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb; + isOracle = lib.getName cfg.package == lib.getName pkgs.mysql80; + # Oracle MySQL has supported "notify" service type since 8.0 + hasNotify = isMariaDB || (isOracle && versionAtLeast cfg.package.version "8.0"); mysqldOptions = "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}"; @@ -377,19 +380,11 @@ in # The super user account to use on *first* run of MySQL server superUser = if isMariaDB then cfg.user else "root"; in '' - ${optionalString (!isMariaDB) '' + ${optionalString (!hasNotify) '' # Wait until the MySQL server is available for use - count=0 while [ ! -e /run/mysqld/mysqld.sock ] do - if [ $count -eq 30 ] - then - echo "Tried 30 times, giving up..." - exit 1 - fi - echo "MySQL daemon not yet started. Waiting for 1 second..." - count=$((count++)) sleep 1 done ''} @@ -477,7 +472,7 @@ in serviceConfig = mkMerge [ { - Type = if isMariaDB then "notify" else "simple"; + Type = if hasNotify then "notify" else "simple"; Restart = "on-abort"; RestartSec = "5s"; diff --git a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix index 65b287e84442..157d49c13161 100644 --- a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix +++ b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix @@ -66,9 +66,6 @@ let ${optionalString (cfg.adminUsers != null) "admin_users = ${cfg.adminUsers}"} ${optionalString (cfg.statsUsers != null) "stats_users = ${cfg.statsUsers}"} - # linux - pidfile = /run/pgbouncer/pgbouncer.pid - # extra ${cfg.extraConfig} ''; @@ -96,10 +93,9 @@ in { logFile = mkOption { type = types.nullOr types.str; - default = "pgbouncer.log"; + default = null; description = lib.mdDoc '' - Specifies the log file. - Either this or syslog has to be specified. + Specifies a log file in addition to journald. ''; }; @@ -601,22 +597,21 @@ in { systemd.services.pgbouncer = { description = "PgBouncer - PostgreSQL connection pooler"; - wants = [ "postgresql.service" ]; - after = [ "postgresql.service" ]; + wants = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service"; + after = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service"; wantedBy = [ "multi-user.target" ]; serviceConfig = { - Type = "forking"; + Type = "notify"; User = cfg.user; Group = cfg.group; - ExecStart = "${pkgs.pgbouncer}/bin/pgbouncer -d ${confFile}"; + ExecStart = "${lib.getExe pkgs.pgbouncer} ${confFile}"; ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID"; RuntimeDirectory = "pgbouncer"; - PIDFile = "/run/pgbouncer/pgbouncer.pid"; LimitNOFILE = cfg.openFilesLimit; }; }; - networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port; + networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.listenPort; }; diff --git a/nixpkgs/nixos/modules/services/display-managers/greetd.nix b/nixpkgs/nixos/modules/services/display-managers/greetd.nix index 2212f97a9ffe..c2d345152de9 100644 --- a/nixpkgs/nixos/modules/services/display-managers/greetd.nix +++ b/nixpkgs/nixos/modules/services/display-managers/greetd.nix @@ -78,7 +78,7 @@ in serviceConfig = { ExecStart = "${pkgs.greetd.greetd}/bin/greetd --config ${settingsFormat.generate "greetd.toml" cfg.settings}"; - Restart = mkIf cfg.restart "always"; + Restart = mkIf cfg.restart "on-success"; # Defaults from greetd upstream configuration IgnoreSIGPIPE = false; diff --git a/nixpkgs/nixos/modules/services/games/teeworlds.nix b/nixpkgs/nixos/modules/services/games/teeworlds.nix index bd0df1ffca57..04b611fb3cb1 100644 --- a/nixpkgs/nixos/modules/services/games/teeworlds.nix +++ b/nixpkgs/nixos/modules/services/games/teeworlds.nix @@ -6,13 +6,86 @@ let cfg = config.services.teeworlds; register = cfg.register; + bool = b: if b != null && b then "1" else "0"; + optionalSetting = s: setting: optionalString (s != null) "${setting} ${s}"; + lookup = attrs: key: default: if attrs ? key then attrs."${key}" else default; + + inactivePenaltyOptions = { + "spectator" = "1"; + "spectator/kick" = "2"; + "kick" = "3"; + }; + skillLevelOptions = { + "casual" = "0"; + "normal" = "1"; + "competitive" = "2"; + }; + tournamentModeOptions = { + "disable" = "0"; + "enable" = "1"; + "restrictSpectators" = "2"; + }; + teeworldsConf = pkgs.writeText "teeworlds.cfg" '' sv_port ${toString cfg.port} - sv_register ${if cfg.register then "1" else "0"} - ${optionalString (cfg.name != null) "sv_name ${cfg.name}"} - ${optionalString (cfg.motd != null) "sv_motd ${cfg.motd}"} - ${optionalString (cfg.password != null) "password ${cfg.password}"} - ${optionalString (cfg.rconPassword != null) "sv_rcon_password ${cfg.rconPassword}"} + sv_register ${bool cfg.register} + sv_name ${cfg.name} + ${optionalSetting cfg.motd "sv_motd"} + ${optionalSetting cfg.password "password"} + ${optionalSetting cfg.rconPassword "sv_rcon_password"} + + ${optionalSetting cfg.server.bindAddr "bindaddr"} + ${optionalSetting cfg.server.hostName "sv_hostname"} + sv_high_bandwidth ${bool cfg.server.enableHighBandwidth} + sv_inactivekick ${lookup inactivePenaltyOptions cfg.server.inactivePenalty "spectator/kick"} + sv_inactivekick_spec ${bool cfg.server.kickInactiveSpectators} + sv_inactivekick_time ${toString cfg.server.inactiveTime} + sv_max_clients ${toString cfg.server.maxClients} + sv_max_clients_per_ip ${toString cfg.server.maxClientsPerIP} + sv_skill_level ${lookup skillLevelOptions cfg.server.skillLevel "normal"} + sv_spamprotection ${bool cfg.server.enableSpamProtection} + + sv_gametype ${cfg.game.gameType} + sv_map ${cfg.game.map} + sv_match_swap ${bool cfg.game.swapTeams} + sv_player_ready_mode ${bool cfg.game.enableReadyMode} + sv_player_slots ${toString cfg.game.playerSlots} + sv_powerups ${bool cfg.game.enablePowerups} + sv_scorelimit ${toString cfg.game.scoreLimit} + sv_strict_spectate_mode ${bool cfg.game.restrictSpectators} + sv_teamdamage ${bool cfg.game.enableTeamDamage} + sv_timelimit ${toString cfg.game.timeLimit} + sv_tournament_mode ${lookup tournamentModeOptions cfg.server.tournamentMode "disable"} + sv_vote_kick ${bool cfg.game.enableVoteKick} + sv_vote_kick_bantime ${toString cfg.game.voteKickBanTime} + sv_vote_kick_min ${toString cfg.game.voteKickMinimumPlayers} + + ${optionalSetting cfg.server.bindAddr "bindaddr"} + ${optionalSetting cfg.server.hostName "sv_hostname"} + sv_high_bandwidth ${bool cfg.server.enableHighBandwidth} + sv_inactivekick ${lookup inactivePenaltyOptions cfg.server.inactivePenalty "spectator/kick"} + sv_inactivekick_spec ${bool cfg.server.kickInactiveSpectators} + sv_inactivekick_time ${toString cfg.server.inactiveTime} + sv_max_clients ${toString cfg.server.maxClients} + sv_max_clients_per_ip ${toString cfg.server.maxClientsPerIP} + sv_skill_level ${lookup skillLevelOptions cfg.server.skillLevel "normal"} + sv_spamprotection ${bool cfg.server.enableSpamProtection} + + sv_gametype ${cfg.game.gameType} + sv_map ${cfg.game.map} + sv_match_swap ${bool cfg.game.swapTeams} + sv_player_ready_mode ${bool cfg.game.enableReadyMode} + sv_player_slots ${toString cfg.game.playerSlots} + sv_powerups ${bool cfg.game.enablePowerups} + sv_scorelimit ${toString cfg.game.scoreLimit} + sv_strict_spectate_mode ${bool cfg.game.restrictSpectators} + sv_teamdamage ${bool cfg.game.enableTeamDamage} + sv_timelimit ${toString cfg.game.timeLimit} + sv_tournament_mode ${lookup tournamentModeOptions cfg.server.tournamentMode "disable"} + sv_vote_kick ${bool cfg.game.enableVoteKick} + sv_vote_kick_bantime ${toString cfg.game.voteKickBanTime} + sv_vote_kick_min ${toString cfg.game.voteKickMinimumPlayers} + ${concatStringsSep "\n" cfg.extraOptions} ''; @@ -22,17 +95,19 @@ in services.teeworlds = { enable = mkEnableOption (lib.mdDoc "Teeworlds Server"); + package = mkPackageOptionMD pkgs "teeworlds-server" { }; + openPorts = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to open firewall ports for Teeworlds"; + description = lib.mdDoc "Whether to open firewall ports for Teeworlds."; }; name = mkOption { - type = types.nullOr types.str; - default = null; + type = types.str; + default = "unnamed server"; description = lib.mdDoc '' - Name of the server. Defaults to 'unnamed server'. + Name of the server. ''; }; @@ -41,7 +116,7 @@ in example = true; default = false; description = lib.mdDoc '' - Whether the server registers as public server in the global server list. This is disabled by default because of privacy. + Whether the server registers as a public server in the global server list. This is disabled by default for privacy reasons. ''; }; @@ -49,7 +124,7 @@ in type = types.nullOr types.str; default = null; description = lib.mdDoc '' - Set the server message of the day text. + The server's message of the day text. ''; }; @@ -85,6 +160,217 @@ in ''; example = [ "sv_map dm1" "sv_gametype dm" ]; }; + + server = { + bindAddr = mkOption { + type = types.nullOr types.str; + default = null; + description = lib.mdDoc '' + The address the server will bind to. + ''; + }; + + enableHighBandwidth = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to enable high bandwidth mode on LAN servers. This will double the amount of bandwidth required for running the server. + ''; + }; + + hostName = mkOption { + type = types.nullOr types.str; + default = null; + description = lib.mdDoc '' + Hostname for the server. + ''; + }; + + inactivePenalty = mkOption { + type = types.enum [ "spectator" "spectator/kick" "kick" ]; + example = "spectator"; + default = "spectator/kick"; + description = lib.mdDoc '' + Specify what to do when a client goes inactive (see [](#opt-services.teeworlds.server.inactiveTime)). + + - `spectator`: send the client into spectator mode + + - `spectator/kick`: send the client into a free spectator slot, otherwise kick the client + + - `kick`: kick the client + ''; + }; + + kickInactiveSpectators = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to kick inactive spectators. + ''; + }; + + inactiveTime = mkOption { + type = types.ints.unsigned; + default = 3; + description = lib.mdDoc '' + The amount of minutes a client has to idle before it is considered inactive. + ''; + }; + + maxClients = mkOption { + type = types.ints.unsigned; + default = 12; + description = lib.mdDoc '' + The maximum amount of clients that can be connected to the server at the same time. + ''; + }; + + maxClientsPerIP = mkOption { + type = types.ints.unsigned; + default = 12; + description = lib.mdDoc '' + The maximum amount of clients with the same IP address that can be connected to the server at the same time. + ''; + }; + + skillLevel = mkOption { + type = types.enum [ "casual" "normal" "competitive" ]; + default = "normal"; + description = lib.mdDoc '' + The skill level shown in the server browser. + ''; + }; + + enableSpamProtection = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to enable chat spam protection. + ''; + }; + }; + + game = { + gameType = mkOption { + type = types.str; + example = "ctf"; + default = "dm"; + description = lib.mdDoc '' + The game type to use on the server. + + The default gametypes are `dm`, `tdm`, `ctf`, `lms`, and `lts`. + ''; + }; + + map = mkOption { + type = types.str; + example = "ctf5"; + default = "dm1"; + description = lib.mdDoc '' + The map to use on the server. + ''; + }; + + swapTeams = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to swap teams each round. + ''; + }; + + enableReadyMode = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to enable "ready mode"; where players can pause/unpause the game + and start the game in warmup, using their ready state. + ''; + }; + + playerSlots = mkOption { + type = types.ints.unsigned; + default = 8; + description = lib.mdDoc '' + The amount of slots to reserve for players (as opposed to spectators). + ''; + }; + + enablePowerups = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to allow powerups such as the ninja. + ''; + }; + + scoreLimit = mkOption { + type = types.ints.unsigned; + example = 400; + default = 20; + description = lib.mdDoc '' + The score limit needed to win a round. + ''; + }; + + restrictSpectators = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to restrict access to information such as health, ammo and armour in spectator mode. + ''; + }; + + enableTeamDamage = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to enable team damage; whether to allow team mates to inflict damage on one another. + ''; + }; + + timeLimit = mkOption { + type = types.ints.unsigned; + default = 0; + description = lib.mdDoc '' + Time limit of the game. In cases of equal points, there will be sudden death. + Setting this to 0 disables a time limit. + ''; + }; + + tournamentMode = mkOption { + type = types.enum [ "disable" "enable" "restrictSpectators" ]; + default = "disable"; + description = lib.mdDoc '' + Whether to enable tournament mode. In tournament mode, players join as spectators. + If this is set to `restrictSpectators`, tournament mode is enabled but spectator chat is restricted. + ''; + }; + + enableVoteKick = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Whether to enable voting to kick players. + ''; + }; + + voteKickBanTime = mkOption { + type = types.ints.unsigned; + default = 5; + description = lib.mdDoc '' + The amount of minutes that a player is banned for if they get kicked by a vote. + ''; + }; + + voteKickMinimumPlayers = mkOption { + type = types.ints.unsigned; + default = 5; + description = lib.mdDoc '' + The minimum amount of players required to start a kick vote. + ''; + }; + }; }; }; @@ -100,7 +386,7 @@ in serviceConfig = { DynamicUser = true; - ExecStart = "${pkgs.teeworlds-server}/bin/teeworlds_srv -f ${teeworldsConf}"; + ExecStart = "${cfg.package}/bin/teeworlds_srv -f ${teeworldsConf}"; # Hardening CapabilityBoundingSet = false; diff --git a/nixpkgs/nixos/modules/services/hardware/asusd.nix b/nixpkgs/nixos/modules/services/hardware/asusd.nix index ebbdea26c051..ff9a751e5be8 100644 --- a/nixpkgs/nixos/modules/services/hardware/asusd.nix +++ b/nixpkgs/nixos/modules/services/hardware/asusd.nix @@ -8,6 +8,8 @@ in services.asusd = { enable = lib.mkEnableOption (lib.mdDoc "the asusd service for ASUS ROG laptops"); + package = lib.mkPackageOption pkgs "asusctl" { }; + enableUserService = lib.mkOption { type = lib.types.bool; default = false; @@ -73,7 +75,7 @@ in }; config = lib.mkIf cfg.enable { - environment.systemPackages = [ pkgs.asusctl ]; + environment.systemPackages = [ cfg.package ]; environment.etc = let @@ -92,9 +94,9 @@ in }; services.dbus.enable = true; - systemd.packages = [ pkgs.asusctl ]; - services.dbus.packages = [ pkgs.asusctl ]; - services.udev.packages = [ pkgs.asusctl ]; + systemd.packages = [ cfg.package ]; + services.dbus.packages = [ cfg.package ]; + services.udev.packages = [ cfg.package ]; services.supergfxd.enable = lib.mkDefault true; systemd.user.services.asusd-user.enable = cfg.enableUserService; diff --git a/nixpkgs/nixos/modules/services/hardware/bolt.nix b/nixpkgs/nixos/modules/services/hardware/bolt.nix index 6990a9ea63b3..3bdf67cc1758 100644 --- a/nixpkgs/nixos/modules/services/hardware/bolt.nix +++ b/nixpkgs/nixos/modules/services/hardware/bolt.nix @@ -1,14 +1,13 @@ -# Thunderbolt 3 device manager - { config, lib, pkgs, ...}: with lib; +let + cfg = config.services.hardware.bolt; +in { options = { - services.hardware.bolt = { - enable = mkOption { type = types.bool; default = false; @@ -20,15 +19,13 @@ with lib; ''; }; + package = mkPackageOption pkgs "bolt" { }; }; - }; - config = mkIf config.services.hardware.bolt.enable { - - environment.systemPackages = [ pkgs.bolt ]; - services.udev.packages = [ pkgs.bolt ]; - systemd.packages = [ pkgs.bolt ]; - + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + services.udev.packages = [ cfg.package ]; + systemd.packages = [ cfg.package ]; }; } diff --git a/nixpkgs/nixos/modules/services/hardware/brltty.nix b/nixpkgs/nixos/modules/services/hardware/brltty.nix index 3133804f485f..f96760e92c57 100644 --- a/nixpkgs/nixos/modules/services/hardware/brltty.nix +++ b/nixpkgs/nixos/modules/services/hardware/brltty.nix @@ -34,6 +34,7 @@ in { users.users.brltty = { description = "BRLTTY daemon user"; group = "brltty"; + isSystemUser = true; }; users.groups = { brltty = { }; diff --git a/nixpkgs/nixos/modules/services/hardware/undervolt.nix b/nixpkgs/nixos/modules/services/hardware/undervolt.nix index 67d8171587bb..c4d4c6791a21 100644 --- a/nixpkgs/nixos/modules/services/hardware/undervolt.nix +++ b/nixpkgs/nixos/modules/services/hardware/undervolt.nix @@ -12,6 +12,7 @@ let inherit (cfg) verbose temp + turbo ; # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs: # @@ -105,6 +106,14 @@ in ''; }; + turbo = mkOption { + type = types.nullOr types.int; + default = null; + description = lib.mdDoc '' + Changes the Intel Turbo feature status (1 is disabled and 0 is enabled). + ''; + }; + p1.limit = mkOption { type = with types; nullOr int; default = null; diff --git a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix index f576a426b318..8ab3497f7a17 100644 --- a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix +++ b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix @@ -32,10 +32,15 @@ in { global.tracing.level = mkDefault "info"; queue.path = mkDefault "${dataDir}/queue"; report.path = mkDefault "${dataDir}/reports"; + store.db.type = mkDefault "sqlite"; store.db.path = mkDefault "${dataDir}/data/index.sqlite3"; - store.blob.type = mkDefault "local"; - store.blob.local.path = mkDefault "${dataDir}/data/blobs"; + store.blob.type = mkDefault "fs"; + store.blob.path = mkDefault "${dataDir}/data/blobs"; + storage.data = mkDefault "db"; + storage.fts = mkDefault "db"; + storage.blob = mkDefault "blob"; resolver.type = mkDefault "system"; + resolver.public-suffix = mkDefault ["https://publicsuffix.org/list/public_suffix_list.dat"]; }; systemd.services.stalwart-mail = { @@ -57,8 +62,8 @@ in { KillSignal = "SIGINT"; Restart = "on-failure"; RestartSec = 5; - StandardOutput = "syslog"; - StandardError = "syslog"; + StandardOutput = "journal"; + StandardError = "journal"; SyslogIdentifier = "stalwart-mail"; DynamicUser = true; diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix index 80a6162b2168..557d6d7e7168 100644 --- a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix +++ b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix @@ -790,13 +790,21 @@ in ''; }; systemd.tmpfiles.settings."10-sourcehut-gitsrht" = mkIf cfg.git.enable ( - builtins.listToAttrs (map (name: { - name = "/var/log/sourcehut/gitsrht-${name}"; - value.f = { - inherit (cfg.git) user group; - mode = "0644"; - }; - }) [ "keys" "shell" "update-hook" ]) + mkMerge [ + (builtins.listToAttrs (map (name: { + name = "/var/log/sourcehut/gitsrht-${name}"; + value.f = { + inherit (cfg.git) user group; + mode = "0644"; + }; + }) [ "keys" "shell" "update-hook" ])) + { + ${cfg.settings."git.sr.ht".repos}.d = { + inherit (cfg.git) user group; + mode = "0644"; + }; + } + ] ); systemd.services.sshd = { preStart = mkIf cfg.hg.enable '' diff --git a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix index 6c51a9bb8555..a8300ecd5233 100644 --- a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix +++ b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix @@ -17,14 +17,11 @@ let lib.mapAttrs (_: toString) cfg.extraConfig ); - manage = - let - setupEnv = lib.concatStringsSep "\n" (mapAttrsToList (name: val: "export ${name}=\"${val}\"") env); - in - pkgs.writeShellScript "manage" '' - ${setupEnv} - exec ${pkg}/bin/tandoor-recipes "$@" - ''; + manage = pkgs.writeShellScript "manage" '' + set -o allexport # Export the following env vars + ${lib.toShellVars env} + exec ${pkg}/bin/tandoor-recipes "$@" + ''; in { meta.maintainers = with maintainers; [ ambroisie ]; diff --git a/nixpkgs/nixos/modules/services/networking/go-camo.nix b/nixpkgs/nixos/modules/services/networking/go-camo.nix new file mode 100644 index 000000000000..cb3b6eade464 --- /dev/null +++ b/nixpkgs/nixos/modules/services/networking/go-camo.nix @@ -0,0 +1,73 @@ +{ lib, pkgs, config, ... }: + +let + cfg = config.services.go-camo; + inherit (lib) mkOption mkEnableOption mkIf mkMerge types optionalString; +in +{ + options.services.go-camo = { + enable = mkEnableOption "go-camo service"; + listen = mkOption { + type = types.nullOr types.str; + default = null; + description = "Address:Port to bind to for HTTP (default: 0.0.0.0:8080)."; + apply = v: optionalString (v != null) "--listen=${v}"; + }; + sslListen = mkOption { + type = types.nullOr types.str; + default = null; + description = "Address:Port to bind to for HTTPS."; + apply = v: optionalString (v != null) "--ssl-listen=${v}"; + }; + sslKey = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to TLS private key."; + apply = v: optionalString (v != null) "--ssl-key=${v}"; + }; + sslCert = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to TLS certificate."; + apply = v: optionalString (v != null) "--ssl-cert=${v}"; + }; + keyFile = mkOption { + type = types.path; + default = null; + description = '' + A file containing the HMAC key to use for signing URLs. + The file can contain any string. Can be generated using "openssl rand -base64 18 > the_file". + ''; + }; + extraOptions = mkOption { + type = with types; listOf str; + default = []; + description = "Extra options passed to the go-camo command."; + }; + }; + + config = mkIf cfg.enable { + systemd.services.go-camo = { + description = "go-camo service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + environment = { + GOCAMO_HMAC_FILE = "%d/hmac"; + }; + script = '' + export GOCAMO_HMAC=$(cat "$GOCAMO_HMAC_FILE") + exec ${lib.escapeShellArgs(lib.lists.remove "" ([ "${pkgs.go-camo}/bin/go-camo" cfg.listen cfg.sslListen cfg.sslKey cfg.sslCert ] ++ cfg.extraOptions))} + ''; + serviceConfig = { + NoNewPrivileges = true; + ProtectSystem = "strict"; + DynamicUser = true; + User = "gocamo"; + Group = "gocamo"; + LoadCredential = [ + "hmac:${cfg.keyFile}" + ]; + }; + }; + }; +} diff --git a/nixpkgs/nixos/modules/services/networking/hostapd.nix b/nixpkgs/nixos/modules/services/networking/hostapd.nix index 00482e59acf3..40542155ed63 100644 --- a/nixpkgs/nixos/modules/services/networking/hostapd.nix +++ b/nixpkgs/nixos/modules/services/networking/hostapd.nix @@ -909,7 +909,7 @@ in { in { settings = { ssid = bssCfg.ssid; - utf8_ssid = bssCfg.ssid; + utf8_ssid = bssCfg.utf8Ssid; logger_syslog = mkDefault (-1); logger_syslog_level = bssCfg.logLevel; diff --git a/nixpkgs/nixos/modules/services/networking/knot.nix b/nixpkgs/nixos/modules/services/networking/knot.nix index 94c32586736a..6488a159b3b7 100644 --- a/nixpkgs/nixos/modules/services/networking/knot.nix +++ b/nixpkgs/nixos/modules/services/networking/knot.nix @@ -1,8 +1,36 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, utils, ... }: -with lib; let + inherit (lib) + attrNames + concatMapStrings + concatMapStringsSep + concatStrings + concatStringsSep + elem + filter + flip + hasAttr + hasPrefix + isAttrs + isBool + isDerivation + isList + mapAttrsToList + mkChangedOptionModule + mkEnableOption + mkIf + mkOption + mkPackageOption + optionals + types + ; + + inherit (utils) + escapeSystemdExecArgs + ; + cfg = config.services.knot; yamlConfig = let @@ -113,8 +141,7 @@ let mkConfigFile = configString: pkgs.writeTextFile { name = "knot.conf"; text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + configString; - # TODO: maybe we could do some checks even when private keys complicate this? - checkPhase = lib.optionalString (cfg.keyFiles == []) '' + checkPhase = lib.optionalString cfg.checkConfig '' ${cfg.package}/bin/knotc --config=$out conf-check ''; }; @@ -142,12 +169,45 @@ let in { options = { services.knot = { - enable = mkEnableOption (lib.mdDoc "Knot authoritative-only DNS server"); + enable = mkEnableOption "Knot authoritative-only DNS server"; + + enableXDP = mkOption { + type = types.bool; + default = lib.hasAttrByPath [ "xdp" "listen" ] cfg.settings; + defaultText = '' + Enabled when the `xdp.listen` setting is configured through `settings`. + ''; + example = true; + description = '' + Extends the systemd unit with permissions to allow for the use of + the eXpress Data Path (XDP). + + ::: {.note} + Make sure to read up on functional [limitations](https://www.knot-dns.cz/docs/latest/singlehtml/index.html#mode-xdp-limitations) + when running in XDP mode. + ::: + ''; + }; + + checkConfig = mkOption { + type = types.bool; + # TODO: maybe we could do some checks even when private keys complicate this? + # conf-check fails hard on missing IPs/devices with XDP + default = cfg.keyFiles == [] && !cfg.enableXDP; + defaultText = '' + Disabled when the config uses `keyFiles` or `enableXDP`. + ''; + example = false; + description = '' + Toggles the configuration test at build time. It runs in a + sandbox, and therefore cannot be used in all scenarios. + ''; + }; extraArgs = mkOption { type = types.listOf types.str; default = []; - description = lib.mdDoc '' + description = '' List of additional command line parameters for knotd ''; }; @@ -155,7 +215,7 @@ in { keyFiles = mkOption { type = types.listOf types.path; default = []; - description = lib.mdDoc '' + description = '' A list of files containing additional configuration to be included using the include directive. This option allows to include configuration like TSIG keys without @@ -168,7 +228,7 @@ in { settings = mkOption { type = types.attrs; default = {}; - description = lib.mdDoc '' + description = '' Extra configuration as nix values. ''; }; @@ -176,7 +236,7 @@ in { settingsFile = mkOption { type = types.nullOr types.path; default = null; - description = lib.mdDoc '' + description = '' As alternative to ``settings``, you can provide whole configuration directly in the almost-YAML format of Knot DNS. You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this. @@ -210,19 +270,35 @@ in { wants = [ "network.target" ]; after = ["network.target" ]; - serviceConfig = { + serviceConfig = let + # https://www.knot-dns.cz/docs/3.3/singlehtml/index.html#pre-requisites + xdpCapabilities = lib.optionals (cfg.enableXDP) [ + "CAP_NET_ADMIN" + "CAP_NET_RAW" + "CAP_SYS_ADMIN" + "CAP_IPC_LOCK" + ] ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "5.11") [ + "CAP_SYS_RESOURCE" + ]; + in { Type = "notify"; - ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}"; - ExecReload = "${knot-cli-wrappers}/bin/knotc reload"; + ExecStart = escapeSystemdExecArgs ([ + (lib.getExe cfg.package) + "--config=${configFile}" + "--socket=${socketFile}" + ] ++ cfg.extraArgs); + ExecReload = escapeSystemdExecArgs [ + "${knot-cli-wrappers}/bin/knotc" "reload" + ]; User = "knot"; Group = "knot"; AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" - ]; + ] ++ xdpCapabilities; CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" - ]; + ] ++ xdpCapabilities; DeviceAllow = ""; DevicePolicy = "closed"; LockPersonality = true; @@ -247,6 +323,9 @@ in { "AF_INET" "AF_INET6" "AF_UNIX" + ] ++ optionals (cfg.enableXDP) [ + "AF_NETLINK" + "AF_XDP" ]; RestrictNamespaces = true; RestrictRealtime =true; @@ -258,6 +337,8 @@ in { SystemCallFilter = [ "@system-service" "~@privileged" + ] ++ optionals (cfg.enableXDP) [ + "bpf" ]; UMask = "0077"; }; diff --git a/nixpkgs/nixos/modules/services/networking/libreswan.nix b/nixpkgs/nixos/modules/services/networking/libreswan.nix index db4d2f7f0ba0..a44cac93d5f6 100644 --- a/nixpkgs/nixos/modules/services/networking/libreswan.nix +++ b/nixpkgs/nixos/modules/services/networking/libreswan.nix @@ -133,9 +133,6 @@ in "ipsec.d/01-nixos.conf".source = configFile; } // policyFiles; - # Create NSS database directory - systemd.tmpfiles.rules = [ "d /var/lib/ipsec/nss 755 root root -" ]; - systemd.services.ipsec = { description = "Internet Key Exchange (IKE) Protocol Daemon for IPsec"; wantedBy = [ "multi-user.target" ]; @@ -153,6 +150,10 @@ in echo 0 | tee /proc/sys/net/ipv4/conf/*/send_redirects echo 0 | tee /proc/sys/net/ipv{4,6}/conf/*/accept_redirects ''; + serviceConfig = { + StateDirectory = "ipsec/nss"; + StateDirectoryMode = 0700; + }; }; }; diff --git a/nixpkgs/nixos/modules/services/security/opensnitch.nix b/nixpkgs/nixos/modules/services/security/opensnitch.nix index 97ac3a72804c..42cf8159f3ea 100644 --- a/nixpkgs/nixos/modules/services/security/opensnitch.nix +++ b/nixpkgs/nixos/modules/services/security/opensnitch.nix @@ -36,7 +36,8 @@ in { description = mdDoc '' Declarative configuration of firewall rules. - All rules will be stored in `/var/lib/opensnitch/rules`. + All rules will be stored in `/var/lib/opensnitch/rules` by default. + Rules path can be configured with `settings.Rules.Path`. See [upstream documentation](https://github.com/evilsocket/opensnitch/wiki/Rules) for available options. ''; @@ -79,15 +80,6 @@ in { ''; }; - DefaultDuration = mkOption { - type = types.enum [ - "once" "always" "until restart" "30s" "5m" "15m" "30m" "1h" - ]; - description = mdDoc '' - Default duration of firewall rule. - ''; - }; - InterceptUnknown = mkOption { type = types.bool; description = mdDoc '' @@ -134,6 +126,30 @@ in { }; }; + + Ebpf.ModulesPath = mkOption { + type = types.path; + default = if cfg.settings.ProcMonitorMethod == "ebpf" then "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd" else null; + defaultText = literalExpression '' + if cfg.settings.ProcMonitorMethod == "ebpf" then + "\\$\\{config.boot.kernelPackages.opensnitch-ebpf\\}/etc/opensnitchd" + else null; + ''; + description = mdDoc '' + Configure eBPF modules path. Used when + `settings.ProcMonitorMethod` is set to `ebpf`. + ''; + }; + + Rules.Path = mkOption { + type = types.path; + default = "/var/lib/opensnitch/rules"; + description = mdDoc '' + Path to the directory where firewall rules can be found and will + get stored by the NixOS module. + ''; + }; + }; }; description = mdDoc '' @@ -151,40 +167,42 @@ in { systemd = { packages = [ pkgs.opensnitch ]; - services.opensnitchd.wantedBy = [ "multi-user.target" ]; + services.opensnitchd = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = [ + "" + "${pkgs.opensnitch}/bin/opensnitchd --config-file ${format.generate "default-config.json" cfg.settings}" + ]; + }; + preStart = mkIf (cfg.rules != {}) (let + rules = flip mapAttrsToList predefinedRules (file: content: { + inherit (content) file; + local = "${cfg.settings.Rules.Path}/${file}.json"; + }); + in '' + # Remove all firewall rules from rules path (configured with + # cfg.settings.Rules.Path) that are symlinks to a store-path, but aren't + # declared in `cfg.rules` (i.e. all networks that were "removed" from + # `cfg.rules`). + find ${cfg.settings.Rules.Path} -type l -lname '${builtins.storeDir}/*' ${optionalString (rules != {}) '' + -not \( ${concatMapStringsSep " -o " ({ local, ... }: + "-name '${baseNameOf local}*'") + rules} \) \ + ''} -delete + ${concatMapStrings ({ file, local }: '' + ln -sf '${file}' "${local}" + '') rules} + ''); + }; + tmpfiles.rules = [ + "d ${cfg.settings.Rules.Path} 0750 root root - -" + "L+ /etc/opensnitchd/system-fw.json - - - - ${pkgs.opensnitch}/etc/opensnitchd/system-fw.json" + ]; }; - systemd.services.opensnitchd.preStart = mkIf (cfg.rules != {}) (let - rules = flip mapAttrsToList predefinedRules (file: content: { - inherit (content) file; - local = "/var/lib/opensnitch/rules/${file}.json"; - }); - in '' - # Remove all firewall rules from `/var/lib/opensnitch/rules` that are symlinks to a store-path, - # but aren't declared in `cfg.rules` (i.e. all networks that were "removed" from - # `cfg.rules`). - find /var/lib/opensnitch/rules -type l -lname '${builtins.storeDir}/*' ${optionalString (rules != {}) '' - -not \( ${concatMapStringsSep " -o " ({ local, ... }: - "-name '${baseNameOf local}*'") - rules} \) \ - ''} -delete - ${concatMapStrings ({ file, local }: '' - ln -sf '${file}' "${local}" - '') rules} - - if [ ! -f /etc/opensnitchd/system-fw.json ]; then - cp "${pkgs.opensnitch}/etc/opensnitchd/system-fw.json" "/etc/opensnitchd/system-fw.json" - fi - ''); - - environment.etc = mkMerge [ ({ - "opensnitchd/default-config.json".source = format.generate "default-config.json" cfg.settings; - }) (mkIf (cfg.settings.ProcMonitorMethod == "ebpf") { - "opensnitchd/opensnitch.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch.o"; - "opensnitchd/opensnitch-dns.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-dns.o"; - "opensnitchd/opensnitch-procs.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-procs.o"; - })]; - }; + + meta.maintainers = with lib.maintainers; [ onny ]; } diff --git a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix index 8934ed3a7ef2..7d3cd004a7ba 100644 --- a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix +++ b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix @@ -50,7 +50,7 @@ in serviceConfig = { Type = "exec"; User = "automatic-timezoned"; - ExecStart = "${cfg.package}/bin/automatic-timezoned --zoneinfo-path=${pkgs.tzdata}/share/zoneinfo/zone1970.tab"; + ExecStart = "${cfg.package}/bin/automatic-timezoned"; }; wantedBy = [ "default.target" ]; }; diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix index 5dd02eb33163..a9fb123b981e 100644 --- a/nixpkgs/nixos/modules/services/torrent/transmission.nix +++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix @@ -74,7 +74,7 @@ in description = lib.mdDoc ""; }; options.message-level = mkOption { - type = types.ints.between 0 3; + type = types.ints.between 0 6; default = 2; description = lib.mdDoc "Set verbosity of transmission messages."; }; diff --git a/nixpkgs/nixos/modules/services/web-apps/mastodon.nix b/nixpkgs/nixos/modules/services/web-apps/mastodon.nix index 8d09d1b97828..7fc710c6fcec 100644 --- a/nixpkgs/nixos/modules/services/web-apps/mastodon.nix +++ b/nixpkgs/nixos/modules/services/web-apps/mastodon.nix @@ -4,7 +4,8 @@ let cfg = config.services.mastodon; opt = options.services.mastodon; - # We only want to create a database if we're actually going to connect to it. + # We only want to create a Redis and PostgreSQL databases if we're actually going to connect to it local. + redisActuallyCreateLocally = cfg.redis.createLocally && (cfg.redis.host == "127.0.0.1" || cfg.redis.enableUnixSocket); databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == "/run/postgresql"; env = { @@ -33,6 +34,7 @@ let TRUSTED_PROXY_IP = cfg.trustedProxy; } + // lib.optionalAttrs (cfg.redis.createLocally && cfg.redis.enableUnixSocket) { REDIS_URL = "unix://${config.services.redis.servers.mastodon.unixSocket}"; } // lib.optionalAttrs (cfg.database.host != "/run/postgresql" && cfg.database.port != null) { DB_PORT = toString cfg.database.port; } // lib.optionalAttrs cfg.smtp.authenticate { SMTP_LOGIN = cfg.smtp.user; } // lib.optionalAttrs (cfg.elasticsearch.host != null) { ES_HOST = cfg.elasticsearch.host; } @@ -116,9 +118,11 @@ let threads = toString (if processCfg.threads == null then cfg.sidekiqThreads else processCfg.threads); in { after = [ "network.target" "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; requires = [ "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; description = "Mastodon sidekiq${jobClassLabel}"; @@ -146,9 +150,11 @@ let name = "mastodon-streaming-${toString i}"; value = { after = [ "network.target" "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; requires = [ "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; wantedBy = [ "mastodon.target" "mastodon-streaming.target" ]; @@ -404,6 +410,19 @@ in { type = lib.types.port; default = 31637; }; + + passwordFile = lib.mkOption { + description = lib.mdDoc "A file containing the password for Redis database."; + type = lib.types.nullOr lib.types.path; + default = null; + example = "/run/keys/mastodon-redis-password"; + }; + + enableUnixSocket = lib.mkOption { + description = lib.mdDoc "Use Unix socket"; + type = lib.types.bool; + default = true; + }; }; database = { @@ -613,6 +632,13 @@ in { config = lib.mkIf cfg.enable (lib.mkMerge [{ assertions = [ { + assertion = redisActuallyCreateLocally -> (!cfg.redis.enableUnixSocket || cfg.redis.passwordFile == null); + message = '' + <option>services.mastodon.redis.enableUnixSocket</option> needs to be disabled if + <option>services.mastodon.redis.passwordFile</option> is used. + ''; + } + { assertion = databaseActuallyCreateLocally -> (cfg.user == cfg.database.user && cfg.database.user == cfg.database.name); message = '' For local automatic database provisioning (services.mastodon.database.createLocally == true) with peer @@ -689,6 +715,8 @@ in { OTP_SECRET="$(cat ${cfg.otpSecretFile})" VAPID_PRIVATE_KEY="$(cat ${cfg.vapidPrivateKeyFile})" VAPID_PUBLIC_KEY="$(cat ${cfg.vapidPublicKeyFile})" + '' + lib.optionalString (cfg.redis.passwordFile != null)'' + REDIS_PASSWORD="$(cat ${cfg.redis.passwordFile})" '' + lib.optionalString (cfg.database.passwordFile != null) '' DB_PASS="$(cat ${cfg.database.passwordFile})" '' + lib.optionalString cfg.smtp.authenticate '' @@ -751,9 +779,11 @@ in { systemd.services.mastodon-web = { after = [ "network.target" "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; requires = [ "mastodon-init-dirs.service" ] + ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service" ++ lib.optional databaseActuallyCreateLocally "postgresql.service" ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service"; wantedBy = [ "mastodon.target" ]; @@ -834,11 +864,14 @@ in { enable = true; hostname = lib.mkDefault "${cfg.localDomain}"; }; - services.redis.servers.mastodon = lib.mkIf (cfg.redis.createLocally && cfg.redis.host == "127.0.0.1") { - enable = true; - port = cfg.redis.port; - bind = "127.0.0.1"; - }; + services.redis.servers.mastodon = lib.mkIf redisActuallyCreateLocally (lib.mkMerge [ + { + enable = true; + } + (lib.mkIf (!cfg.redis.enableUnixSocket) { + port = cfg.redis.port; + }) + ]); services.postgresql = lib.mkIf databaseActuallyCreateLocally { enable = true; ensureUsers = [ @@ -859,6 +892,7 @@ in { }; }) (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package pkgs.imagemagick ]) + (lib.mkIf (cfg.redis.createLocally && cfg.redis.enableUnixSocket) {${config.services.mastodon.user}.extraGroups = [ "redis-mastodon" ];}) ]; users.groups.${cfg.group}.members = lib.optional cfg.configureNginx config.services.nginx.user; diff --git a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix index d3773cc9cf78..ccf995fccf3e 100644 --- a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix +++ b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix @@ -12,17 +12,14 @@ let lib.mapAttrs (_: toString) cfg.settings ); - manage = - let - setupEnv = lib.concatStringsSep "\n" (lib.mapAttrsToList (name: val: "export ${name}=${lib.escapeShellArg val}") env); - in - pkgs.writeShellScript "manage" '' - ${setupEnv} - eval "$(${config.systemd.package}/bin/systemctl show -pUID,MainPID photoprism.service | ${pkgs.gnused}/bin/sed "s/UID/ServiceUID/")" - exec ${pkgs.util-linux}/bin/nsenter \ - -t $MainPID -m -S $ServiceUID -G $ServiceUID --wdns=${cfg.storagePath} \ - ${cfg.package}/bin/photoprism "$@" - ''; + manage = pkgs.writeShellScript "manage" '' + set -o allexport # Export the following env vars + ${lib.toShellVars env} + eval "$(${config.systemd.package}/bin/systemctl show -pUID,MainPID photoprism.service | ${pkgs.gnused}/bin/sed "s/UID/ServiceUID/")" + exec ${pkgs.util-linux}/bin/nsenter \ + -t $MainPID -m -S $ServiceUID -G $ServiceUID --wdns=${cfg.storagePath} \ + ${cfg.package}/bin/photoprism "$@" + ''; in { meta.maintainers = with lib.maintainers; [ stunkymonkey ]; diff --git a/nixpkgs/nixos/modules/services/web-servers/garage.nix b/nixpkgs/nixos/modules/services/web-servers/garage.nix index 47b4c6ab416e..48dd5b34757c 100644 --- a/nixpkgs/nixos/modules/services/web-servers/garage.nix +++ b/nixpkgs/nixos/modules/services/web-servers/garage.nix @@ -30,7 +30,7 @@ in }; logLevel = mkOption { - type = types.enum ([ "info" "debug" "trace" ]); + type = types.enum ([ "error" "warn" "info" "debug" "trace" ]); default = "info"; example = "debug"; description = lib.mdDoc "Garage log level, see <https://garagehq.deuxfleurs.fr/documentation/quick-start/#launching-the-garage-server> for examples."; diff --git a/nixpkgs/nixos/modules/services/web-servers/ttyd.nix b/nixpkgs/nixos/modules/services/web-servers/ttyd.nix index e545869ca432..14361df2bb66 100644 --- a/nixpkgs/nixos/modules/services/web-servers/ttyd.nix +++ b/nixpkgs/nixos/modules/services/web-servers/ttyd.nix @@ -1,11 +1,17 @@ { config, lib, pkgs, ... }: -with lib; - let cfg = config.services.ttyd; + inherit (lib) + optionals + types + concatLists + mapAttrsToList + mkOption + ; + # Command line arguments for the ttyd daemon args = [ "--port" (toString cfg.port) ] ++ optionals (cfg.socket != null) [ "--interface" cfg.socket ] @@ -14,6 +20,7 @@ let ++ (concatLists (mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions)) ++ [ "--terminal-type" cfg.terminalType ] ++ optionals cfg.checkOrigin [ "--check-origin" ] + ++ optionals cfg.writeable [ "--writable" ] # the typo is correct ++ [ "--max-clients" (toString cfg.maxClients) ] ++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ] ++ optionals cfg.enableIPv6 [ "--ipv6" ] @@ -30,40 +37,40 @@ in options = { services.ttyd = { - enable = mkEnableOption (lib.mdDoc "ttyd daemon"); + enable = lib.mkEnableOption ("ttyd daemon"); port = mkOption { type = types.port; default = 7681; - description = lib.mdDoc "Port to listen on (use 0 for random port)"; + description = "Port to listen on (use 0 for random port)"; }; socket = mkOption { type = types.nullOr types.path; default = null; example = "/var/run/ttyd.sock"; - description = lib.mdDoc "UNIX domain socket path to bind."; + description = "UNIX domain socket path to bind."; }; interface = mkOption { type = types.nullOr types.str; default = null; example = "eth0"; - description = lib.mdDoc "Network interface to bind."; + description = "Network interface to bind."; }; username = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc "Username for basic authentication."; + description = "Username for basic http authentication."; }; passwordFile = mkOption { type = types.nullOr types.path; default = null; apply = value: if value == null then null else toString value; - description = lib.mdDoc '' - File containing the password to use for basic authentication. + description = '' + File containing the password to use for basic http authentication. For insecurely putting the password in the globally readable store use `pkgs.writeText "ttydpw" "MyPassword"`. ''; @@ -72,19 +79,46 @@ in signal = mkOption { type = types.ints.u8; default = 1; - description = lib.mdDoc "Signal to send to the command on session close."; + description = "Signal to send to the command on session close."; + }; + + entrypoint = mkOption { + type = types.listOf types.str; + default = [ "${pkgs.shadow}/bin/login" ]; + defaultText = lib.literalExpression '' + [ "''${pkgs.shadow}/bin/login" ] + ''; + example = lib.literalExpression '' + [ (lib.getExe pkgs.htop) ] + ''; + description = "Which command ttyd runs."; + apply = lib.escapeShellArgs; + }; + + user = mkOption { + type = types.str; + # `login` needs to be run as root + default = "root"; + description = "Which unix user ttyd should run as."; + }; + + writeable = mkOption { + type = types.nullOr types.bool; + default = null; # null causes an eval error, forcing the user to consider attack surface + example = true; + description = "Allow clients to write to the TTY."; }; clientOptions = mkOption { type = types.attrsOf types.str; default = {}; - example = literalExpression '' + example = lib.literalExpression '' { fontSize = "16"; fontFamily = "Fira Code"; } ''; - description = lib.mdDoc '' + description = '' Attribute set of client options for xtermjs. <https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/> ''; @@ -93,50 +127,50 @@ in terminalType = mkOption { type = types.str; default = "xterm-256color"; - description = lib.mdDoc "Terminal type to report."; + description = "Terminal type to report."; }; checkOrigin = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to allow a websocket connection from a different origin."; + description = "Whether to allow a websocket connection from a different origin."; }; maxClients = mkOption { type = types.int; default = 0; - description = lib.mdDoc "Maximum clients to support (0, no limit)"; + description = "Maximum clients to support (0, no limit)"; }; indexFile = mkOption { type = types.nullOr types.path; default = null; - description = lib.mdDoc "Custom index.html path"; + description = "Custom index.html path"; }; enableIPv6 = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether or not to enable IPv6 support."; + description = "Whether or not to enable IPv6 support."; }; enableSSL = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether or not to enable SSL (https) support."; + description = "Whether or not to enable SSL (https) support."; }; certFile = mkOption { type = types.nullOr types.path; default = null; - description = lib.mdDoc "SSL certificate file path."; + description = "SSL certificate file path."; }; keyFile = mkOption { type = types.nullOr types.path; default = null; apply = value: if value == null then null else toString value; - description = lib.mdDoc '' + description = '' SSL key file path. For insecurely putting the keyFile in the globally readable store use `pkgs.writeText "ttydKeyFile" "SSLKEY"`. @@ -146,25 +180,27 @@ in caFile = mkOption { type = types.nullOr types.path; default = null; - description = lib.mdDoc "SSL CA file path for client certificate verification."; + description = "SSL CA file path for client certificate verification."; }; logLevel = mkOption { type = types.int; default = 7; - description = lib.mdDoc "Set log level."; + description = "Set log level."; }; }; }; ###### implementation - config = mkIf cfg.enable { + config = lib.mkIf cfg.enable { assertions = [ { assertion = cfg.enableSSL -> cfg.certFile != null && cfg.keyFile != null && cfg.caFile != null; message = "SSL is enabled for ttyd, but no certFile, keyFile or caFile has been specified."; } + { assertion = cfg.writeable != null; + message = "services.ttyd.writeable must be set"; } { assertion = ! (cfg.interface != null && cfg.socket != null); message = "Cannot set both interface and socket for ttyd."; } { assertion = (cfg.username != null) == (cfg.passwordFile != null); @@ -177,21 +213,19 @@ in wantedBy = [ "multi-user.target" ]; serviceConfig = { - # Runs login which needs to be run as root - # login: Cannot possibly work without effective root - User = "root"; + User = cfg.user; LoadCredential = lib.optionalString (cfg.passwordFile != null) "TTYD_PASSWORD_FILE:${cfg.passwordFile}"; }; script = if cfg.passwordFile != null then '' PASSWORD=$(cat "$CREDENTIALS_DIRECTORY/TTYD_PASSWORD_FILE") ${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \ - --credential ${escapeShellArg cfg.username}:"$PASSWORD" \ - ${pkgs.shadow}/bin/login + --credential ${lib.escapeShellArg cfg.username}:"$PASSWORD" \ + ${cfg.entrypoint} '' else '' ${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \ - ${pkgs.shadow}/bin/login + ${cfg.entrypoint} ''; }; }; diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix index 463c45675cee..fe39097a22e8 100644 --- a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix +++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix @@ -39,6 +39,10 @@ let ''; destination = "/share/gnome-background-properties/nixos.xml"; }; + + budgie-control-center = pkgs.budgie.budgie-control-center.override { + enableSshSocket = config.services.openssh.startWhenNeeded; + }; in { options = { services.xserver.desktopManager.budgie = { @@ -114,7 +118,7 @@ in { [ # Budgie Desktop. budgie.budgie-backgrounds - budgie.budgie-control-center + budgie-control-center (budgie.budgie-desktop-with-plugins.override { plugins = cfg.extraPlugins; }) budgie.budgie-desktop-view budgie.budgie-screensaver @@ -233,8 +237,8 @@ in { services.gvfs.enable = mkDefault true; # Register packages for DBus. - services.dbus.packages = with pkgs; [ - budgie.budgie-control-center + services.dbus.packages = [ + budgie-control-center ]; # Register packages for udev. diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix index 48741aa41d85..e3cb5cc3be2b 100644 --- a/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix +++ b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix @@ -17,7 +17,7 @@ in { name = "icewm"; start = '' - ${pkgs.icewm}/bin/icewm & + ${pkgs.icewm}/bin/icewm-session & waitPID=$! ''; }; diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix index a46331ccd431..b0ac857feb4b 100644 --- a/nixpkgs/nixos/modules/system/boot/kernel.nix +++ b/nixpkgs/nixos/modules/system/boot/kernel.nix @@ -81,6 +81,13 @@ in extraStructuredConfig.FOO = lib.kernel.yes; features.foo = true; } + { + name = "foo-ml-mbox"; + patch = (fetchurl { + url = "https://lore.kernel.org/lkml/19700205182810.58382-1-email@domain/t.mbox.gz"; + hash = "sha256-..."; + }); + } ] ''; description = lib.mdDoc '' diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix index e990aeea7a14..8f3f3612805f 100644 --- a/nixpkgs/nixos/modules/system/boot/stage-1.nix +++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix @@ -621,6 +621,11 @@ in path the secret should have inside the initrd, the value is the path it should be copied from (or null for the same path inside and out). + + Note that `nixos-rebuild switch` will generate the initrd + also for past generations, so if secrets are moved or deleted + you will also have to garbage collect the generations that + use those secrets. ''; example = literalExpression '' diff --git a/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix b/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix index 000b18c01609..edc25784367a 100644 --- a/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix +++ b/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix @@ -49,15 +49,15 @@ in { systemd.slices."-".sliceConfig = lib.mkIf cfg.enableRootSlice { ManagedOOMMemoryPressure = "kill"; - ManagedOOMMemoryPressureLimit = "80%"; + ManagedOOMMemoryPressureLimit = lib.mkDefault "80%"; }; systemd.slices."system".sliceConfig = lib.mkIf cfg.enableSystemSlice { ManagedOOMMemoryPressure = "kill"; - ManagedOOMMemoryPressureLimit = "80%"; + ManagedOOMMemoryPressureLimit = lib.mkDefault "80%"; }; systemd.slices."user-".sliceConfig = lib.mkIf cfg.enableUserSlices { ManagedOOMMemoryPressure = "kill"; - ManagedOOMMemoryPressureLimit = "80%"; + ManagedOOMMemoryPressureLimit = lib.mkDefault "80%"; }; systemd.user.units."slice" = lib.mkIf cfg.enableUserSlices { text = '' diff --git a/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py b/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py index bf4ec791ecf7..bba454dd888d 100644 --- a/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py +++ b/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py @@ -199,7 +199,8 @@ def main() -> None: size=os.stat(source).st_size, filetype=FileType.file, mode=mode, - payload=target, + # payload needs to be relative path in this case + payload=target.lstrip("/"), ) paths[target] = composefs_path add_leading_directories(target, attrs, paths) diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix index b0d61ee06091..d4d34d13a94d 100644 --- a/nixpkgs/nixos/modules/virtualisation/docker.nix +++ b/nixpkgs/nixos/modules/virtualisation/docker.nix @@ -93,8 +93,18 @@ in default = null; description = lib.mdDoc '' - This option determines which Docker storage driver to use. By default - it let's docker automatically choose preferred storage driver. + This option determines which Docker + [storage driver](https://docs.docker.com/storage/storagedriver/select-storage-driver/) + to use. + By default it lets docker automatically choose the preferred storage + driver. + However, it is recommended to specify a storage driver explicitly, as + docker's default varies over versions. + + ::: {.warning} + Changing the storage driver will cause any existing containers + and images to become inaccessible. + ::: ''; }; diff --git a/nixpkgs/nixos/modules/virtualisation/incus.nix b/nixpkgs/nixos/modules/virtualisation/incus.nix index bbe5b48b95bb..3bbe0ba45851 100644 --- a/nixpkgs/nixos/modules/virtualisation/incus.nix +++ b/nixpkgs/nixos/modules/virtualisation/incus.nix @@ -97,6 +97,12 @@ in considered failed and systemd will attempt to restart it. ''; }; + + ui = { + enable = lib.mkEnableOption (lib.mdDoc "(experimental) Incus UI"); + + package = lib.mkPackageOption pkgs [ "incus" "ui" ] { }; + }; }; }; @@ -165,10 +171,12 @@ in "${config.boot.zfs.package}/lib/udev" ]; - environment = { + environment = lib.mkMerge [ { # Override Path to the LXC template configuration directory INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config"; - }; + } (lib.mkIf (cfg.ui.enable) { + "INCUS_UI" = cfg.ui.package; + }) ]; serviceConfig = { ExecStart = "${cfg.package}/bin/incusd --group incus-admin"; |