diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-09-15 07:58:52 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-09-15 07:58:52 +0000 |
commit | 9d1daa60832979d5d361dfdac136fb9e5a1af2c5 (patch) | |
tree | 5192dd85903cb092cf7dff0e3403387b3b683d84 /nixpkgs/nixos | |
parent | 67cdfc7d42f721bf85814af5a0095fb9f9ea455d (diff) | |
parent | f2ea252d23ebc9a5336bf6a61e0644921f64e67c (diff) | |
download | nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar.gz nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar.bz2 nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar.lz nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar.xz nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.tar.zst nixlib-9d1daa60832979d5d361dfdac136fb9e5a1af2c5.zip |
Merge branch 'nixos-unstable' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/nixos')
35 files changed, 1490 insertions, 354 deletions
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md b/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md index d4581fe9441c..6f5a807f478a 100644 --- a/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2205.section.md @@ -935,8 +935,7 @@ In addition to numerous new and upgraded packages, this release has the followin using the `pomerium-cli` command, you should now install the `pomerium-cli` package. -- The option - [services.networking.networkmanager.enableFccUnlock](#opt-networking.networkmanager.enableFccUnlock) +- The option `services.networking.networkmanager.enableFccUnlock` was added to support FCC unlock procedures. Since release 1.18.4, the ModemManager daemon no longer automatically performs the FCC unlock procedure by default. See [the docs](https://modemmanager.org/docs/modemmanager/fcc-unlock/) for more details. diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md index 827e2a579c2e..044d7686ae5c 100644 --- a/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2311.section.md @@ -91,6 +91,8 @@ - `getent` has been moved from `glibc`'s `bin` output to its own dedicated output, reducing closure size for many dependents. Dependents using the `getent` alias should not be affected; others should move from using `glibc.bin` or `getBin glibc` to `getent` (which also improves compatibility with non-glibc platforms). +- The `users.users.<name>.passwordFile` has been renamed to `users.users.<name>.hashedPasswordFile` to avoid possible confusions. The option is in fact the file-based version of `hashedPassword`, not `password`, and expects a file containing the {manpage}`crypt(3)` hash of the user password. + - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`. - JACK tools (`jack_*` except `jack_control`) have moved from the `jack2` package to `jack-example-tools` @@ -185,12 +187,18 @@ - Emacs macport version 29 was introduced. +- The option `services.networking.networkmanager.enableFccUnlock` was removed in favor of `networking.networkmanager.fccUnlockScripts`, which allows specifying unlock scripts explicitly. The previous option simply did enable all unlock scripts bundled with ModemManager, which is risky, and didn't allow using vendor-provided unlock scripts at all. + - The `html-proofer` package has been updated from major version 3 to major version 5, which includes [breaking changes](https://github.com/gjtorikian/html-proofer/blob/v5.0.8/UPGRADING.md). - `kratos` has been updated from 0.10.1 to the first stable version 1.0.0, please read the [0.10.1 to 0.11.0](https://github.com/ory/kratos/releases/tag/v0.11.0), [0.11.0 to 0.11.1](https://github.com/ory/kratos/releases/tag/v0.11.1), [0.11.1 to 0.13.0](https://github.com/ory/kratos/releases/tag/v0.13.0) and [0.13.0 to 1.0.0](https://github.com/ory/kratos/releases/tag/v1.0.0) upgrade guides. The most notable breaking change is the introduction of one-time passwords (`code`) and update of the default recovery strategy from `link` to `code`. - The `hail` NixOS module was removed, as `hail` was unmaintained since 2017. +- Package `noto-fonts-emoji` was renamed to `noto-fonts-color-emoji`; + see [#221181](https://github.com/NixOS/nixpkgs/issues/221181). + + ## Other Notable Changes {#sec-release-23.11-notable-changes} - The Cinnamon module now enables XDG desktop integration by default. If you are experiencing collisions related to xdg-desktop-portal-gtk you can safely remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your NixOS configuration. @@ -247,6 +255,8 @@ The module update takes care of the new config syntax and the data itself (user - `programs.gnupg.agent.pinentryFlavor` is now set in `/etc/gnupg/gpg-agent.conf`, and will no longer take precedence over a `pinentry-program` set in `~/.gnupg/gpg-agent.conf`. +- `dockerTools.buildImage`, `dockerTools.buildLayeredImage` and `dockerTools.streamLayeredImage` now use `lib.makeOverridable` to allow `dockerTools`-based images to be customized more efficiently at the nix-level. + - `services.influxdb2` now supports doing an automatic initial setup and provisioning of users, organizations, buckets and authentication tokens, see [#249502](https://github.com/NixOS/nixpkgs/pull/249502) for more details. - `wrapHelm` now exposes `passthru.pluginsDir` which can be passed to `helmfile`. For convenience, a top-level package `helmfile-wrapped` has been added, which inherits `passthru.pluginsDir` from `kubernetes-helm-wrapped`. See [#217768](https://github.com/NixOS/nixpkgs/issues/217768) for details. @@ -263,6 +273,8 @@ The module update takes care of the new config syntax and the data itself (user - The `cawbird` package is dropped from nixpkgs, as it got broken by the Twitter API closing down and has been abandoned upstream. +- `hardware.nvidia` gained `datacenter` options for enabling NVIDIA Data Center drivers and configuration of NVLink/NVSwitch topologies through `nv-fabricmanager`. + - Certificate generation via the `security.acme` now limits the concurrent number of running certificate renewals and generation jobs, to avoid spiking resource usage when processing many certificates at once. The limit defaults to *5* and can be adjusted via `maxConcurrentRenewals`. Setting it to *0* disables the limits altogether. - New `boot.bcache.enable` (default enabled) allows completely removing `bcache` mount support. diff --git a/nixpkgs/nixos/modules/config/fonts/packages.nix b/nixpkgs/nixos/modules/config/fonts/packages.nix index 46907d5411ca..37b705ecb345 100644 --- a/nixpkgs/nixos/modules/config/fonts/packages.nix +++ b/nixpkgs/nixos/modules/config/fonts/packages.nix @@ -37,7 +37,7 @@ in gyre-fonts # TrueType substitutes for standard PostScript fonts liberation_ttf unifont - noto-fonts-emoji + noto-fonts-color-emoji ]); }; } diff --git a/nixpkgs/nixos/modules/config/terminfo.nix b/nixpkgs/nixos/modules/config/terminfo.nix index 82f9ae48372a..1ae8e82c471e 100644 --- a/nixpkgs/nixos/modules/config/terminfo.nix +++ b/nixpkgs/nixos/modules/config/terminfo.nix @@ -16,16 +16,24 @@ with lib; config = { - # can be generated with: filter (drv: (builtins.tryEval (drv ? terminfo)).value) (attrValues pkgs) + # can be generated with: + # attrNames (filterAttrs + # (_: drv: (builtins.tryEval (isDerivation drv && drv ? terminfo)).value) + # pkgs) environment.systemPackages = mkIf config.environment.enableAllTerminfo (map (x: x.terminfo) (with pkgs; [ alacritty + contour foot kitty mtm + rio rxvt-unicode-unwrapped rxvt-unicode-unwrapped-emoji + st termite + tmux wezterm + yaft ])); environment.pathsToLink = [ diff --git a/nixpkgs/nixos/modules/config/update-users-groups.pl b/nixpkgs/nixos/modules/config/update-users-groups.pl index 4312197a3735..7aee58e697de 100644 --- a/nixpkgs/nixos/modules/config/update-users-groups.pl +++ b/nixpkgs/nixos/modules/config/update-users-groups.pl @@ -241,12 +241,12 @@ foreach my $u (@{$spec->{users}}) { chmod oct($u->{homeMode}), $u->{home}; } - if (defined $u->{passwordFile}) { - if (-e $u->{passwordFile}) { - $u->{hashedPassword} = read_file($u->{passwordFile}); + if (defined $u->{hashedPasswordFile}) { + if (-e $u->{hashedPasswordFile}) { + $u->{hashedPassword} = read_file($u->{hashedPasswordFile}); chomp $u->{hashedPassword}; } else { - warn "warning: password file ‘$u->{passwordFile}’ does not exist\n"; + warn "warning: password file ‘$u->{hashedPasswordFile}’ does not exist\n"; } } elsif (defined $u->{password}) { $u->{hashedPassword} = hashPassword($u->{password}); diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix index 684b4bc8fbcc..5158974c27b3 100644 --- a/nixpkgs/nixos/modules/config/users-groups.nix +++ b/nixpkgs/nixos/modules/config/users-groups.nix @@ -18,11 +18,11 @@ let passwordDescription = '' The options {option}`hashedPassword`, - {option}`password` and {option}`passwordFile` + {option}`password` and {option}`hashedPasswordFile` controls what password is set for the user. {option}`hashedPassword` overrides both - {option}`password` and {option}`passwordFile`. - {option}`password` overrides {option}`passwordFile`. + {option}`password` and {option}`hashedPasswordFile`. + {option}`password` overrides {option}`hashedPasswordFile`. If none of these three options are set, no password is assigned to the user, and the user will not be able to do password logins. If the option {option}`users.mutableUsers` is true, the @@ -250,18 +250,26 @@ let ''; }; - passwordFile = mkOption { + hashedPasswordFile = mkOption { type = with types; nullOr str; - default = null; + default = cfg.users.${name}.passwordFile; + defaultText = literalExpression "null"; description = lib.mdDoc '' - The full path to a file that contains the user's password. The password - file is read on each system activation. The file should contain - exactly one line, which should be the password in an encrypted form - that is suitable for the `chpasswd -e` command. + The full path to a file that contains the hash of the user's + password. The password file is read on each system activation. The + file should contain exactly one line, which should be the password in + an encrypted form that is suitable for the `chpasswd -e` command. ${passwordDescription} ''; }; + passwordFile = mkOption { + type = with types; nullOr str; + default = null; + visible = false; + description = lib.mdDoc "Deprecated alias of hashedPasswordFile"; + }; + initialHashedPassword = mkOption { type = with types; nullOr (passwdEntry str); default = null; @@ -447,7 +455,7 @@ let users = mapAttrsToList (_: u: { inherit (u) name uid group description home homeMode createHome isSystemUser - password passwordFile hashedPassword + password hashedPasswordFile hashedPassword autoSubUidGidRange subUidRanges subGidRanges initialPassword initialHashedPassword expires; shell = utils.toShellPath u.shell; @@ -756,7 +764,7 @@ in { && (allowsLogin cfg.hashedPassword || cfg.password != null - || cfg.passwordFile != null + || cfg.hashedPasswordFile != null || cfg.openssh.authorizedKeys.keys != [] || cfg.openssh.authorizedKeys.keyFiles != []) ) cfg.users ++ [ @@ -845,9 +853,13 @@ in { The password hash of user "${user.name}" may be invalid. You must set a valid hash or the user will be locked out of their account. Please check the value of option `users.users."${user.name}".hashedPassword`.'' - else null - )); - + else null) + ++ flip mapAttrsToList cfg.users (name: user: + if user.passwordFile != null then + ''The option `users.users."${name}".passwordFile' has been renamed '' + + ''to `users.users."${name}".hashedPasswordFile'.'' + else null) + ); }; } diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix index 67c3afcf320a..0b1238dd888a 100644 --- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix +++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix @@ -4,8 +4,10 @@ pkgs, ... }: let + x11Enabled = config.services.xserver.enable + && (lib.elem "nvidia" config.services.xserver.videoDrivers); nvidia_x11 = - if (lib.elem "nvidia" config.services.xserver.videoDrivers) + if x11Enabled || cfg.datacenter.enable then cfg.package else null; @@ -18,9 +20,64 @@ primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable; busIDType = lib.types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?"; ibtSupport = cfg.open || (nvidia_x11.ibtSupport or false); + settingsFormat = pkgs.formats.keyValue {}; in { options = { hardware.nvidia = { + datacenter.enable = lib.mkEnableOption (lib.mdDoc '' + Data Center drivers for NVIDIA cards on a NVLink topology. + ''); + datacenter.settings = lib.mkOption { + type = settingsFormat.type; + default = { + LOG_LEVEL=4; + LOG_FILE_NAME="/var/log/fabricmanager.log"; + LOG_APPEND_TO_LOG=1; + LOG_FILE_MAX_SIZE=1024; + LOG_USE_SYSLOG=0; + DAEMONIZE=1; + BIND_INTERFACE_IP="127.0.0.1"; + STARTING_TCP_PORT=16000; + FABRIC_MODE=0; + FABRIC_MODE_RESTART=0; + STATE_FILE_NAME="/var/tmp/fabricmanager.state"; + FM_CMD_BIND_INTERFACE="127.0.0.1"; + FM_CMD_PORT_NUMBER=6666; + FM_STAY_RESIDENT_ON_FAILURES=0; + ACCESS_LINK_FAILURE_MODE=0; + TRUNK_LINK_FAILURE_MODE=0; + NVSWITCH_FAILURE_MODE=0; + ABORT_CUDA_JOBS_ON_FM_EXIT=1; + TOPOLOGY_FILE_PATH=nvidia_x11.fabricmanager + "/share/nvidia-fabricmanager/nvidia/nvswitch"; + }; + defaultText = lib.literalExpression '' + { + LOG_LEVEL=4; + LOG_FILE_NAME="/var/log/fabricmanager.log"; + LOG_APPEND_TO_LOG=1; + LOG_FILE_MAX_SIZE=1024; + LOG_USE_SYSLOG=0; + DAEMONIZE=1; + BIND_INTERFACE_IP="127.0.0.1"; + STARTING_TCP_PORT=16000; + FABRIC_MODE=0; + FABRIC_MODE_RESTART=0; + STATE_FILE_NAME="/var/tmp/fabricmanager.state"; + FM_CMD_BIND_INTERFACE="127.0.0.1"; + FM_CMD_PORT_NUMBER=6666; + FM_STAY_RESIDENT_ON_FAILURES=0; + ACCESS_LINK_FAILURE_MODE=0; + TRUNK_LINK_FAILURE_MODE=0; + NVSWITCH_FAILURE_MODE=0; + ABORT_CUDA_JOBS_ON_FM_EXIT=1; + TOPOLOGY_FILE_PATH=nvidia_x11.fabricmanager + "/share/nvidia-fabricmanager/nvidia/nvswitch"; + } + ''; + description = lib.mdDoc '' + Additional configuration options for fabricmanager. + ''; + }; + powerManagement.enable = lib.mkEnableOption (lib.mdDoc '' experimental power management through systemd. For more information, see the NVIDIA docs, on Chapter 21. Configuring Power Management Support. @@ -167,9 +224,15 @@ in { It also drastically increases the time the driver needs to clock down after load. ''); - package = lib.mkPackageOptionMD config.boot.kernelPackages.nvidiaPackages "nvidia_x11" { - default = "stable"; + package = lib.mkOption { + default = config.boot.kernelPackages.nvidiaPackages."${if cfg.datacenter.enable then "dc" else "stable"}"; + defaultText = lib.literalExpression '' + config.boot.kernelPackages.nvidiaPackages."\$\{if cfg.datacenter.enable then "dc" else "stable"}" + ''; example = lib.mdDoc "config.boot.kernelPackages.nvidiaPackages.legacy_470"; + description = lib.mdDoc '' + The NVIDIA driver package to use. + ''; }; open = lib.mkEnableOption (lib.mdDoc '' @@ -188,8 +251,46 @@ in { then pCfg.intelBusId else pCfg.amdgpuBusId; in - lib.mkIf (nvidia_x11 != null) { - assertions = [ + lib.mkIf (nvidia_x11 != null) (lib.mkMerge [ + # Common + ({ + assertions = [ + { + assertion = !(x11Enabled && cfg.datacenter.enable); + message = "You cannot configure both X11 and Data Center drivers at the same time."; + } + ]; + boot = { + blacklistedKernelModules = ["nouveau" "nvidiafb"]; + kernelModules = [ "nvidia-uvm" ]; + }; + systemd.tmpfiles.rules = + lib.optional config.virtualisation.docker.enableNvidia + "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"; + services.udev.extraRules = + '' + # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. + KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'" + KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \ -f 4); do mknod -m 666 /dev/nvidia$${i} c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) $${i}; done'" + KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'" + KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" + KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" + ''; + hardware.opengl = { + extraPackages = [ + nvidia_x11.out + ]; + extraPackages32 = [ + nvidia_x11.lib32 + ]; + }; + environment.systemPackages = [ + nvidia_x11.bin + ]; + }) + # X11 + (lib.mkIf x11Enabled { + assertions = [ { assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == ""; message = "You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor."; @@ -248,227 +349,207 @@ in { { assertion = cfg.dynamicBoost.enable -> lib.versionAtLeast nvidia_x11.version "510.39.01"; message = "NVIDIA's Dynamic Boost feature only exists on versions >= 510.39.01"; - } - ]; - - # If Optimus/PRIME is enabled, we: - # - Specify the configured NVIDIA GPU bus ID in the Device section for the - # "nvidia" driver. - # - Add the AllowEmptyInitialConfiguration option to the Screen section for the - # "nvidia" driver, in order to allow the X server to start without any outputs. - # - Add a separate Device section for the Intel GPU, using the "modesetting" - # driver and with the configured BusID. - # - OR add a separate Device section for the AMD APU, using the "amdgpu" - # driver and with the configures BusID. - # - Reference that Device section from the ServerLayout section as an inactive - # device. - # - Configure the display manager to run specific `xrandr` commands which will - # configure/enable displays connected to the Intel iGPU / AMD APU. - - # reverse sync implies offloading - hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable; - - services.xserver.drivers = - lib.optional primeEnabled { - name = igpuDriver; - display = offloadCfg.enable; - modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu; - deviceSection = - '' - BusID "${igpuBusId}" - '' - + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") '' - Option "AccelMethod" "none" - ''; - } - ++ lib.singleton { - name = "nvidia"; - modules = [nvidia_x11.bin]; - display = !offloadCfg.enable; - deviceSection = - lib.optionalString primeEnabled - '' - BusID "${pCfg.nvidiaBusId}" - '' - + lib.optionalString pCfg.allowExternalGpu '' - Option "AllowExternalGpus" - ''; - screenSection = - '' - Option "RandRRotation" "on" - '' - + lib.optionalString syncCfg.enable '' - Option "AllowEmptyInitialConfiguration" - '' - + lib.optionalString cfg.forceFullCompositionPipeline '' - Option "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}" - Option "AllowIndirectGLXProtocol" "off" - Option "TripleBuffer" "on" - ''; - }; - - services.xserver.serverLayoutSection = - lib.optionalString syncCfg.enable '' - Inactive "Device-${igpuDriver}[0]" - '' - + lib.optionalString reverseSyncCfg.enable '' - Inactive "Device-nvidia[0]" - '' - + lib.optionalString offloadCfg.enable '' - Option "AllowNVIDIAGPUScreens" - ''; - - services.xserver.displayManager.setupCommands = let - gpuProviderName = - if igpuDriver == "amdgpu" - then - # find the name of the provider if amdgpu - "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`" - else igpuDriver; - providerCmdParams = - if syncCfg.enable - then "\"${gpuProviderName}\" NVIDIA-0" - else "NVIDIA-G0 \"${gpuProviderName}\""; - in - lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) '' - # Added by nvidia configuration module for Optimus/PRIME. - ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams} - ${lib.getExe pkgs.xorg.xrandr} --auto - ''; - - environment.etc = { - "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";}; + }]; + + # If Optimus/PRIME is enabled, we: + # - Specify the configured NVIDIA GPU bus ID in the Device section for the + # "nvidia" driver. + # - Add the AllowEmptyInitialConfiguration option to the Screen section for the + # "nvidia" driver, in order to allow the X server to start without any outputs. + # - Add a separate Device section for the Intel GPU, using the "modesetting" + # driver and with the configured BusID. + # - OR add a separate Device section for the AMD APU, using the "amdgpu" + # driver and with the configures BusID. + # - Reference that Device section from the ServerLayout section as an inactive + # device. + # - Configure the display manager to run specific `xrandr` commands which will + # configure/enable displays connected to the Intel iGPU / AMD APU. + + # reverse sync implies offloading + hardware.nvidia.prime.offload.enable = lib.mkDefault reverseSyncCfg.enable; + + services.xserver.drivers = + lib.optional primeEnabled { + name = igpuDriver; + display = offloadCfg.enable; + modules = lib.optional (igpuDriver == "amdgpu") pkgs.xorg.xf86videoamdgpu; + deviceSection = + '' + BusID "${igpuBusId}" + '' + + lib.optionalString (syncCfg.enable && igpuDriver != "amdgpu") '' + Option "AccelMethod" "none" + ''; + } + ++ lib.singleton { + name = "nvidia"; + modules = [nvidia_x11.bin]; + display = !offloadCfg.enable; + deviceSection = + lib.optionalString primeEnabled + '' + BusID "${pCfg.nvidiaBusId}" + '' + + lib.optionalString pCfg.allowExternalGpu '' + Option "AllowExternalGpus" + ''; + screenSection = + '' + Option "RandRRotation" "on" + '' + + lib.optionalString syncCfg.enable '' + Option "AllowEmptyInitialConfiguration" + '' + + lib.optionalString cfg.forceFullCompositionPipeline '' + Option "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}" + Option "AllowIndirectGLXProtocol" "off" + Option "TripleBuffer" "on" + ''; + }; - # 'nvidia_x11' installs it's files to /run/opengl-driver/... - "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/"; - }; + services.xserver.serverLayoutSection = + lib.optionalString syncCfg.enable '' + Inactive "Device-${igpuDriver}[0]" + '' + + lib.optionalString reverseSyncCfg.enable '' + Inactive "Device-nvidia[0]" + '' + + lib.optionalString offloadCfg.enable '' + Option "AllowNVIDIAGPUScreens" + ''; + + services.xserver.displayManager.setupCommands = let + gpuProviderName = + if igpuDriver == "amdgpu" + then + # find the name of the provider if amdgpu + "`${lib.getExe pkgs.xorg.xrandr} --listproviders | ${lib.getExe pkgs.gnugrep} -i AMD | ${lib.getExe pkgs.gnused} -n 's/^.*name://p'`" + else igpuDriver; + providerCmdParams = + if syncCfg.enable + then "\"${gpuProviderName}\" NVIDIA-0" + else "NVIDIA-G0 \"${gpuProviderName}\""; + in + lib.optionalString (syncCfg.enable || reverseSyncCfg.enable) '' + # Added by nvidia configuration module for Optimus/PRIME. + ${lib.getExe pkgs.xorg.xrandr} --setprovideroutputsource ${providerCmdParams} + ${lib.getExe pkgs.xorg.xrandr} --auto + ''; + + environment.etc = { + "nvidia/nvidia-application-profiles-rc" = lib.mkIf nvidia_x11.useProfiles {source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";}; + + # 'nvidia_x11' installs it's files to /run/opengl-driver/... + "egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/"; + }; - hardware.opengl = { - extraPackages = [ - nvidia_x11.out - pkgs.nvidia-vaapi-driver - ]; - extraPackages32 = [ - nvidia_x11.lib32 - pkgs.pkgsi686Linux.nvidia-vaapi-driver - ]; - }; - environment.systemPackages = - [nvidia_x11.bin] - ++ lib.optional cfg.nvidiaSettings nvidia_x11.settings - ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced - ++ lib.optional offloadCfg.enableOffloadCmd - (pkgs.writeShellScriptBin "nvidia-offload" '' - export __NV_PRIME_RENDER_OFFLOAD=1 - export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 - export __GLX_VENDOR_LIBRARY_NAME=nvidia - export __VK_LAYER_NV_optimus=NVIDIA_only - exec "$@" - ''); - - systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out; - - systemd.services = let - nvidiaService = state: { - description = "NVIDIA system ${state} actions"; - path = [pkgs.kbd]; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'"; - }; - before = ["systemd-${state}.service"]; - requiredBy = ["systemd-${state}.service"]; + hardware.opengl = { + extraPackages = [ + pkgs.nvidia-vaapi-driver + ]; + extraPackages32 = [ + pkgs.pkgsi686Linux.nvidia-vaapi-driver + ]; }; - in - lib.mkMerge [ - (lib.mkIf cfg.powerManagement.enable { - nvidia-suspend = nvidiaService "suspend"; - nvidia-hibernate = nvidiaService "hibernate"; - nvidia-resume = - (nvidiaService "resume") - // { - before = []; - after = ["systemd-suspend.service" "systemd-hibernate.service"]; - requiredBy = ["systemd-suspend.service" "systemd-hibernate.service"]; - }; - }) - (lib.mkIf cfg.nvidiaPersistenced { - "nvidia-persistenced" = { - description = "NVIDIA Persistence Daemon"; - wantedBy = ["multi-user.target"]; - serviceConfig = { - Type = "forking"; - Restart = "always"; - PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid"; - ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose"; - ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced"; - }; + environment.systemPackages = + lib.optional cfg.nvidiaSettings nvidia_x11.settings + ++ lib.optional cfg.nvidiaPersistenced nvidia_x11.persistenced + ++ lib.optional offloadCfg.enableOffloadCmd + (pkgs.writeShellScriptBin "nvidia-offload" '' + export __NV_PRIME_RENDER_OFFLOAD=1 + export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 + export __GLX_VENDOR_LIBRARY_NAME=nvidia + export __VK_LAYER_NV_optimus=NVIDIA_only + exec "$@" + ''); + + systemd.packages = lib.optional cfg.powerManagement.enable nvidia_x11.out; + + systemd.services = let + nvidiaService = state: { + description = "NVIDIA system ${state} actions"; + path = [pkgs.kbd]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'"; }; - }) - (lib.mkIf cfg.dynamicBoost.enable { - "nvidia-powerd" = { - description = "nvidia-powerd service"; - path = [ - pkgs.util-linux # nvidia-powerd wants lscpu - ]; - wantedBy = ["multi-user.target"]; - serviceConfig = { - Type = "dbus"; - BusName = "nvidia.powerd.server"; - ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd"; + before = ["systemd-${state}.service"]; + requiredBy = ["systemd-${state}.service"]; + }; + in + lib.mkMerge [ + (lib.mkIf cfg.powerManagement.enable { + nvidia-suspend = nvidiaService "suspend"; + nvidia-hibernate = nvidiaService "hibernate"; + nvidia-resume = + (nvidiaService "resume") + // { + before = []; + after = ["systemd-suspend.service" "systemd-hibernate.service"]; + requiredBy = ["systemd-suspend.service" "systemd-hibernate.service"]; + }; + }) + (lib.mkIf cfg.nvidiaPersistenced { + "nvidia-persistenced" = { + description = "NVIDIA Persistence Daemon"; + wantedBy = ["multi-user.target"]; + serviceConfig = { + Type = "forking"; + Restart = "always"; + PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid"; + ExecStart = "${lib.getExe nvidia_x11.persistenced} --verbose"; + ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced"; + }; }; - }; - }) - ]; - - services.acpid.enable = true; - - services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin; - - hardware.firmware = lib.optional cfg.open nvidia_x11.firmware; - - systemd.tmpfiles.rules = - lib.optional config.virtualisation.docker.enableNvidia - "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin" - ++ lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia) - "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced"; - - boot = { - blacklistedKernelModules = ["nouveau" "nvidiafb"]; - - extraModulePackages = - if cfg.open - then [nvidia_x11.open] - else [nvidia_x11.bin]; - - # nvidia-uvm is required by CUDA applications. - kernelModules = - ["nvidia-uvm"] - ++ lib.optionals config.services.xserver.enable ["nvidia" "nvidia_modeset" "nvidia_drm"]; - - # If requested enable modesetting via kernel parameter. - kernelParams = - lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1" - ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1" - ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1" - ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off"; - - # enable finegrained power management - extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained '' - options nvidia "NVreg_DynamicPowerManagement=0x02" - ''; - }; - - services.udev.extraRules = - '' - # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. - KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'" - KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'for i in $$(cat /proc/driver/nvidia/gpus/*/information | grep Minor | cut -d \ -f 4); do mknod -m 666 /dev/nvidia$${i} c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) $${i}; done'" - KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'" - KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" - KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" - '' - + lib.optionalString cfg.powerManagement.finegrained ( + }) + (lib.mkIf cfg.dynamicBoost.enable { + "nvidia-powerd" = { + description = "nvidia-powerd service"; + path = [ + pkgs.util-linux # nvidia-powerd wants lscpu + ]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + Type = "dbus"; + BusName = "nvidia.powerd.server"; + ExecStart = "${nvidia_x11.bin}/bin/nvidia-powerd"; + }; + }; + }) + ]; + services.acpid.enable = true; + + services.dbus.packages = lib.optional cfg.dynamicBoost.enable nvidia_x11.bin; + + hardware.firmware = lib.optional cfg.open nvidia_x11.firmware; + + systemd.tmpfiles.rules = + lib.optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia) + "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced"; + + boot = { + extraModulePackages = + if cfg.open + then [nvidia_x11.open] + else [nvidia_x11.bin]; + # nvidia-uvm is required by CUDA applications. + kernelModules = + lib.optionals config.services.xserver.enable ["nvidia" "nvidia_modeset" "nvidia_drm"]; + + # If requested enable modesetting via kernel parameter. + kernelParams = + lib.optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1" + ++ lib.optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1" + ++ lib.optional cfg.open "nvidia.NVreg_OpenRmEnableUnsupportedGpus=1" + ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2" && !ibtSupport) "ibt=off"; + + # enable finegrained power management + extraModprobeConfig = lib.optionalString cfg.powerManagement.finegrained '' + options nvidia "NVreg_DynamicPowerManagement=0x02" + ''; + }; + services.udev.extraRules = + lib.optionalString cfg.powerManagement.finegrained ( lib.optionalString (lib.versionOlder config.boot.kernelPackages.kernel.version "5.5") '' # Remove NVIDIA USB xHCI Host Controller devices, if present ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1" @@ -489,5 +570,30 @@ in { ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on" '' ); - }; + }) + # Data Center + (lib.mkIf (cfg.datacenter.enable) { + boot.extraModulePackages = [ + nvidia_x11.bin + ]; + systemd.services.nvidia-fabricmanager = { + enable = true; + description = "Start NVIDIA NVLink Management"; + wantedBy = [ "multi-user.target" ]; + unitConfig.After = [ "network-online.target" ]; + unitConfig.Requires = [ "network-online.target" ]; + serviceConfig = { + Type = "forking"; + TimeoutStartSec = 240; + ExecStart = let + nv-fab-conf = settingsFormat.generate "fabricmanager.conf" cfg.datacenter.settings; + in + nvidia_x11.fabricmanager + "/bin/nv-fabricmanager -c " + nv-fab-conf; + LimitCORE="infinity"; + }; + }; + environment.systemPackages = + lib.optional cfg.datacenter.enable nvidia_x11.fabricmanager; + }) + ]); } diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix index c0abfaa08817..05b0415d8558 100644 --- a/nixpkgs/nixos/modules/module-list.nix +++ b/nixpkgs/nixos/modules/module-list.nix @@ -279,6 +279,7 @@ ./programs/xss-lock.nix ./programs/xwayland.nix ./programs/yabar.nix + ./programs/yazi.nix ./programs/zmap.nix ./programs/zsh/oh-my-zsh.nix ./programs/zsh/zsh-autoenv.nix @@ -647,6 +648,7 @@ ./services/misc/etesync-dav.nix ./services/misc/evdevremapkeys.nix ./services/misc/felix.nix + ./services/misc/forgejo.nix ./services/misc/freeswitch.nix ./services/misc/fstrim.nix ./services/misc/gammu-smsd.nix @@ -1251,6 +1253,7 @@ ./services/web-apps/matomo.nix ./services/web-apps/mattermost.nix ./services/web-apps/mediawiki.nix + ./services/web-apps/meme-bingo-web.nix ./services/web-apps/miniflux.nix ./services/web-apps/monica.nix ./services/web-apps/moodle.nix diff --git a/nixpkgs/nixos/modules/programs/bash/bash.nix b/nixpkgs/nixos/modules/programs/bash/bash.nix index 286faeadc489..7d3322ea5e50 100644 --- a/nixpkgs/nixos/modules/programs/bash/bash.nix +++ b/nixpkgs/nixos/modules/programs/bash/bash.nix @@ -81,7 +81,7 @@ in if [ "$TERM" != "dumb" ] || [ -n "$INSIDE_EMACS" ]; then PROMPT_COLOR="1;31m" ((UID)) && PROMPT_COLOR="1;32m" - if [ -n "$INSIDE_EMACS" ] || [ "$TERM" = "eterm" ] || [ "$TERM" = "eterm-color" ]; then + if [ -n "$INSIDE_EMACS" ]; then # Emacs term mode doesn't support xterm title escape sequence (\e]0;) PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] " else diff --git a/nixpkgs/nixos/modules/programs/clash-verge.nix b/nixpkgs/nixos/modules/programs/clash-verge.nix index 29977be3858f..57a1c0377edb 100644 --- a/nixpkgs/nixos/modules/programs/clash-verge.nix +++ b/nixpkgs/nixos/modules/programs/clash-verge.nix @@ -2,17 +2,9 @@ { options.programs.clash-verge = { - enable = lib.mkEnableOption (lib.mdDoc '' - Clash Verge. - ''); - - autoStart = lib.mkEnableOption (lib.mdDoc '' - Clash Verge Auto Launch. - ''); - - tunMode = lib.mkEnableOption (lib.mdDoc '' - Clash Verge Tun Mode. - ''); + enable = lib.mkEnableOption (lib.mdDoc "Clash Verge"); + autoStart = lib.mkEnableOption (lib.mdDoc "Clash Verge auto launch"); + tunMode = lib.mkEnableOption (lib.mdDoc "Clash Verge TUN mode"); }; config = diff --git a/nixpkgs/nixos/modules/programs/direnv.nix b/nixpkgs/nixos/modules/programs/direnv.nix index 53717fae11a0..1a80cb202806 100644 --- a/nixpkgs/nixos/modules/programs/direnv.nix +++ b/nixpkgs/nixos/modules/programs/direnv.nix @@ -32,15 +32,6 @@ in { the hiding of direnv logging ''); - persistDerivations = - (lib.mkEnableOption (lib.mdDoc '' - setting keep-derivations and keep-outputs to true - to prevent shells from getting garbage collected - '')) - // { - default = true; - }; - loadInNixShell = lib.mkEnableOption (lib.mdDoc '' loading direnv in `nix-shell` `nix shell` or `nix develop` @@ -62,6 +53,10 @@ in { }; }; + imports = [ + (lib.mkRemovedOptionModule ["programs" "direnv" "persistDerivations"] "persistDerivations was removed as it is on longer necessary") + ]; + config = lib.mkIf cfg.enable { programs = { @@ -87,11 +82,6 @@ in { ''; }; - nix.settings = lib.mkIf cfg.persistDerivations { - keep-outputs = true; - keep-derivations = true; - }; - environment = { systemPackages = if cfg.loadInNixShell then [cfg.package] diff --git a/nixpkgs/nixos/modules/programs/yazi.nix b/nixpkgs/nixos/modules/programs/yazi.nix index 3416bca06679..973f5c0122c2 100644 --- a/nixpkgs/nixos/modules/programs/yazi.nix +++ b/nixpkgs/nixos/modules/programs/yazi.nix @@ -45,5 +45,9 @@ in names); }; }; - meta.maintainers = with lib.maintainers; [ linsui ]; + meta = { + maintainers = with lib.maintainers; [ linsui ]; + # The version of the package is used in the doc. + buildDocsInSandbox = false; + }; } diff --git a/nixpkgs/nixos/modules/security/acme/default.md b/nixpkgs/nixos/modules/security/acme/default.md index 8ff97b55f685..31548ad181a7 100644 --- a/nixpkgs/nixos/modules/security/acme/default.md +++ b/nixpkgs/nixos/modules/security/acme/default.md @@ -189,7 +189,7 @@ security.acme.defaults.email = "admin+acme@example.com"; security.acme.certs."example.com" = { domain = "*.example.com"; dnsProvider = "rfc2136"; - credentialsFile = "/var/lib/secrets/certs.secret"; + environmentFile = "/var/lib/secrets/certs.secret"; # We don't need to wait for propagation since this is a local DNS server dnsPropagationCheck = false; }; @@ -256,7 +256,7 @@ security.acme.acceptTerms = true; security.acme.defaults.email = "admin+acme@example.com"; security.acme.defaults = { dnsProvider = "rfc2136"; - credentialsFile = "/var/lib/secrets/certs.secret"; + environmentFile = "/var/lib/secrets/certs.secret"; # We don't need to wait for propagation since this is a local DNS server dnsPropagationCheck = false; }; diff --git a/nixpkgs/nixos/modules/security/acme/default.nix b/nixpkgs/nixos/modules/security/acme/default.nix index 222a25cf11dc..92bed172f452 100644 --- a/nixpkgs/nixos/modules/security/acme/default.nix +++ b/nixpkgs/nixos/modules/security/acme/default.nix @@ -362,8 +362,14 @@ let "/var/lib/acme/.lego/${cert}/${certDir}:/tmp/certificates" ]; - # Only try loading the credentialsFile if the dns challenge is enabled - EnvironmentFile = mkIf useDns data.credentialsFile; + # Only try loading the environmentFile if the dns challenge is enabled + EnvironmentFile = mkIf useDns data.environmentFile; + + Environment = mkIf useDns + (mapAttrsToList (k: v: ''"${k}=%d/${k}"'') data.credentialFiles); + + LoadCredential = mkIf useDns + (mapAttrsToList (k: v: "${k}:${v}") data.credentialFiles); # Run as root (Prefixed with +) ExecStartPost = "+" + (pkgs.writeShellScript "acme-postrun" '' @@ -496,6 +502,10 @@ let defaultText = if isDefaults then default else literalExpression "config.security.acme.defaults.${name}"; }; in { + imports = [ + (mkRenamedOptionModule [ "credentialsFile" ] [ "environmentFile" ]) + ]; + options = { validMinDays = mkOption { type = types.int; @@ -607,9 +617,9 @@ let ''; }; - credentialsFile = mkOption { + environmentFile = mkOption { type = types.nullOr types.path; - inherit (defaultAndText "credentialsFile" null) default defaultText; + inherit (defaultAndText "environmentFile" null) default defaultText; description = lib.mdDoc '' Path to an EnvironmentFile for the cert's service containing any required and optional environment variables for your selected dnsProvider. @@ -619,6 +629,24 @@ let example = "/var/src/secrets/example.org-route53-api-token"; }; + credentialFiles = mkOption { + type = types.attrsOf (types.path); + inherit (defaultAndText "credentialFiles" {}) default defaultText; + description = lib.mdDoc '' + Environment variables suffixed by "_FILE" to set for the cert's service + for your selected dnsProvider. + To find out what values you need to set, consult the documentation at + <https://go-acme.github.io/lego/dns/> for the corresponding dnsProvider. + This allows to securely pass credential files to lego by leveraging systemd + credentials. + ''; + example = literalExpression '' + { + "RFC2136_TSIG_SECRET_FILE" = "/run/secrets/tsig-secret-example.org"; + } + ''; + }; + dnsPropagationCheck = mkOption { type = types.bool; inherit (defaultAndText "dnsPropagationCheck" true) default defaultText; @@ -929,6 +957,13 @@ in { `security.acme.certs.${cert}.listenHTTP` must be provided. ''; } + { + assertion = all (hasSuffix "_FILE") (attrNames data.credentialFiles); + message = '' + Option `security.acme.certs.${cert}.credentialFiles` can only be + used for variables suffixed by "_FILE". + ''; + } ]) cfg.certs)); users.users.acme = { diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix index a431817fe1bb..d83259ccbebc 100644 --- a/nixpkgs/nixos/modules/security/pam.nix +++ b/nixpkgs/nixos/modules/security/pam.nix @@ -1303,7 +1303,7 @@ in security.pam.enableEcryptfs = mkEnableOption (lib.mdDoc "eCryptfs PAM module (mounting ecryptfs home directory on login)"); security.pam.enableFscrypt = mkEnableOption (lib.mdDoc '' - Enables fscrypt to automatically unlock directories with the user's login password. + fscrypt to automatically unlock directories with the user's login password. This also enables a service at security.pam.services.fscrypt which is used by fscrypt to verify the user's password when setting up a new protector. If you diff --git a/nixpkgs/nixos/modules/services/audio/tts.nix b/nixpkgs/nixos/modules/services/audio/tts.nix index 1a355c8ee39f..0d93224ec030 100644 --- a/nixpkgs/nixos/modules/services/audio/tts.nix +++ b/nixpkgs/nixos/modules/services/audio/tts.nix @@ -134,6 +134,7 @@ in ProtectProc = "invisible"; ProcSubset = "pid"; RestrictAddressFamilies = [ + "AF_UNIX" "AF_INET" "AF_INET6" ]; diff --git a/nixpkgs/nixos/modules/services/misc/forgejo.nix b/nixpkgs/nixos/modules/services/misc/forgejo.nix new file mode 100644 index 000000000000..f26658b7bcb4 --- /dev/null +++ b/nixpkgs/nixos/modules/services/misc/forgejo.nix @@ -0,0 +1,668 @@ +{ config, lib, options, pkgs, ... }: + +let + cfg = config.services.forgejo; + opt = options.services.forgejo; + format = pkgs.formats.ini { }; + + exe = lib.getExe cfg.package; + + pg = config.services.postgresql; + useMysql = cfg.database.type == "mysql"; + usePostgresql = cfg.database.type == "postgres"; + useSqlite = cfg.database.type == "sqlite3"; + + inherit (lib) + literalExpression + mdDoc + mkChangedOptionModule + mkDefault + mkEnableOption + mkIf + mkMerge + mkOption + mkPackageOptionMD + mkRemovedOptionModule + mkRenamedOptionModule + optionalAttrs + optionals + optionalString + types + ; +in +{ + imports = [ + (mkRenamedOptionModule [ "services" "forgejo" "appName" ] [ "services" "forgejo" "settings" "DEFAULT" "APP_NAME" ]) + (mkRemovedOptionModule [ "services" "forgejo" "extraConfig" ] "services.forgejo.extraConfig has been removed. Please use the freeform services.forgejo.settings option instead") + (mkRemovedOptionModule [ "services" "forgejo" "database" "password" ] "services.forgejo.database.password has been removed. Please use services.forgejo.database.passwordFile instead") + + # copied from services.gitea; remove at some point + (mkRenamedOptionModule [ "services" "forgejo" "cookieSecure" ] [ "services" "forgejo" "settings" "session" "COOKIE_SECURE" ]) + (mkRenamedOptionModule [ "services" "forgejo" "disableRegistration" ] [ "services" "forgejo" "settings" "service" "DISABLE_REGISTRATION" ]) + (mkRenamedOptionModule [ "services" "forgejo" "domain" ] [ "services" "forgejo" "settings" "server" "DOMAIN" ]) + (mkRenamedOptionModule [ "services" "forgejo" "httpAddress" ] [ "services" "forgejo" "settings" "server" "HTTP_ADDR" ]) + (mkRenamedOptionModule [ "services" "forgejo" "httpPort" ] [ "services" "forgejo" "settings" "server" "HTTP_PORT" ]) + (mkRenamedOptionModule [ "services" "forgejo" "log" "level" ] [ "services" "forgejo" "settings" "log" "LEVEL" ]) + (mkRenamedOptionModule [ "services" "forgejo" "log" "rootPath" ] [ "services" "forgejo" "settings" "log" "ROOT_PATH" ]) + (mkRenamedOptionModule [ "services" "forgejo" "rootUrl" ] [ "services" "forgejo" "settings" "server" "ROOT_URL" ]) + (mkRenamedOptionModule [ "services" "forgejo" "ssh" "clonePort" ] [ "services" "forgejo" "settings" "server" "SSH_PORT" ]) + (mkRenamedOptionModule [ "services" "forgejo" "staticRootPath" ] [ "services" "forgejo" "settings" "server" "STATIC_ROOT_PATH" ]) + (mkChangedOptionModule [ "services" "forgejo" "enableUnixSocket" ] [ "services" "forgejo" "settings" "server" "PROTOCOL" ] ( + config: if config.services.forgejo.enableUnixSocket then "http+unix" else "http" + )) + (mkRemovedOptionModule [ "services" "forgejo" "ssh" "enable" ] "services.forgejo.ssh.enable has been migrated into freeform setting services.forgejo.settings.server.DISABLE_SSH. Keep in mind that the setting is inverted") + ]; + + options = { + services.forgejo = { + enable = mkEnableOption (mdDoc "Forgejo"); + + package = mkPackageOptionMD pkgs "forgejo" { }; + + useWizard = mkOption { + default = false; + type = types.bool; + description = mdDoc '' + Whether to use the built-in installation wizard instead of + declaratively managing the {file}`app.ini` config file in nix. + ''; + }; + + stateDir = mkOption { + default = "/var/lib/forgejo"; + type = types.str; + description = mdDoc "Forgejo data directory."; + }; + + customDir = mkOption { + default = "${cfg.stateDir}/custom"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/custom"''; + type = types.str; + description = mdDoc '' + Base directory for custom templates and other options. + + If {option}`${opt.useWizard}` is disabled (default), this directory will also + hold secrets and the resulting {file}`app.ini` config at runtime. + ''; + }; + + user = mkOption { + type = types.str; + default = "forgejo"; + description = mdDoc "User account under which Forgejo runs."; + }; + + group = mkOption { + type = types.str; + default = "forgejo"; + description = mdDoc "Group under which Forgejo runs."; + }; + + database = { + type = mkOption { + type = types.enum [ "sqlite3" "mysql" "postgres" ]; + example = "mysql"; + default = "sqlite3"; + description = mdDoc "Database engine to use."; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = mdDoc "Database host address."; + }; + + port = mkOption { + type = types.port; + default = if !usePostgresql then 3306 else pg.port; + defaultText = literalExpression '' + if config.${opt.database.type} != "postgresql" + then 3306 + else config.${options.services.postgresql.port} + ''; + description = mdDoc "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "forgejo"; + description = mdDoc "Database name."; + }; + + user = mkOption { + type = types.str; + default = "forgejo"; + description = mdDoc "Database user."; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/forgejo-dbpassword"; + description = mdDoc '' + A file containing the password corresponding to + {option}`${opt.database.user}`. + ''; + }; + + socket = mkOption { + type = types.nullOr types.path; + default = if (cfg.database.createDatabase && usePostgresql) then "/run/postgresql" else if (cfg.database.createDatabase && useMysql) then "/run/mysqld/mysqld.sock" else null; + defaultText = literalExpression "null"; + example = "/run/mysqld/mysqld.sock"; + description = mdDoc "Path to the unix socket file to use for authentication."; + }; + + path = mkOption { + type = types.str; + default = "${cfg.stateDir}/data/forgejo.db"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/data/forgejo.db"''; + description = mdDoc "Path to the sqlite3 database file."; + }; + + createDatabase = mkOption { + type = types.bool; + default = true; + description = mdDoc "Whether to create a local database automatically."; + }; + }; + + dump = { + enable = mkEnableOption (mdDoc "periodic dumps via the [built-in {command}`dump` command](https://forgejo.org/docs/latest/admin/command-line/#dump)"); + + interval = mkOption { + type = types.str; + default = "04:31"; + example = "hourly"; + description = mdDoc '' + Run a Forgejo dump at this interval. Runs by default at 04:31 every day. + + The format is described in + {manpage}`systemd.time(7)`. + ''; + }; + + backupDir = mkOption { + type = types.str; + default = "${cfg.stateDir}/dump"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/dump"''; + description = mdDoc "Path to the directory where the dump archives will be stored."; + }; + + type = mkOption { + type = types.enum [ "zip" "tar" "tar.sz" "tar.gz" "tar.xz" "tar.bz2" "tar.br" "tar.lz4" "tar.zst" ]; + default = "zip"; + description = mdDoc "Archive format used to store the dump file."; + }; + + file = mkOption { + type = types.nullOr types.str; + default = null; + description = mdDoc "Filename to be used for the dump. If `null` a default name is chosen by forgejo."; + example = "forgejo-dump"; + }; + }; + + lfs = { + enable = mkOption { + type = types.bool; + default = false; + description = mdDoc "Enables git-lfs support."; + }; + + contentDir = mkOption { + type = types.str; + default = "${cfg.stateDir}/data/lfs"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/data/lfs"''; + description = mdDoc "Where to store LFS files."; + }; + }; + + repositoryRoot = mkOption { + type = types.str; + default = "${cfg.stateDir}/repositories"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/repositories"''; + description = mdDoc "Path to the git repositories."; + }; + + mailerPasswordFile = mkOption { + type = types.nullOr types.str; + default = null; + example = "/run/keys/forgejo-mailpw"; + description = mdDoc "Path to a file containing the SMTP password."; + }; + + settings = mkOption { + default = { }; + description = mdDoc '' + Free-form settings written directly to the `app.ini` configfile file. + Refer to <https://forgejo.org/docs/latest/admin/config-cheat-sheet/> for supported values. + ''; + example = literalExpression '' + { + DEFAULT = { + RUN_MODE = "dev"; + }; + "cron.sync_external_users" = { + RUN_AT_START = true; + SCHEDULE = "@every 24h"; + UPDATE_EXISTING = true; + }; + mailer = { + ENABLED = true; + MAILER_TYPE = "sendmail"; + FROM = "do-not-reply@example.org"; + SENDMAIL_PATH = "''${pkgs.system-sendmail}/bin/sendmail"; + }; + other = { + SHOW_FOOTER_VERSION = false; + }; + } + ''; + type = types.submodule { + freeformType = format.type; + options = { + log = { + ROOT_PATH = mkOption { + default = "${cfg.stateDir}/log"; + defaultText = literalExpression ''"''${config.${opt.stateDir}}/log"''; + type = types.str; + description = mdDoc "Root path for log files."; + }; + LEVEL = mkOption { + default = "Info"; + type = types.enum [ "Trace" "Debug" "Info" "Warn" "Error" "Critical" ]; + description = mdDoc "General log level."; + }; + }; + + server = { + PROTOCOL = mkOption { + type = types.enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ]; + default = "http"; + description = mdDoc ''Listen protocol. `+unix` means "over unix", not "in addition to."''; + }; + + HTTP_ADDR = mkOption { + type = types.either types.str types.path; + default = if lib.hasSuffix "+unix" cfg.settings.server.PROTOCOL then "/run/forgejo/forgejo.sock" else "0.0.0.0"; + defaultText = literalExpression ''if lib.hasSuffix "+unix" cfg.settings.server.PROTOCOL then "/run/forgejo/forgejo.sock" else "0.0.0.0"''; + description = mdDoc "Listen address. Must be a path when using a unix socket."; + }; + + HTTP_PORT = mkOption { + type = types.port; + default = 3000; + description = mdDoc "Listen port. Ignored when using a unix socket."; + }; + + DOMAIN = mkOption { + type = types.str; + default = "localhost"; + description = mdDoc "Domain name of your server."; + }; + + ROOT_URL = mkOption { + type = types.str; + default = "http://${cfg.settings.server.DOMAIN}:${toString cfg.settings.server.HTTP_PORT}/"; + defaultText = literalExpression ''"http://''${config.services.forgejo.settings.server.DOMAIN}:''${toString config.services.forgejo.settings.server.HTTP_PORT}/"''; + description = mdDoc "Full public URL of Forgejo server."; + }; + + STATIC_ROOT_PATH = mkOption { + type = types.either types.str types.path; + default = cfg.package.data; + defaultText = literalExpression "config.${opt.package}.data"; + example = "/var/lib/forgejo/data"; + description = mdDoc "Upper level of template and static files path."; + }; + + DISABLE_SSH = mkOption { + type = types.bool; + default = false; + description = mdDoc "Disable external SSH feature."; + }; + + SSH_PORT = mkOption { + type = types.port; + default = 22; + example = 2222; + description = mdDoc '' + SSH port displayed in clone URL. + The option is required to configure a service when the external visible port + differs from the local listening port i.e. if port forwarding is used. + ''; + }; + }; + + session = { + COOKIE_SECURE = mkOption { + type = types.bool; + default = false; + description = mdDoc '' + Marks session cookies as "secure" as a hint for browsers to only send + them via HTTPS. This option is recommend, if Forgejo is being served over HTTPS. + ''; + }; + }; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = cfg.database.createDatabase -> useSqlite || cfg.database.user == cfg.user; + message = "services.forgejo.database.user must match services.forgejo.user if the database is to be automatically provisioned"; + } + ]; + + services.forgejo.settings = { + DEFAULT = { + RUN_MODE = mkDefault "prod"; + RUN_USER = mkDefault cfg.user; + WORK_PATH = mkDefault cfg.stateDir; + }; + + database = mkMerge [ + { + DB_TYPE = cfg.database.type; + } + (mkIf (useMysql || usePostgresql) { + HOST = if cfg.database.socket != null then cfg.database.socket else cfg.database.host + ":" + toString cfg.database.port; + NAME = cfg.database.name; + USER = cfg.database.user; + PASSWD = "#dbpass#"; + }) + (mkIf useSqlite { + PATH = cfg.database.path; + }) + (mkIf usePostgresql { + SSL_MODE = "disable"; + }) + ]; + + repository = { + ROOT = cfg.repositoryRoot; + }; + + server = mkIf cfg.lfs.enable { + LFS_START_SERVER = true; + LFS_JWT_SECRET = "#lfsjwtsecret#"; + }; + + session = { + COOKIE_NAME = mkDefault "session"; + }; + + security = { + SECRET_KEY = "#secretkey#"; + INTERNAL_TOKEN = "#internaltoken#"; + INSTALL_LOCK = true; + }; + + mailer = mkIf (cfg.mailerPasswordFile != null) { + PASSWD = "#mailerpass#"; + }; + + oauth2 = { + JWT_SECRET = "#oauth2jwtsecret#"; + }; + + lfs = mkIf cfg.lfs.enable { + PATH = cfg.lfs.contentDir; + }; + }; + + services.postgresql = optionalAttrs (usePostgresql && cfg.database.createDatabase) { + enable = mkDefault true; + + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { + name = cfg.database.user; + ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; }; + } + ]; + }; + + services.mysql = optionalAttrs (useMysql && cfg.database.createDatabase) { + enable = mkDefault true; + package = mkDefault pkgs.mariadb; + + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { + name = cfg.database.user; + ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; }; + } + ]; + }; + + systemd.tmpfiles.rules = [ + "d '${cfg.dump.backupDir}' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.dump.backupDir}' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.repositoryRoot}' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.repositoryRoot}' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.stateDir}/conf' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.customDir}' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.customDir}/conf' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.stateDir}/data' 0750 ${cfg.user} ${cfg.group} - -" + "d '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.stateDir}/.ssh' 0700 ${cfg.user} ${cfg.group} - -" + "z '${cfg.stateDir}/conf' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.customDir}' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.customDir}/conf' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.stateDir}/data' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -" + + # If we have a folder or symlink with Forgejo locales, remove it + # And symlink the current Forgejo locales in place + "L+ '${cfg.stateDir}/conf/locale' - - - - ${cfg.package.out}/locale" + + ] ++ optionals cfg.lfs.enable [ + "d '${cfg.lfs.contentDir}' 0750 ${cfg.user} ${cfg.group} - -" + "z '${cfg.lfs.contentDir}' 0750 ${cfg.user} ${cfg.group} - -" + ]; + + systemd.services.forgejo = { + description = "Forgejo (Beyond coding. We forge.)"; + after = [ + "network.target" + ] ++ optionals usePostgresql [ + "postgresql.service" + ] ++ optionals useMysql [ + "mysql.service" + ]; + requires = optionals (cfg.database.createDatabase && usePostgresql) [ + "postgresql.service" + ] ++ optionals (cfg.database.createDatabase && useMysql) [ + "mysql.service" + ]; + wantedBy = [ "multi-user.target" ]; + path = [ cfg.package pkgs.git pkgs.gnupg ]; + + # In older versions the secret naming for JWT was kind of confusing. + # The file jwt_secret hold the value for LFS_JWT_SECRET and JWT_SECRET + # wasn't persistent at all. + # To fix that, there is now the file oauth2_jwt_secret containing the + # values for JWT_SECRET and the file jwt_secret gets renamed to + # lfs_jwt_secret. + # We have to consider this to stay compatible with older installations. + preStart = + let + runConfig = "${cfg.customDir}/conf/app.ini"; + secretKey = "${cfg.customDir}/conf/secret_key"; + oauth2JwtSecret = "${cfg.customDir}/conf/oauth2_jwt_secret"; + oldLfsJwtSecret = "${cfg.customDir}/conf/jwt_secret"; # old file for LFS_JWT_SECRET + lfsJwtSecret = "${cfg.customDir}/conf/lfs_jwt_secret"; # new file for LFS_JWT_SECRET + internalToken = "${cfg.customDir}/conf/internal_token"; + replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; + in + '' + # copy custom configuration and generate random secrets if needed + ${lib.optionalString (!cfg.useWizard) '' + function forgejo_setup { + cp -f '${format.generate "app.ini" cfg.settings}' '${runConfig}' + + if [ ! -s '${secretKey}' ]; then + ${exe} generate secret SECRET_KEY > '${secretKey}' + fi + + # Migrate LFS_JWT_SECRET filename + if [[ -s '${oldLfsJwtSecret}' && ! -s '${lfsJwtSecret}' ]]; then + mv '${oldLfsJwtSecret}' '${lfsJwtSecret}' + fi + + if [ ! -s '${oauth2JwtSecret}' ]; then + ${exe} generate secret JWT_SECRET > '${oauth2JwtSecret}' + fi + + ${optionalString cfg.lfs.enable '' + if [ ! -s '${lfsJwtSecret}' ]; then + ${exe} generate secret LFS_JWT_SECRET > '${lfsJwtSecret}' + fi + ''} + + if [ ! -s '${internalToken}' ]; then + ${exe} generate secret INTERNAL_TOKEN > '${internalToken}' + fi + + chmod u+w '${runConfig}' + ${replaceSecretBin} '#secretkey#' '${secretKey}' '${runConfig}' + ${replaceSecretBin} '#oauth2jwtsecret#' '${oauth2JwtSecret}' '${runConfig}' + ${replaceSecretBin} '#internaltoken#' '${internalToken}' '${runConfig}' + + ${optionalString cfg.lfs.enable '' + ${replaceSecretBin} '#lfsjwtsecret#' '${lfsJwtSecret}' '${runConfig}' + ''} + + ${optionalString (cfg.database.passwordFile != null) '' + ${replaceSecretBin} '#dbpass#' '${cfg.database.passwordFile}' '${runConfig}' + ''} + + ${optionalString (cfg.mailerPasswordFile != null) '' + ${replaceSecretBin} '#mailerpass#' '${cfg.mailerPasswordFile}' '${runConfig}' + ''} + chmod u-w '${runConfig}' + } + (umask 027; forgejo_setup) + ''} + + # run migrations/init the database + ${exe} migrate + + # update all hooks' binary paths + ${exe} admin regenerate hooks + + # update command option in authorized_keys + if [ -r ${cfg.stateDir}/.ssh/authorized_keys ] + then + ${exe} admin regenerate keys + fi + ''; + + serviceConfig = { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = cfg.stateDir; + ExecStart = "${exe} web --pid /run/forgejo/forgejo.pid"; + Restart = "always"; + # Runtime directory and mode + RuntimeDirectory = "forgejo"; + RuntimeDirectoryMode = "0755"; + # Proc filesystem + ProcSubset = "pid"; + ProtectProc = "invisible"; + # Access write directories + ReadWritePaths = [ cfg.customDir cfg.dump.backupDir cfg.repositoryRoot cfg.stateDir cfg.lfs.contentDir ]; + UMask = "0027"; + # Capabilities + CapabilityBoundingSet = ""; + # Security + NoNewPrivileges = true; + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = true; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; + SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid" "setrlimit" ]; + }; + + environment = { + USER = cfg.user; + HOME = cfg.stateDir; + # `GITEA_` prefix until https://codeberg.org/forgejo/forgejo/issues/497 + # is resolved. + GITEA_WORK_DIR = cfg.stateDir; + GITEA_CUSTOM = cfg.customDir; + }; + }; + + users.users = mkIf (cfg.user == "forgejo") { + forgejo = { + home = cfg.stateDir; + useDefaultShell = true; + group = cfg.group; + isSystemUser = true; + }; + }; + + users.groups = mkIf (cfg.group == "forgejo") { + forgejo = { }; + }; + + systemd.services.forgejo-dump = mkIf cfg.dump.enable { + description = "forgejo dump"; + after = [ "forgejo.service" ]; + path = [ cfg.package ]; + + environment = { + USER = cfg.user; + HOME = cfg.stateDir; + # `GITEA_` prefix until https://codeberg.org/forgejo/forgejo/issues/497 + # is resolved. + GITEA_WORK_DIR = cfg.stateDir; + GITEA_CUSTOM = cfg.customDir; + }; + + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + ExecStart = "${exe} dump --type ${cfg.dump.type}" + optionalString (cfg.dump.file != null) " --file ${cfg.dump.file}"; + WorkingDirectory = cfg.dump.backupDir; + }; + }; + + systemd.timers.forgejo-dump = mkIf cfg.dump.enable { + description = "Forgejo dump timer"; + partOf = [ "forgejo-dump.service" ]; + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = cfg.dump.interval; + }; + }; + + meta.maintainers = with lib.maintainers; [ bendlas emilylange ]; +} diff --git a/nixpkgs/nixos/modules/services/networking/adguardhome.nix b/nixpkgs/nixos/modules/services/networking/adguardhome.nix index 1701e5b439c1..399d838ccc69 100644 --- a/nixpkgs/nixos/modules/services/networking/adguardhome.nix +++ b/nixpkgs/nixos/modules/services/networking/adguardhome.nix @@ -17,6 +17,7 @@ let text = builtins.toJSON cfg.settings; checkPhase = "${pkgs.adguardhome}/bin/adguardhome -c $out --check-config"; }; + defaultBindPort = 3000; in { @@ -86,7 +87,7 @@ in ''; }; bind_port = mkOption { - default = 3000; + default = defaultBindPort; type = port; description = lib.mdDoc '' Port to serve HTTP pages on. @@ -169,6 +170,6 @@ in }; }; - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.bind_port ]; + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.bind_port or defaultBindPort ]; }; } diff --git a/nixpkgs/nixos/modules/services/networking/networkmanager.nix b/nixpkgs/nixos/modules/services/networking/networkmanager.nix index e28f96f7a6d6..6bc46a9a90e4 100644 --- a/nixpkgs/nixos/modules/services/networking/networkmanager.nix +++ b/nixpkgs/nixos/modules/services/networking/networkmanager.nix @@ -5,7 +5,7 @@ with lib; let cfg = config.networking.networkmanager; - delegateWireless = config.networking.wireless.enable == true && cfg.unmanaged != []; + delegateWireless = config.networking.wireless.enable == true && cfg.unmanaged != [ ]; enableIwd = cfg.wifi.backend == "iwd"; @@ -40,7 +40,7 @@ let }) (mkSection "keyfile" { unmanaged-devices = - if cfg.unmanaged == [] then null + if cfg.unmanaged == [ ] then null else lib.concatStringsSep ";" cfg.unmanaged; }) (mkSection "logging" { @@ -103,7 +103,7 @@ let }; macAddressOpt = mkOption { - type = types.either types.str (types.enum ["permanent" "preserve" "random" "stable"]); + type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" ]); default = "preserve"; example = "00:11:22:33:44:55"; description = lib.mdDoc '' @@ -126,7 +126,8 @@ let pkgs.wpa_supplicant ]; -in { +in +{ meta = { maintainers = teams.freedesktop.members; @@ -156,7 +157,7 @@ in { int str ])); - default = {}; + default = { }; description = lib.mdDoc '' Configuration for the [connection] section of NetworkManager.conf. Refer to @@ -186,7 +187,7 @@ in { unmanaged = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = lib.mdDoc '' List of interfaces that will not be managed by NetworkManager. Interface name can be specified here, but if you need more fidelity, @@ -251,7 +252,7 @@ in { appendNameservers = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = lib.mdDoc '' A list of name servers that should be appended to the ones configured in NetworkManager or received by DHCP. @@ -260,7 +261,7 @@ in { insertNameservers = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = lib.mdDoc '' A list of name servers that should be inserted before the ones configured in NetworkManager or received by DHCP. @@ -336,21 +337,21 @@ in { }; }; }); - default = []; + default = [ ]; example = literalExpression '' - [ { - source = pkgs.writeText "upHook" ''' - - if [ "$2" != "up" ]; then - logger "exit: event $2 != up" - exit - fi - - # coreutils and iproute are in PATH too - logger "Device $DEVICE_IFACE coming up" - '''; - type = "basic"; - } ]''; + [ { + source = pkgs.writeText "upHook" ''' + + if [ "$2" != "up" ]; then + logger "exit: event $2 != up" + exit + fi + + # coreutils and iproute are in PATH too + logger "Device $DEVICE_IFACE coming up" + '''; + type = "basic"; + } ]''; description = lib.mdDoc '' A list of scripts which will be executed in response to network events. ''; @@ -369,14 +370,24 @@ in { ''; }; - enableFccUnlock = mkOption { - type = types.bool; - default = false; + fccUnlockScripts = mkOption { + type = types.listOf (types.submodule { + options = { + id = mkOption { + type = types.str; + description = lib.mdDoc "vid:pid of either the PCI or USB vendor and product ID"; + }; + path = mkOption { + type = types.path; + description = lib.mdDoc "Path to the unlock script"; + }; + }; + }); + default = [ ]; + example = literalExpression ''[{ name = "03f0:4e1d"; script = "''${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/03f0:4e1d"; }]''; description = lib.mdDoc '' - Enable FCC unlock procedures. Since release 1.18.4, the ModemManager daemon no longer - automatically performs the FCC unlock procedure by default. See - [the docs](https://modemmanager.org/docs/modemmanager/fcc-unlock/) - for more details. + List of FCC unlock scripts to enable on the system, behaving as described in + https://modemmanager.org/docs/modemmanager/fcc-unlock/#integration-with-third-party-fcc-unlock-tools. ''; }; }; @@ -387,7 +398,14 @@ in { [ "networking" "networkmanager" "packages" ] [ "networking" "networkmanager" "plugins" ]) (mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ]) - (mkRemovedOptionModule ["networking" "networkmanager" "dynamicHosts"] '' + (mkRemovedOptionModule [ "networking" "networkmanager" "enableFccUnlock" ] '' + This option was removed, because using bundled FCC unlock scripts is risky, + might conflict with vendor-provided unlock scripts, and should + be a conscious decision on a per-device basis. + Instead it's recommended to use the + `networking.networkmanager.fccUnlockScripts` option. + '') + (mkRemovedOptionModule [ "networking" "networkmanager" "dynamicHosts" ] '' This option was removed because allowing (multiple) regular users to override host entries affecting the whole system opens up a huge attack vector. There seem to be very rare cases where this might be useful. @@ -403,7 +421,8 @@ in { config = mkIf cfg.enable { assertions = [ - { assertion = config.networking.wireless.enable == true -> cfg.unmanaged != []; + { + assertion = config.networking.wireless.enable == true -> cfg.unmanaged != [ ]; message = '' You can not use networking.networkmanager with networking.wireless. Except if you mark some interfaces as <literal>unmanaged</literal> by NetworkManager. @@ -414,25 +433,29 @@ in { hardware.wirelessRegulatoryDatabase = true; environment.etc = { - "NetworkManager/NetworkManager.conf".source = configFile; - } - // builtins.listToAttrs (map (pkg: nameValuePair "NetworkManager/${pkg.networkManagerPlugin}" { + "NetworkManager/NetworkManager.conf".source = configFile; + } + // builtins.listToAttrs (map + (pkg: nameValuePair "NetworkManager/${pkg.networkManagerPlugin}" { source = "${pkg}/lib/NetworkManager/${pkg.networkManagerPlugin}"; - }) cfg.plugins) - // optionalAttrs cfg.enableFccUnlock - { - "ModemManager/fcc-unlock.d".source = - "${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/*"; - } - // optionalAttrs (cfg.appendNameservers != [] || cfg.insertNameservers != []) - { - "NetworkManager/dispatcher.d/02overridedns".source = overrideNameserversScript; - } - // listToAttrs (lib.imap1 (i: s: - { - name = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}"; - value = { mode = "0544"; inherit (s) source; }; - }) cfg.dispatcherScripts); + }) + cfg.plugins) + // builtins.listToAttrs (map + (e: nameValuePair "ModemManager/fcc-unlock.d/${e.id}" { + source = e.path; + }) + cfg.fccUnlockScripts) + // optionalAttrs (cfg.appendNameservers != [ ] || cfg.insertNameservers != [ ]) + { + "NetworkManager/dispatcher.d/02overridedns".source = overrideNameserversScript; + } + // listToAttrs (lib.imap1 + (i: s: + { + name = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}"; + value = { mode = "0544"; inherit (s) source; }; + }) + cfg.dispatcherScripts); environment.systemPackages = packages; diff --git a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix index 162267b5a85d..942317f8da74 100644 --- a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix @@ -33,8 +33,7 @@ let ${cfg.extraConfig} EOL - ssh-keygen -q -f mock-hostkey -N "" - sshd -t -f $out -h mock-hostkey + sshd -G -f $out ''; cfg = config.services.openssh; diff --git a/nixpkgs/nixos/modules/services/networking/trust-dns.nix b/nixpkgs/nixos/modules/services/networking/trust-dns.nix index a3b4d12479b4..4196d124a2ab 100644 --- a/nixpkgs/nixos/modules/services/networking/trust-dns.nix +++ b/nixpkgs/nixos/modules/services/networking/trust-dns.nix @@ -1,5 +1,4 @@ { config, lib, pkgs, ... }: - let cfg = config.services.trust-dns; toml = pkgs.formats.toml { }; @@ -55,7 +54,7 @@ in defaultText = "pkgs.trust-dns"; description = mdDoc '' Trust-dns package to use. - Only `bin/named` need be provided: the other trust-dns utilities (client and resolver) are not needed. + Only `bin/trust-dns` need be provided: the other trust-dns utilities (client and resolver) are not needed. ''; }; quiet = mkOption { @@ -136,7 +135,7 @@ in flags = (lib.optional cfg.debug "--debug") ++ (lib.optional cfg.quiet "--quiet"); flagsStr = builtins.concatStringsSep " " flags; in '' - ${cfg.package}/bin/named --config ${configFile} ${flagsStr} + ${cfg.package}/bin/trust-dns --config ${configFile} ${flagsStr} ''; Type = "simple"; Restart = "on-failure"; diff --git a/nixpkgs/nixos/modules/services/networking/websockify.nix b/nixpkgs/nixos/modules/services/networking/websockify.nix index 45a3487bd337..27ad8953d3fa 100644 --- a/nixpkgs/nixos/modules/services/networking/websockify.nix +++ b/nixpkgs/nixos/modules/services/networking/websockify.nix @@ -38,7 +38,7 @@ let cfg = config.services.networking.websockify; in { description = "Service to forward websocket connections to TCP connections (from port:to port %I)"; script = '' IFS=':' read -a array <<< "$1" - ${pkgs.pythonPackages.websockify}/bin/websockify --ssl-only \ + ${pkgs.python3Packages.websockify}/bin/websockify --ssl-only \ --cert=${cfg.sslCert} --key=${cfg.sslKey} 0.0.0.0:''${array[0]} 0.0.0.0:''${array[1]} ''; scriptArgs = "%i"; diff --git a/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix b/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix index b3fdb681e2f3..b92525075541 100644 --- a/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix +++ b/nixpkgs/nixos/modules/services/web-apps/healthchecks.nix @@ -1,16 +1,16 @@ -{ config, lib, pkgs, buildEnv, ... }: +{ config, lib, options, pkgs, buildEnv, ... }: with lib; let defaultUser = "healthchecks"; cfg = config.services.healthchecks; + opt = options.services.healthchecks; pkg = cfg.package; boolToPython = b: if b then "True" else "False"; environment = { PYTHONPATH = pkg.pythonPath; STATIC_ROOT = cfg.dataDir + "/static"; - DB_NAME = "${cfg.dataDir}/healthchecks.sqlite"; } // cfg.settings; environmentFile = pkgs.writeText "healthchecks-environment" (lib.generators.toKeyValue { } environment); @@ -98,17 +98,24 @@ in description = lib.mdDoc '' Environment variables which are read by healthchecks `(local)_settings.py`. - Settings which are explicitly covered in options bewlow, are type-checked and/or transformed + Settings which are explicitly covered in options below, are type-checked and/or transformed before added to the environment, everything else is passed as a string. See <https://healthchecks.io/docs/self_hosted_configuration/> for a full documentation of settings. - We add two variables to this list inside the packages `local_settings.py.` - - STATIC_ROOT to set a state directory for dynamically generated static files. - - SECRET_KEY_FILE to read SECRET_KEY from a file at runtime and keep it out of /nix/store. + We add additional variables to this list inside the packages `local_settings.py.` + - `STATIC_ROOT` to set a state directory for dynamically generated static files. + - `SECRET_KEY_FILE` to read `SECRET_KEY` from a file at runtime and keep it out of + /nix/store. + - `_FILE` variants for several values that hold sensitive information in + [Healthchecks configuration](https://healthchecks.io/docs/self_hosted_configuration/) so + that they also can be read from a file and kept out of /nix/store. To see which values + have support for a `_FILE` variant, run: + - `nix-instantiate --eval --expr '(import <nixpkgs> {}).healthchecks.secrets'` + - or `nix eval 'nixpkgs#healthchecks.secrets'` if the flake support has been enabled. ''; - type = types.submodule { + type = types.submodule (settings: { freeformType = types.attrsOf types.str; options = { ALLOWED_HOSTS = lib.mkOption { @@ -143,8 +150,28 @@ in ''; apply = boolToPython; }; + + DB = mkOption { + type = types.enum [ "sqlite" "postgres" "mysql" ]; + default = "sqlite"; + description = lib.mdDoc "Database engine to use."; + }; + + DB_NAME = mkOption { + type = types.str; + default = + if settings.config.DB == "sqlite" + then "${cfg.dataDir}/healthchecks.sqlite" + else "hc"; + defaultText = lib.literalExpression '' + if config.${settings.options.DB} == "sqlite" + then "''${config.${opt.dataDir}}/healthchecks.sqlite" + else "hc" + ''; + description = lib.mdDoc "Database name."; + }; }; - }; + }); }; }; @@ -168,7 +195,7 @@ in StateDirectoryMode = mkIf (cfg.dataDir == "/var/lib/healthchecks") "0750"; }; in - { + { healthchecks-migration = { description = "Healthchecks migrations"; wantedBy = [ "healthchecks.target" ]; diff --git a/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix b/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix new file mode 100644 index 000000000000..cb864321ef27 --- /dev/null +++ b/nixpkgs/nixos/modules/services/web-apps/meme-bingo-web.nix @@ -0,0 +1,93 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) mkEnableOption mkIf mkOption mdDoc types literalExpression; + + cfg = config.services.meme-bingo-web; +in { + options = { + services.meme-bingo-web = { + enable = mkEnableOption (mdDoc '' + A web app for the meme bingo, rendered entirely on the web server and made interactive with forms. + + Note: The application's author suppose to run meme-bingo-web behind a reverse proxy for SSL and HTTP/3. + ''); + + package = mkOption { + type = types.package; + default = pkgs.meme-bingo-web; + defaultText = literalExpression "pkgs.meme-bingo-web"; + description = mdDoc "meme-bingo-web package to use."; + }; + + baseUrl = mkOption { + description = mdDoc '' + URL to be used for the HTML <base> element on all HTML routes. + ''; + type = types.str; + default = "http://localhost:41678/"; + example = "https://bingo.example.com/"; + }; + port = mkOption { + description = mdDoc '' + Port to be used for the web server. + ''; + type = types.port; + default = 41678; + example = 21035; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.meme-bingo-web = { + description = "A web app for playing meme bingos."; + wantedBy = [ "multi-user.target" ]; + + environment = { + MEME_BINGO_BASE = cfg.baseUrl; + MEME_BINGO_PORT = toString cfg.port; + }; + path = [ cfg.package ]; + + serviceConfig = { + User = "meme-bingo-web"; + Group = "meme-bingo-web"; + + DynamicUser = true; + + ExecStart = "${cfg.package}/bin/meme-bingo-web"; + + Restart = "always"; + RestartSec = 1; + + # Hardening + CapabilityBoundingSet = [ "" ]; + DeviceAllow = [ "/dev/random" ]; + LockPersonality = true; + PrivateDevices = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectSystem = "strict"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; + UMask = "0077"; + RestrictSUIDSGID = true; + RemoveIPC = true; + NoNewPrivileges = true; + MemoryDenyWriteExecute = true; + }; + }; + }; +} diff --git a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix index 1770f0759434..d9a1535ffc7d 100644 --- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix +++ b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix @@ -147,7 +147,7 @@ in { default = false; type = types.bool; description = lib.mdDoc '' - Make MemTest86+ available from the systemd-boot menu. MemTest86+ is a + Make Memtest86+ available from the systemd-boot menu. Memtest86+ is a program for testing memory. ''; }; @@ -191,7 +191,7 @@ in { default = {}; example = literalExpression '' { "memtest86.conf" = ''' - title MemTest86+ + title Memtest86+ efi /efi/memtest86/memtest.efi '''; } ''; @@ -285,7 +285,7 @@ in { boot.loader.systemd-boot.extraEntries = mkMerge [ (mkIf cfg.memtest86.enable { "${cfg.memtest86.entryFilename}" = '' - title MemTest86 + title Memtest86+ efi /efi/memtest86/memtest.efi ''; }) diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix index 87afc5023253..238c6670ea0f 100644 --- a/nixpkgs/nixos/modules/system/boot/networkd.nix +++ b/nixpkgs/nixos/modules/system/boot/networkd.nix @@ -902,6 +902,9 @@ let "RelayTarget" "RelayAgentCircuitId" "RelayAgentRemoteId" + "BootServerAddress" + "BootServerName" + "BootFilename" ]) (assertInt "PoolOffset") (assertMinimum "PoolOffset" 0) diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix index 21d604bee6e3..5cf863c87f27 100644 --- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix @@ -662,6 +662,11 @@ in ]; }; + # ZFS already has its own scheduler. Without this my(@Artturin) computer froze for a second when I nix build something. + services.udev.extraRules = '' + ACTION=="add|change", KERNEL=="sd[a-z]*[0-9]*|mmcblk[0-9]*p[0-9]*|nvme[0-9]*n[0-9]*p[0-9]*", ENV{ID_FS_TYPE}=="zfs_member", ATTR{../queue/scheduler}="none" + ''; + environment.etc = genAttrs (map (file: "zfs/zed.d/${file}") diff --git a/nixpkgs/nixos/tests/acme.nix b/nixpkgs/nixos/tests/acme.nix index f255c655bffc..e5f2d4c7934a 100644 --- a/nixpkgs/nixos/tests/acme.nix +++ b/nixpkgs/nixos/tests/acme.nix @@ -18,7 +18,7 @@ dnsConfig = nodes: { dnsProvider = "exec"; dnsPropagationCheck = false; - credentialsFile = pkgs.writeText "wildcard.env" '' + environmentFile = pkgs.writeText "wildcard.env" '' EXEC_PATH=${dnsScript nodes} EXEC_POLLING_INTERVAL=1 EXEC_PROPAGATION_TIMEOUT=1 diff --git a/nixpkgs/nixos/tests/adguardhome.nix b/nixpkgs/nixos/tests/adguardhome.nix index 9f8ddc33f57e..a6f790b83f5f 100644 --- a/nixpkgs/nixos/tests/adguardhome.nix +++ b/nixpkgs/nixos/tests/adguardhome.nix @@ -7,7 +7,6 @@ emptyConf = { lib, ... }: { services.adguardhome = { enable = true; - settings = {}; }; }; diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix index d674d0cdba37..30ea7c70026f 100644 --- a/nixpkgs/nixos/tests/all-tests.nix +++ b/nixpkgs/nixos/tests/all-tests.nix @@ -284,7 +284,7 @@ in { fluentd = handleTest ./fluentd.nix {}; fluidd = handleTest ./fluidd.nix {}; fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {}; - forgejo = handleTest ./gitea.nix { giteaPackage = pkgs.forgejo; }; + forgejo = handleTest ./forgejo.nix { }; freenet = handleTest ./freenet.nix {}; freeswitch = handleTest ./freeswitch.nix {}; freshrss-sqlite = handleTest ./freshrss-sqlite.nix {}; diff --git a/nixpkgs/nixos/tests/fontconfig-default-fonts.nix b/nixpkgs/nixos/tests/fontconfig-default-fonts.nix index d8c6ea0f721b..293dc43f91f3 100644 --- a/nixpkgs/nixos/tests/fontconfig-default-fonts.nix +++ b/nixpkgs/nixos/tests/fontconfig-default-fonts.nix @@ -9,7 +9,7 @@ import ./make-test-python.nix ({ lib, ... }: nodes.machine = { config, pkgs, ... }: { fonts.enableDefaultPackages = true; # Background fonts fonts.packages = with pkgs; [ - noto-fonts-emoji + noto-fonts-color-emoji cantarell-fonts twitter-color-emoji source-code-pro diff --git a/nixpkgs/nixos/tests/forgejo.nix b/nixpkgs/nixos/tests/forgejo.nix new file mode 100644 index 000000000000..b326819e3190 --- /dev/null +++ b/nixpkgs/nixos/tests/forgejo.nix @@ -0,0 +1,157 @@ +{ system ? builtins.currentSystem +, config ? { } +, pkgs ? import ../.. { inherit system config; } +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; +with pkgs.lib; + +let + ## gpg --faked-system-time='20230301T010000!' --quick-generate-key snakeoil ed25519 sign + signingPrivateKey = '' + -----BEGIN PGP PRIVATE KEY BLOCK----- + + lFgEY/6jkBYJKwYBBAHaRw8BAQdADXiZRV8RJUyC9g0LH04wLMaJL9WTc+szbMi7 + 5fw4yP8AAQCl8EwGfzSLm/P6fCBfA3I9znFb3MEHGCCJhJ6VtKYyRw7ktAhzbmFr + ZW9pbIiUBBMWCgA8FiEE+wUM6VW/NLtAdSixTWQt6LZ4x50FAmP+o5ACGwMFCQPC + ZwAECwkIBwQVCgkIBRYCAwEAAh4FAheAAAoJEE1kLei2eMedFTgBAKQs1oGFZrCI + TZP42hmBTKxGAI1wg7VSdDEWTZxut/2JAQDGgo2sa4VHMfj0aqYGxrIwfP2B7JHO + GCqGCRf9O/hzBA== + =9Uy3 + -----END PGP PRIVATE KEY BLOCK----- + ''; + signingPrivateKeyId = "4D642DE8B678C79D"; + + supportedDbTypes = [ "mysql" "postgres" "sqlite3" ]; + makeGForgejoTest = type: nameValuePair type (makeTest { + name = "forgejo-${type}"; + meta.maintainers = with maintainers; [ bendlas emilylange ]; + + nodes = { + server = { config, pkgs, ... }: { + virtualisation.memorySize = 2047; + services.forgejo = { + enable = true; + database = { inherit type; }; + settings.service.DISABLE_REGISTRATION = true; + settings."repository.signing".SIGNING_KEY = signingPrivateKeyId; + settings.actions.ENABLED = true; + }; + environment.systemPackages = [ config.services.forgejo.package pkgs.gnupg pkgs.jq ]; + services.openssh.enable = true; + + specialisation.runner = { + inheritParentConfig = true; + configuration.services.gitea-actions-runner.instances."test" = { + enable = true; + name = "ci"; + url = "http://localhost:3000"; + labels = [ + # don't require docker/podman + "native:host" + ]; + tokenFile = "/var/lib/forgejo/runner_token"; + }; + }; + }; + client1 = { config, pkgs, ... }: { + environment.systemPackages = [ pkgs.git ]; + }; + client2 = { config, pkgs, ... }: { + environment.systemPackages = [ pkgs.git ]; + }; + }; + + testScript = { nodes, ... }: + let + inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; + serverSystem = nodes.server.system.build.toplevel; + in + '' + GIT_SSH_COMMAND = "ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no" + REPO = "forgejo@server:test/repo" + PRIVK = "${snakeOilPrivateKey}" + + start_all() + + client1.succeed("mkdir /tmp/repo") + client1.succeed("mkdir -p $HOME/.ssh") + client1.succeed(f"cat {PRIVK} > $HOME/.ssh/privk") + client1.succeed("chmod 0400 $HOME/.ssh/privk") + client1.succeed("git -C /tmp/repo init") + client1.succeed("echo hello world > /tmp/repo/testfile") + client1.succeed("git -C /tmp/repo add .") + client1.succeed("git config --global user.email test@localhost") + client1.succeed("git config --global user.name test") + client1.succeed("git -C /tmp/repo commit -m 'Initial import'") + client1.succeed(f"git -C /tmp/repo remote add origin {REPO}") + + server.wait_for_unit("forgejo.service") + server.wait_for_open_port(3000) + server.wait_for_open_port(22) + server.succeed("curl --fail http://localhost:3000/") + + server.succeed( + "su -l forgejo -c 'gpg --homedir /var/lib/forgejo/data/home/.gnupg " + + "--import ${toString (pkgs.writeText "forgejo.key" signingPrivateKey)}'" + ) + + assert "BEGIN PGP PUBLIC KEY BLOCK" in server.succeed("curl http://localhost:3000/api/v1/signing-key.gpg") + + server.succeed( + "curl --fail http://localhost:3000/user/sign_up | grep 'Registration is disabled. " + + "Please contact your site administrator.'" + ) + server.succeed( + "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea admin user create " + + "--username test --password totallysafe --email test@localhost'" + ) + + api_token = server.succeed( + "curl --fail -X POST http://test:totallysafe@localhost:3000/api/v1/users/test/tokens " + + "-H 'Accept: application/json' -H 'Content-Type: application/json' -d " + + "'{\"name\":\"token\",\"scopes\":[\"all\"]}' | jq '.sha1' | xargs echo -n" + ) + + server.succeed( + "curl --fail -X POST http://localhost:3000/api/v1/user/repos " + + "-H 'Accept: application/json' -H 'Content-Type: application/json' " + + f"-H 'Authorization: token {api_token}'" + + ' -d \'{"auto_init":false, "description":"string", "license":"mit", "name":"repo", "private":false}\''' + ) + + server.succeed( + "curl --fail -X POST http://localhost:3000/api/v1/user/keys " + + "-H 'Accept: application/json' -H 'Content-Type: application/json' " + + f"-H 'Authorization: token {api_token}'" + + ' -d \'{"key":"${snakeOilPublicKey}","read_only":true,"title":"SSH"}\''' + ) + + client1.succeed( + f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git -C /tmp/repo push origin master" + ) + + client2.succeed("mkdir -p $HOME/.ssh") + client2.succeed(f"cat {PRIVK} > $HOME/.ssh/privk") + client2.succeed("chmod 0400 $HOME/.ssh/privk") + client2.succeed(f"GIT_SSH_COMMAND='{GIT_SSH_COMMAND}' git clone {REPO}") + client2.succeed('test "$(cat repo/testfile | xargs echo -n)" = "hello world"') + + server.wait_until_succeeds( + 'test "$(curl http://localhost:3000/api/v1/repos/test/repo/commits ' + + '-H "Accept: application/json" | jq length)" = "1"', + timeout=10 + ) + + with subtest("Testing runner registration"): + server.succeed( + "su -l forgejo -c 'GITEA_WORK_DIR=/var/lib/forgejo gitea actions generate-runner-token' | sed 's/^/TOKEN=/' | tee /var/lib/forgejo/runner_token" + ) + server.succeed("${serverSystem}/specialisation/runner/bin/switch-to-configuration test") + server.wait_for_unit("gitea-runner-test.service") + server.succeed("journalctl -o cat -u gitea-runner-test.service | grep -q 'Runner registered successfully'") + ''; + }); +in + +listToAttrs (map makeGForgejoTest supportedDbTypes) diff --git a/nixpkgs/nixos/tests/noto-fonts.nix b/nixpkgs/nixos/tests/noto-fonts.nix index edbb0db4cb7a..b871f5f51729 100644 --- a/nixpkgs/nixos/tests/noto-fonts.nix +++ b/nixpkgs/nixos/tests/noto-fonts.nix @@ -11,7 +11,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { noto-fonts noto-fonts-cjk-sans noto-fonts-cjk-serif - noto-fonts-emoji + noto-fonts-color-emoji ]; fontconfig.defaultFonts = { serif = [ "Noto Serif" "Noto Serif CJK SC" ]; diff --git a/nixpkgs/nixos/tests/postgis.nix b/nixpkgs/nixos/tests/postgis.nix index 9d81ebaad85f..d0685abc510c 100644 --- a/nixpkgs/nixos/tests/postgis.nix +++ b/nixpkgs/nixos/tests/postgis.nix @@ -9,7 +9,7 @@ import ./make-test-python.nix ({ pkgs, ...} : { { pkgs, ... }: { - services.postgresql = let mypg = pkgs.postgresql_11; in { + services.postgresql = let mypg = pkgs.postgresql; in { enable = true; package = mypg; extraPlugins = with mypg.pkgs; [ diff --git a/nixpkgs/nixos/tests/shadow.nix b/nixpkgs/nixos/tests/shadow.nix index c9a04088e870..a027af7e450b 100644 --- a/nixpkgs/nixos/tests/shadow.nix +++ b/nixpkgs/nixos/tests/shadow.nix @@ -32,7 +32,7 @@ in import ./make-test-python.nix ({ pkgs, ... }: { }; users.berta = { isNormalUser = true; - hashedPassword = hashed_bcrypt; + hashedPasswordFile = (pkgs.writeText "hashed_bcrypt" hashed_bcrypt).outPath; shell = pkgs.bash; }; users.yesim = { |