diff options
Diffstat (limited to 'nixos')
167 files changed, 2473 insertions, 598 deletions
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix index a368b16201f8..5f51bb53ad7f 100644 --- a/nixos/doc/manual/default.nix +++ b/nixos/doc/manual/default.nix @@ -105,7 +105,9 @@ in rec { mkdir -p $dst cp ${../../../doc/style.css} $dst/style.css - cp ${../../../doc/overrides.css} $dst/overrides.css + cp ${../../../doc/anchor.min.js} $dst/anchor.min.js + cp ${../../../doc/anchor-use.js} $dst/anchor-use.js + cp -r ${pkgs.documentation-highlighter} $dst/highlightjs ${prepareManualFromMD} @@ -115,10 +117,11 @@ in rec { --revision ${lib.escapeShellArg revision} \ --generator "nixos-render-docs ${lib.version}" \ --stylesheet style.css \ - --stylesheet overrides.css \ --stylesheet highlightjs/mono-blue.css \ --script ./highlightjs/highlight.pack.js \ --script ./highlightjs/loader.js \ + --script ./anchor.min.js \ + --script ./anchor-use.js \ --toc-depth 1 \ --chunk-toc-depth 1 \ ./manual.md \ diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index 22689868cf02..19ff6f4485cd 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -82,6 +82,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [ollama](https://ollama.ai), server for running large language models locally. +- [Mihomo](https://github.com/MetaCubeX/mihomo), a rule-based proxy in Go. Available as [services.mihomo.enable](#opt-services.mihomo.enable). + - [hebbot](https://github.com/haecker-felix/hebbot), a Matrix bot to generate "This Week in X" like blog posts. Available as [services.hebbot](#opt-services.hebbot.enable). - [Python Matter Server](https://github.com/home-assistant-libs/python-matter-server), a @@ -103,8 +105,12 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - [Monado](https://monado.freedesktop.org/), an open source XR runtime. Available as [services.monado](#opt-services.monado.enable). +- [Pretix](https://pretix.eu/about/en/), an open source ticketing software for events. Available as [services.pretix]($opt-services-pretix.enable). + - [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable). +- [fritz-exporter](https://github.com/pdreker/fritz_exporter), a Prometheus exporter for extracting metrics from [FRITZ!](https://avm.de/produkte/) devices. Available as [services.prometheus.exporters.fritz](#opt-services.prometheus.exporters.fritz.enable). + - [armagetronad](https://wiki.armagetronad.org), a mid-2000s 3D lightcycle game widely played at iD Tech Camps. You can define multiple servers using `services.armagetronad.<server>.enable`. - [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable). @@ -123,13 +129,15 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> +- `k3s`: was updated to version [v1.29](https://github.com/k3s-io/k3s/releases/tag/v1.29.1%2Bk3s2), all previous versions (k3s_1_26, k3s_1_27, k3s_1_28) will be removed. See [changelog and upgrade notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md#urgent-upgrade-notes) for more information. + - `himalaya` was updated to `v1.0.0-beta.3`, which introduces breaking changes. Check out the [release note](https://github.com/soywod/himalaya/releases/tag/v1.0.0-beta.3) for details. - The `power.ups` module now generates `upsd.conf`, `upsd.users` and `upsmon.conf` automatically from a set of new configuration options. This breaks compatibility with existing `power.ups` setups where these files were created manually. Back up these files before upgrading NixOS. -- `unrar` was updated to v7. See [changelog](https://www.rarlab.com/unrar7notes.htm) for more information. +- `pdns` was updated to version [v4.9.x](https://doc.powerdns.com/authoritative/changelog/4.9.html), which introduces breaking changes. Check out the [Upgrade Notes](https://doc.powerdns.com/authoritative/upgrading.html#to-4-9-0) for details. -- `k3s` was updated to [v1.29](https://github.com/k3s-io/k3s/releases/tag/v1.29.1%2Bk3s2). See [changelog and upgrade notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md#urgent-upgrade-notes) for more information. +- `unrar` was updated to v7. See [changelog](https://www.rarlab.com/unrar7notes.htm) for more information. - `k9s` was updated to v0.31. There have been various breaking changes in the config file format, check out the changelog of [v0.29](https://github.com/derailed/k9s/releases/tag/v0.29.0), @@ -150,6 +158,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - `idris2` was updated to v0.7.0. This version introduces breaking changes. Check out the [changelog](https://github.com/idris-lang/Idris2/blob/v0.7.0/CHANGELOG.md#v070) for details. +- `nvtop` family of packages was reorganized into nested attrset. `nvtop` has been renamed to `nvtopPackages.full`, and all `nvtop-{amd,nvidia,intel,msm}` packages are now named as `nvtopPackages.{amd,nvidia,intel,msm}` + - `neo4j` has been updated to 5, you may want to read the [release notes for Neo4j 5](https://neo4j.com/release-notes/database/neo4j-5/) - `services.neo4j.allowUpgrade` was removed and no longer has any effect. Neo4j 5 supports automatic rolling upgrades. @@ -167,6 +177,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - Invidious has changed its default database username from `kemal` to `invidious`. Setups involving an externally provisioned database (i.e. `services.invidious.database.createLocally == false`) should adjust their configuration accordingly. The old `kemal` user will not be removed automatically even when the database is provisioned automatically.(https://github.com/NixOS/nixpkgs/pull/265857) +- `writeReferencesToFile` is deprecated in favour of the new trivial build helper `writeClosure`. The latter accepts a list of paths and has an unambiguous name and cleaner implementation. + - `inetutils` now has a lower priority to avoid shadowing the commonly used `util-linux`. If one wishes to restore the default priority, simply use `lib.setPrio 5 inetutils` or override with `meta.priority = 5`. - `paperless`' `services.paperless.extraConfig` setting has been removed and converted to the freeform type and option named `services.paperless.settings`. @@ -320,7 +332,14 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - `addDriverRunpath` has been added to facilitate the deprecation of the old `addOpenGLRunpath` setuphook. This change is motivated by the evolution of the setuphook to include all hardware acceleration. -- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release. +- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release and could potentially [affect Xorg sessions](https://blog.linuxmint.com/?p=4639). We suggest a reboot when switching between sessions. + +- MATE has been updated to 1.28. + - To properly support panel plugins built with Wayland (in-process) support, we are introducing `services.xserver.desktopManager.mate.extraPanelApplets` option, please use that for installing panel applets. + - Similarly, please use `services.xserver.desktopManager.mate.extraCajaExtensions` option for installing Caja extensions. + - To use the Wayland session, enable `services.xserver.desktopManager.mate.enableWaylandSession`. This is opt-in for now as it is in early stage and introduces a new set of Wayfire closure. Due to [known issues with LightDM](https://github.com/canonical/lightdm/issues/63), we suggest using SDDM for display manager. + +- The Budgie module installs gnome-terminal by default (instead of mate-terminal). - New `boot.loader.systemd-boot.xbootldrMountPoint` allows setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned. @@ -347,6 +366,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - [Lilypond](https://lilypond.org/index.html) and [Denemo](https://www.denemo.org) are now compiled with Guile 3.0. +- The EC2 image module now enables the [Amazon SSM Agent](https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent.html) by default. + - The following options of the Nextcloud module were moved into [`services.nextcloud.settings`](#opt-services.nextcloud.settings) and renamed to match the name from Nextcloud's `config.php`: - `logLevel` -> [`loglevel`](#opt-services.nextcloud.settings.loglevel), - `logType` -> [`log_type`](#opt-services.nextcloud.settings.log_type), @@ -442,4 +463,7 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - QtMultimedia has changed its default backend to `QT_MEDIA_BACKEND=ffmpeg` (previously `gstreamer` on Linux or `darwin` on MacOS). The previous native backends remain available but are now minimally maintained. Refer to [upstream documentation](https://doc.qt.io/qt-6/qtmultimedia-index.html#ffmpeg-as-the-default-backend) for further details about each platform. -- The oil shell is now using the c++ version by default. The python based build is still available as `oil-python` +- The oil shell's c++ version is now available as `oils-for-unix`. The python version is still available as `oil` + +- `documentation.man.mandoc` now by default uses `MANPATH` to set the directories where mandoc will search for manual pages. + This enables mandoc to find manual pages in Nix profiles. To set the manual search paths via the `mandoc.conf` configuration file like before, use `documentation.man.mandoc.settings.manpath` instead. diff --git a/nixos/lib/make-options-doc/default.nix b/nixos/lib/make-options-doc/default.nix index 284934a7608e..09a4022845e0 100644 --- a/nixos/lib/make-options-doc/default.nix +++ b/nixos/lib/make-options-doc/default.nix @@ -1,20 +1,95 @@ -/* Generate JSON, XML and DocBook documentation for given NixOS options. +/** + Generates documentation for [nix modules](https://nix.dev/tutorials/module-system/module-system.html). - Minimal example: + It uses the declared `options` to generate documentation in various formats. - { pkgs, }: + # Outputs - let - eval = import (pkgs.path + "/nixos/lib/eval-config.nix") { - baseModules = [ - ../module.nix - ]; - modules = []; - }; - in pkgs.nixosOptionsDoc { - options = eval.options; + This function returns an attribute set with the following entries. + + ## optionsCommonMark + + Documentation in CommonMark text format. + + ## optionsJSON + + All options in a JSON format suitable for further automated processing. + + `example.json` + ```json + { + ... + "fileSystems.<name>.options": { + "declarations": ["nixos/modules/tasks/filesystems.nix"], + "default": { + "_type": "literalExpression", + "text": "[\n \"defaults\"\n]" + }, + "description": "Options used to mount the file system.", + "example": { + "_type": "literalExpression", + "text": "[\n \"data=journal\"\n]" + }, + "loc": ["fileSystems", "<name>", "options"], + "readOnly": false, + "type": "non-empty (list of string (with check: non-empty))" + "relatedPackages": "- [`pkgs.tmux`](\n https://search.nixos.org/packages?show=tmux&sort=relevance&query=tmux\n )\n", + }, + ... + } + ``` + + ## optionsDocBook + + deprecated since 23.11 and will be removed in 24.05. + + ## optionsAsciiDoc + + Documentation rendered as AsciiDoc. This is useful for e.g. man pages. + + > Note: NixOS itself uses this ouput to to build the configuration.nix man page" + + ## optionsNix + + All options as a Nix attribute set value, with the same schema as `optionsJSON`. + + # Example + + ## Example: NixOS configuration + + ```nix + let + # Evaluate a NixOS configuration + eval = import (pkgs.path + "/nixos/lib/eval-config.nix") { + # Overriden explicitly here, this would include all modules from NixOS otherwise. + # See: docs of eval-config.nix for more details + baseModules = []; + modules = [ + ./module.nix + ]; + }; + in + pkgs.nixosOptionsDoc { + inherit (eval) options; } + ``` + + ## Example: non-NixOS modules + + `nixosOptionsDoc` can also be used to build documentation for non-NixOS modules. + ```nix + let + eval = lib.evalModules { + modules = [ + ./module.nix + ]; + }; + in + pkgs.nixosOptionsDoc { + inherit (eval) options; + } + ``` */ { pkgs , lib diff --git a/nixos/lib/systemd-lib.nix b/nixos/lib/systemd-lib.nix index ef218e674ebf..c00b2d0f207c 100644 --- a/nixos/lib/systemd-lib.nix +++ b/nixos/lib/systemd-lib.nix @@ -73,13 +73,26 @@ in rec { optional (attr ? ${name} && (! isMacAddress attr.${name} && attr.${name} != "none")) "Systemd ${group} field `${name}` must be a valid MAC address or the special value `none`."; - + isNumberOrRangeOf = check: v: + if isInt v + then check v + else let + parts = splitString "-" v; + lower = toIntBase10 (head parts); + upper = if tail parts != [] then toIntBase10 (head (tail parts)) else lower; + in + length parts <= 2 && lower <= upper && check lower && check upper; isPort = i: i >= 0 && i <= 65535; + isPortOrPortRange = isNumberOrRangeOf isPort; assertPort = name: group: attr: optional (attr ? ${name} && ! isPort attr.${name}) "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number."; + assertPortOrPortRange = name: group: attr: + optional (attr ? ${name} && ! isPortOrPortRange attr.${name}) + "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number or range of port numbers."; + assertValueOneOf = name: values: group: attr: optional (attr ? ${name} && !elem attr.${name} values) "Systemd ${group} field `${name}' cannot have value `${toString attr.${name}}'."; diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix index 49ba2e5c8386..22a2c79843c6 100644 --- a/nixos/lib/utils.nix +++ b/nixos/lib/utils.nix @@ -64,8 +64,8 @@ rec { let s = if builtins.isPath arg then "${arg}" else if builtins.isString arg then arg - else if builtins.isInt arg || builtins.isFloat arg then toString arg - else throw "escapeSystemdExecArg only allows strings, paths and numbers"; + else if builtins.isInt arg || builtins.isFloat arg || lib.isDerivation arg then toString arg + else throw "escapeSystemdExecArg only allows strings, paths, numbers and derivations"; in replaceStrings [ "%" "$" ] [ "%%" "$$" ] (builtins.toJSON s); diff --git a/nixos/modules/config/nix.nix b/nixos/modules/config/nix.nix index e6a74bbb73fc..a40953a3a3c9 100644 --- a/nixos/modules/config/nix.nix +++ b/nixos/modules/config/nix.nix @@ -14,8 +14,10 @@ let concatStringsSep boolToString escape + filterAttrs floatToString getVersion + hasPrefix isBool isDerivation isFloat @@ -95,14 +97,19 @@ let mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs); + isExtra = key: hasPrefix "extra-" key; + in pkgs.writeTextFile { name = "nix.conf"; + # workaround for https://github.com/NixOS/nix/issues/9487 + # extra-* settings must come after their non-extra counterpart text = '' # WARNING: this file is generated from the nix.* options in # your NixOS configuration, typically # /etc/nixos/configuration.nix. Do not edit it! - ${mkKeyValuePairs cfg.settings} + ${mkKeyValuePairs (filterAttrs (key: value: !(isExtra key)) cfg.settings)} + ${mkKeyValuePairs (filterAttrs (key: value: isExtra key) cfg.settings)} ${cfg.extraOptions} ''; checkPhase = lib.optionalString cfg.checkConfig ( @@ -345,7 +352,7 @@ in show-trace = true; system-features = [ "big-parallel" "kvm" "recursive-nix" ]; - sandbox-paths = { "/bin/sh" = "''${pkgs.busybox-sandbox-shell.out}/bin/busybox"; }; + sandbox-paths = [ "/bin/sh=''${pkgs.busybox-sandbox-shell.out}/bin/busybox" ]; } ''; description = lib.mdDoc '' diff --git a/nixos/modules/config/resolvconf.nix b/nixos/modules/config/resolvconf.nix index e9ae4d651d26..3b8cc0cb8f42 100644 --- a/nixos/modules/config/resolvconf.nix +++ b/nixos/modules/config/resolvconf.nix @@ -28,6 +28,8 @@ let '' + optionalString cfg.useLocalResolver '' # This hosts runs a full-blown DNS resolver. name_servers='127.0.0.1' + '' + optionalString (cfg.useLocalResolver && config.networking.enableIPv6) '' + name_servers='::1' '' + cfg.extraConfig; in diff --git a/nixos/modules/hardware/video/webcam/ipu6.nix b/nixos/modules/hardware/video/webcam/ipu6.nix index c2dbdc217bd6..a7767e446bd4 100644 --- a/nixos/modules/hardware/video/webcam/ipu6.nix +++ b/nixos/modules/hardware/video/webcam/ipu6.nix @@ -30,7 +30,10 @@ in ipu6-drivers ]; - hardware.firmware = [ pkgs.ipu6-camera-bins ]; + hardware.firmware = with pkgs; [ + ipu6-camera-bins + ivsc-firmware + ]; services.udev.extraRules = '' SUBSYSTEM=="intel-ipu6-psys", MODE="0660", GROUP="video" diff --git a/nixos/modules/i18n/input-method/fcitx5.nix b/nixos/modules/i18n/input-method/fcitx5.nix index ee8d2652b1c7..755336220520 100644 --- a/nixos/modules/i18n/input-method/fcitx5.nix +++ b/nixos/modules/i18n/input-method/fcitx5.nix @@ -32,8 +32,8 @@ in }; plasma6Support = mkOption { type = types.bool; - default = config.services.xserver.desktopManager.plasma6.enable; - defaultText = literalExpression "config.services.xserver.desktopManager.plasma6.enable"; + default = config.services.desktopManager.plasma6.enable; + defaultText = literalExpression "config.services.desktopManager.plasma6.enable"; description = lib.mdDoc '' Use qt6 versions of fcitx5 packages. Required for configuring fcitx5 in KDE System Settings. diff --git a/nixos/modules/image/repart-image.nix b/nixos/modules/image/repart-image.nix index 5ae523c43f58..83e766268cf0 100644 --- a/nixos/modules/image/repart-image.nix +++ b/nixos/modules/image/repart-image.nix @@ -2,8 +2,8 @@ # NixOS module that can be imported. { lib +, stdenvNoCC , runCommand -, runCommandLocal , python3 , black , ruff @@ -26,15 +26,18 @@ , xz # arguments +, name +, version , imageFileBasename , compression , fileSystems -, partitions +, partitionsJSON , split , seed , definitionsDirectory , sectorSize , mkfsEnv ? {} +, createEmpty ? true }: let @@ -52,11 +55,6 @@ let mypy --strict $out ''; - amendedRepartDefinitions = runCommandLocal "amended-repart.d" {} '' - definitions=$(${amendRepartDefinitions} ${partitions} ${definitionsDirectory}) - cp -r $definitions $out - ''; - fileSystemToolMapping = { "vfat" = [ dosfstools mtools ]; "ext4" = [ e2fsprogs.bin ]; @@ -78,53 +76,88 @@ let "xz" = "xz --keep --verbose --threads=0 -${toString compression.level}"; }."${compression.algorithm}"; in - -runCommand imageFileBasename -{ + stdenvNoCC.mkDerivation (finalAttrs: + (if (version != null) + then { pname = name; inherit version; } + else { inherit name; } + ) // { __structuredAttrs = true; nativeBuildInputs = [ systemd fakeroot util-linux + ] ++ lib.optionals (compression.enable) [ compressionPkg ] ++ fileSystemTools; env = mkfsEnv; + inherit partitionsJSON definitionsDirectory; + + # relative path to the repart definitions that are read by systemd-repart + finalRepartDefinitions = "repart.d"; + systemdRepartFlags = [ "--dry-run=no" - "--empty=create" "--size=auto" "--seed=${seed}" - "--definitions=${amendedRepartDefinitions}" + "--definitions=${finalAttrs.finalRepartDefinitions}" "--split=${lib.boolToString split}" "--json=pretty" + ] ++ lib.optionals createEmpty [ + "--empty=create" ] ++ lib.optionals (sectorSize != null) [ "--sector-size=${toString sectorSize}" ]; - passthru = { - inherit amendRepartDefinitions amendedRepartDefinitions; - }; -} '' - mkdir -p $out - cd $out + dontUnpack = true; + dontConfigure = true; + doCheck = false; + + patchPhase = '' + runHook prePatch + + amendedRepartDefinitionsDir=$(${amendRepartDefinitions} $partitionsJSON $definitionsDirectory) + ln -vs $amendedRepartDefinitionsDir $finalRepartDefinitions - echo "Building image with systemd-repart..." - unshare --map-root-user fakeroot systemd-repart \ - ''${systemdRepartFlags[@]} \ - ${imageFileBasename}.raw \ - | tee repart-output.json + runHook postPatch + ''; + + buildPhase = '' + runHook preBuild + + echo "Building image with systemd-repart..." + unshare --map-root-user fakeroot systemd-repart \ + ''${systemdRepartFlags[@]} \ + ${imageFileBasename}.raw \ + | tee repart-output.json + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out + '' # Compression is implemented in the same derivation as opposed to in a # separate derivation to allow users to save disk space. Disk images are # already very space intensive so we want to allow users to mitigate this. - if ${lib.boolToString compression.enable}; then + + lib.optionalString compression.enable + '' for f in ${imageFileBasename}*; do echo "Compressing $f with ${compression.algorithm}..." # Keep the original file when compressing and only delete it afterwards ${compressionCommand} $f && rm $f done - fi -'' + '' + '' + mv -v repart-output.json ${imageFileBasename}* $out + + runHook postInstall + ''; + + passthru = { + inherit amendRepartDefinitions; + }; +}) diff --git a/nixos/modules/image/repart.nix b/nixos/modules/image/repart.nix index 90c9c7e51dfa..1a43297f4b43 100644 --- a/nixos/modules/image/repart.nix +++ b/nixos/modules/image/repart.nix @@ -211,6 +211,15 @@ in ''; }; + finalPartitions = lib.mkOption { + type = lib.types.attrs; + internal = true; + readOnly = true; + description = lib.mdDoc '' + Convenience option to access partitions with added closures. + ''; + }; + }; config = { @@ -224,6 +233,16 @@ in "zstd" = ".zst"; "xz" = ".xz"; }."${cfg.compression.algorithm}"; + + makeClosure = paths: pkgs.closureInfo { rootPaths = paths; }; + + # Add the closure of the provided Nix store paths to cfg.partitions so + # that amend-repart-definitions.py can read it. + addClosure = _name: partitionConfig: partitionConfig // ( + lib.optionalAttrs + (partitionConfig.storePaths or [ ] != [ ]) + { closure = "${makeClosure partitionConfig.storePaths}/store-paths"; } + ); in { name = lib.mkIf (config.system.image.id != null) (lib.mkOptionDefault config.system.image.id); @@ -239,6 +258,8 @@ in "xz" = 3; }."${cfg.compression.algorithm}"; }; + + finalPartitions = lib.mapAttrs addClosure cfg.partitions; }; system.build.image = @@ -247,36 +268,25 @@ in (f: f != null) (lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions); - makeClosure = paths: pkgs.closureInfo { rootPaths = paths; }; - - # Add the closure of the provided Nix store paths to cfg.partitions so - # that amend-repart-definitions.py can read it. - addClosure = _name: partitionConfig: partitionConfig // ( - lib.optionalAttrs - (partitionConfig.storePaths or [ ] != [ ]) - { closure = "${makeClosure partitionConfig.storePaths}/store-paths"; } - ); - - finalPartitions = lib.mapAttrs addClosure cfg.partitions; format = pkgs.formats.ini { }; definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format - (lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) finalPartitions); + (lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions); - partitions = pkgs.writeText "partitions.json" (builtins.toJSON finalPartitions); + partitionsJSON = pkgs.writeText "partitions.json" (builtins.toJSON cfg.finalPartitions); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; in pkgs.callPackage ./repart-image.nix { systemd = cfg.package; - inherit (cfg) imageFileBasename compression split seed sectorSize; - inherit fileSystems definitionsDirectory partitions mkfsEnv; + inherit (cfg) name version imageFileBasename compression split seed sectorSize; + inherit fileSystems definitionsDirectory partitionsJSON mkfsEnv; }; - meta.maintainers = with lib.maintainers; [ nikstur ]; + meta.maintainers = with lib.maintainers; [ nikstur willibutz ]; }; } diff --git a/nixos/modules/misc/mandoc.nix b/nixos/modules/misc/mandoc.nix index 73646a60aabb..706e2ac2c283 100644 --- a/nixos/modules/misc/mandoc.nix +++ b/nixos/modules/misc/mandoc.nix @@ -17,6 +17,8 @@ let ) output ); + + makeLeadingSlashes = map (path: if builtins.substring 0 1 path != "/" then "/${path}" else path); in { meta.maintainers = [ lib.maintainers.sternenseemann ]; @@ -29,6 +31,7 @@ in type = with lib.types; listOf str; default = [ "share/man" ]; example = lib.literalExpression "[ \"share/man\" \"share/man/fr\" ]"; + apply = makeLeadingSlashes; description = '' Change the paths included in the MANPATH environment variable, i. e. the directories where {manpage}`man(1)` @@ -41,6 +44,28 @@ in ''; }; + cachePath = lib.mkOption { + type = with lib.types; listOf str; + default = cfg.manPath; + defaultText = lib.literalExpression "config.documentation.man.mandoc.manPath"; + example = lib.literalExpression "[ \"share/man\" \"share/man/fr\" ]"; + apply = makeLeadingSlashes; + description = '' + Change the paths where mandoc {manpage}`makewhatis(8)`generates the + manual page index caches. {option}`documentation.man.generateCaches` + should be enabled to allow cache generation. This list should only + include the paths to manpages installed in the system configuration, + i. e. /run/current-system/sw/share/man. {manpage}`makewhatis(8)` + creates a database in each directory using the files + `mansection/[arch/]title.section` and `catsection/[arch/]title.0` + in it. If a directory contains no manual pages, no database is + created in that directory. + This option only needs to be set manually if extra paths should be + indexed or {option}`documentation.man.manPath` contains paths that + can't be indexed. + ''; + }; + package = lib.mkOption { type = lib.types.package; default = pkgs.mandoc; @@ -178,19 +203,14 @@ in # TODO(@sternenseemman): fix symlinked directories not getting indexed, # see: https://inbox.vuxu.org/mandoc-tech/20210906171231.GF83680@athene.usta.de/T/#e85f773c1781e3fef85562b2794f9cad7b2909a3c extraSetup = lib.mkIf config.documentation.man.generateCaches '' - for man_path in ${ - lib.concatMapStringsSep " " (path: - "$out/" + lib.escapeShellArg path - ) cfg.manPath} ${lib.concatMapStringsSep " " (path: - lib.escapeShellArg path) cfg.settings.manpath - } + for man_path in ${lib.concatMapStringsSep " " (path: "$out" + lib.escapeShellArg path) cfg.cachePath} do [[ -d "$man_path" ]] && ${makewhatis} -T utf8 $man_path done ''; # tell mandoc the paths containing man pages - profileRelativeSessionVariables."MANPATH" = map (path: if builtins.substring 0 1 path != "/" then "/${path}" else path) cfg.manPath; + profileRelativeSessionVariables."MANPATH" = lib.mkIf (cfg.manPath != [ ]) cfg.manPath; }; }; } diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 41e369ac1c65..d17e638a0883 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -203,6 +203,7 @@ ./programs/i3lock.nix ./programs/iotop.nix ./programs/java.nix + ./programs/joycond-cemuhook.nix ./programs/k3b.nix ./programs/k40-whisperer.nix ./programs/kbdlight.nix @@ -1018,6 +1019,7 @@ ./services/networking/lxd-image-server.nix ./services/networking/magic-wormhole-mailbox-server.nix ./services/networking/matterbridge.nix + ./services/networking/mihomo.nix ./services/networking/minidlna.nix ./services/networking/miniupnpd.nix ./services/networking/miredo.nix @@ -1034,6 +1036,7 @@ ./services/networking/multipath.nix ./services/networking/murmur.nix ./services/networking/mxisd.nix + ./services/networking/mycelium.nix ./services/networking/namecoind.nix ./services/networking/nar-serve.nix ./services/networking/nat.nix @@ -1358,6 +1361,7 @@ ./services/web-apps/plausible.nix ./services/web-apps/powerdns-admin.nix ./services/web-apps/pretalx.nix + ./services/web-apps/pretix.nix ./services/web-apps/prosody-filer.nix ./services/web-apps/rimgo.nix ./services/web-apps/sftpgo.nix diff --git a/nixos/modules/programs/_1password-gui.nix b/nixos/modules/programs/_1password-gui.nix index 83ef6037fb5a..eb2effee4326 100644 --- a/nixos/modules/programs/_1password-gui.nix +++ b/nixos/modules/programs/_1password-gui.nix @@ -51,14 +51,6 @@ in setuid = false; setgid = true; }; - - "1Password-KeyringHelper" = { - source = "${package}/share/1password/1Password-KeyringHelper"; - owner = "root"; - group = "onepassword"; - setuid = true; - setgid = true; - }; }; }; diff --git a/nixos/modules/programs/starship.nix b/nixos/modules/programs/starship.nix index 34f6f0882c61..7f8d9eb3363d 100644 --- a/nixos/modules/programs/starship.nix +++ b/nixos/modules/programs/starship.nix @@ -12,7 +12,7 @@ let nativeBuildInputs = [ pkgs.yq ]; } '' tomlq -s -t 'reduce .[] as $item ({}; . * $item)' \ - ${lib.concatStringsSep " " (map (f: "${pkgs.starship}/share/starship/presets/${f}.toml") cfg.presets)} \ + ${lib.concatStringsSep " " (map (f: "${cfg.package}/share/starship/presets/${f}.toml") cfg.presets)} \ ${userSettingsFile} \ > $out ''; @@ -26,23 +26,20 @@ let in { options.programs.starship = { - enable = lib.mkEnableOption (lib.mdDoc "the Starship shell prompt"); + enable = lib.mkEnableOption "the Starship shell prompt"; - interactiveOnly = lib.mkOption { - default = true; - example = false; - type = lib.types.bool; - description = lib.mdDoc '' - Whether to enable starship only when the shell is interactive. - Some plugins require this to be set to false to function correctly. - ''; - }; + package = lib.mkPackageOption pkgs "starship" { }; + + interactiveOnly = lib.mkEnableOption '' + starship only when the shell is interactive. + Some plugins require this to be set to false to function correctly + '' // { default = true; }; presets = lib.mkOption { default = [ ]; example = [ "nerd-font-symbols" ]; type = with lib.types; listOf str; - description = lib.mdDoc '' + description = '' Presets files to be merged with settings in order. ''; }; @@ -50,7 +47,7 @@ in settings = lib.mkOption { inherit (settingsFormat) type; default = { }; - description = lib.mdDoc '' + description = '' Configuration included in `starship.toml`. See https://starship.rs/config/#prompt for documentation. @@ -68,7 +65,7 @@ in if [[ ! -f "$HOME/.config/starship.toml" ]]; then export STARSHIP_CONFIG=${settingsFile} fi - eval "$(${pkgs.starship}/bin/starship init bash)" + eval "$(${cfg.package}/bin/starship init bash)" fi ''; @@ -81,7 +78,7 @@ in if not test -f "$HOME/.config/starship.toml"; set -x STARSHIP_CONFIG ${settingsFile} end - eval (${pkgs.starship}/bin/starship init fish) + eval (${cfg.package}/bin/starship init fish) end ''; @@ -94,7 +91,7 @@ in if [[ ! -f "$HOME/.config/starship.toml" ]]; then export STARSHIP_CONFIG=${settingsFile} fi - eval "$(${pkgs.starship}/bin/starship init zsh)" + eval "$(${cfg.package}/bin/starship init zsh)" fi ''; }; diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix index 31803f061dce..c93a34f61849 100644 --- a/nixos/modules/programs/steam.nix +++ b/nixos/modules/programs/steam.nix @@ -44,8 +44,8 @@ in { ''; apply = steam: steam.override (prev: { extraEnv = (lib.optionalAttrs (cfg.extraCompatPackages != [ ]) { - STEAM_EXTRA_COMPAT_TOOLS_PATHS = makeBinPath cfg.extraCompatPackages; - }) // (prev.extraEnv or {}); + STEAM_EXTRA_COMPAT_TOOLS_PATHS = makeSearchPathOutput "steamcompattool" "" cfg.extraCompatPackages; + }) // (prev.extraEnv or {}); extraLibraries = pkgs: let prevLibs = if prev ? extraLibraries then prev.extraLibraries pkgs else [ ]; additionalLibs = with config.hardware.opengl; @@ -74,10 +74,17 @@ in { extraCompatPackages = mkOption { type = types.listOf types.package; default = [ ]; + example = literalExpression '' + with pkgs; [ + proton-ge-bin + ] + ''; description = lib.mdDoc '' Extra packages to be used as compatibility tools for Steam on Linux. Packages will be included in the `STEAM_EXTRA_COMPAT_TOOLS_PATHS` environmental variable. For more information see - <https://github.com/ValveSoftware/steam-for-linux/issues/6310">. + https://github.com/ValveSoftware/steam-for-linux/issues/6310. + + These packages must be Steam compatibility tools that have a `steamcompattool` output. ''; }; diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 560e5eff5c39..26dc724ae159 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -683,7 +683,7 @@ let (let dp9ik = config.security.pam.dp9ik; in { name = "p9"; enable = dp9ik.enable; control = dp9ik.control; modulePath = "${pkgs.pam_dp9ik}/lib/security/pam_p9.so"; args = [ dp9ik.authserver ]; }) - { name = "fprintd"; enable = cfg.fprintAuth; control = "sufficient"; modulePath = "${pkgs.fprintd}/lib/security/pam_fprintd.so"; } + { name = "fprintd"; enable = cfg.fprintAuth; control = "sufficient"; modulePath = "${config.services.fprintd.package}/lib/security/pam_fprintd.so"; } ] ++ # Modules in this block require having the password set in PAM_AUTHTOK. # pam_unix is marked as 'sufficient' on NixOS which means nothing will run diff --git a/nixos/modules/services/audio/spotifyd.nix b/nixos/modules/services/audio/spotifyd.nix index 1194b6f200d7..04bb523e25b1 100644 --- a/nixos/modules/services/audio/spotifyd.nix +++ b/nixos/modules/services/audio/spotifyd.nix @@ -24,7 +24,7 @@ in type = types.lines; description = lib.mdDoc '' (Deprecated) Configuration for Spotifyd. For syntax and directives, see - <https://github.com/Spotifyd/spotifyd#Configuration>. + <https://docs.spotifyd.rs/config/File.html>. ''; }; @@ -34,7 +34,7 @@ in example = { global.bitrate = 320; }; description = lib.mdDoc '' Configuration for Spotifyd. For syntax and directives, see - <https://github.com/Spotifyd/spotifyd#Configuration>. + <https://docs.spotifyd.rs/config/File.html>. ''; }; }; diff --git a/nixos/modules/services/databases/postgresql.md b/nixos/modules/services/databases/postgresql.md index 7d141f12b5de..3ff1f00fa9cf 100644 --- a/nixos/modules/services/databases/postgresql.md +++ b/nixos/modules/services/databases/postgresql.md @@ -277,7 +277,7 @@ self: super: { Here's a recipe on how to override a particular plugin through an overlay: ``` self: super: { - postgresql_15 = super.postgresql_15.override { this = self.postgresql_15; } // { + postgresql_15 = super.postgresql_15// { pkgs = super.postgresql_15.pkgs // { pg_repack = super.postgresql_15.pkgs.pg_repack.overrideAttrs (_: { name = "pg_repack-v20181024"; diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index c4e76c82ba5c..c3f3b98ae5e7 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -14,7 +14,7 @@ let # package = pkgs.postgresql_<major>; # }; # works. - base = if cfg.enableJIT && !cfg.package.jitSupport then cfg.package.withJIT else cfg.package; + base = if cfg.enableJIT then cfg.package.withJIT else cfg.package; in if cfg.extraPlugins == [] then base diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix index 1710d28954d6..e20b431f0b58 100644 --- a/nixos/modules/services/desktop-managers/plasma6.nix +++ b/nixos/modules/services/desktop-managers/plasma6.nix @@ -170,6 +170,7 @@ in { breeze.qt5 plasma-integration.qt5 pkgs.plasma5Packages.kwayland-integration + pkgs.plasma5Packages.kio kio-extras-kf5 ] # Optional hardware support features @@ -215,7 +216,7 @@ in { serif = ["Noto Serif"]; }; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt; + programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt; programs.ssh.askPassword = mkDefault "${kdePackages.ksshaskpass.out}/bin/ksshaskpass"; # Enable helpful DBus services. @@ -252,6 +253,7 @@ in { services.xserver.displayManager.sddm = { package = kdePackages.sddm; theme = mkDefault "breeze"; + wayland.compositor = "kwin"; extraPackages = with kdePackages; [ breeze-icons kirigami diff --git a/nixos/modules/services/desktops/pipewire/pipewire.nix b/nixos/modules/services/desktops/pipewire/pipewire.nix index 09448833620c..182615cd4d6c 100644 --- a/nixos/modules/services/desktops/pipewire/pipewire.nix +++ b/nixos/modules/services/desktops/pipewire/pipewire.nix @@ -95,6 +95,14 @@ in { enable = mkEnableOption (lib.mdDoc "JACK audio emulation"); }; + raopOpenFirewall = mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Opens UDP/6001-6002, required by RAOP/Airplay for timing and control data. + ''; + }; + pulse = { enable = mkEnableOption (lib.mdDoc "PulseAudio server emulation"); }; @@ -371,6 +379,8 @@ in { environment.sessionVariables.LD_LIBRARY_PATH = lib.mkIf cfg.jack.enable [ "${cfg.package.jack}/lib" ]; + networking.firewall.allowedUDPPorts = lib.mkIf cfg.raopOpenFirewall [ 6001 6002 ]; + users = lib.mkIf cfg.systemWide { users.pipewire = { uid = config.ids.uids.pipewire; diff --git a/nixos/modules/services/desktops/pipewire/wireplumber.nix b/nixos/modules/services/desktops/pipewire/wireplumber.nix index 009d68bd4f28..de177d0e4ef3 100644 --- a/nixos/modules/services/desktops/pipewire/wireplumber.nix +++ b/nixos/modules/services/desktops/pipewire/wireplumber.nix @@ -56,24 +56,30 @@ in config = let - pwNotForAudioConfigPkg = pkgs.writeTextDir "share/wireplumber/main.lua.d/80-pw-not-for-audio.lua" '' - -- PipeWire is not used for audio, so prevent it from grabbing audio devices - alsa_monitor.enable = function() end - ''; - systemwideConfigPkg = pkgs.writeTextDir "share/wireplumber/main.lua.d/80-systemwide.lua" '' - -- When running system-wide, these settings need to be disabled (they - -- use functions that aren't available on the system dbus). - alsa_monitor.properties["alsa.reserve"] = false - default_access.properties["enable-flatpak-portal"] = false + pwNotForAudioConfigPkg = pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/90-nixos-no-audio.conf" '' + # PipeWire is not used for audio, so WirePlumber should not be handling it + wireplumber.profiles = { + main = { + hardware.audio = disabled + hardware.bluetooth = disabled + } + } ''; - systemwideBluetoothConfigPkg = pkgs.writeTextDir "share/wireplumber/bluetooth.lua.d/80-systemwide.lua" '' - -- When running system-wide, logind-integration needs to be disabled. - bluez_monitor.properties["with-logind"] = false + + systemwideConfigPkg = pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/90-nixos-systemwide.conf" '' + # When running system-wide, we don't have logind to call ReserveDevice, + # And bluetooth logind integration needs to be disabled + wireplumber.profiles = { + main = { + support.reserve-device = disabled + monitor.bluez.seat-monitoring = disabled + } + } ''; configPackages = cfg.configPackages ++ lib.optional (!pwUsedForAudio) pwNotForAudioConfigPkg - ++ lib.optionals config.services.pipewire.systemWide [ systemwideConfigPkg systemwideBluetoothConfigPkg ]; + ++ lib.optional config.services.pipewire.systemWide systemwideConfigPkg; configs = pkgs.buildEnv { name = "wireplumber-configs"; diff --git a/nixos/modules/services/display-managers/greetd.nix b/nixos/modules/services/display-managers/greetd.nix index c2d345152de9..5ce67c3fb3fd 100644 --- a/nixos/modules/services/display-managers/greetd.nix +++ b/nixos/modules/services/display-managers/greetd.nix @@ -61,6 +61,8 @@ in systemd.services."autovt@${tty}".enable = false; systemd.services.greetd = { + aliases = [ "display-manager.service" ]; + unitConfig = { Wants = [ "systemd-user-sessions.service" diff --git a/nixos/modules/services/matrix/synapse.nix b/nixos/modules/services/matrix/synapse.nix index e3f9c7742cc7..7291c0fcbcdd 100644 --- a/nixos/modules/services/matrix/synapse.nix +++ b/nixos/modules/services/matrix/synapse.nix @@ -1232,7 +1232,8 @@ in { ProtectKernelTunables = true; ProtectProc = "invisible"; ProtectSystem = "strict"; - ReadWritePaths = [ cfg.dataDir cfg.settings.media_store_path ]; + ReadWritePaths = [ cfg.dataDir cfg.settings.media_store_path ] ++ + (map (listener: dirOf listener.path) (filter (listener: listener.path != null) cfg.settings.listeners)); RemoveIPC = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; RestrictNamespaces = true; diff --git a/nixos/modules/services/misc/etebase-server.nix b/nixos/modules/services/misc/etebase-server.nix index f5a5e8a780d4..6ec3807f0fb2 100644 --- a/nixos/modules/services/misc/etebase-server.nix +++ b/nixos/modules/services/misc/etebase-server.nix @@ -177,6 +177,8 @@ in systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" + ] ++ lib.optionals (cfg.unixSocket != null) [ + "d '${builtins.dirOf cfg.unixSocket}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" ]; systemd.services.etebase-server = { diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index ec347a75f063..e95ab0a112bc 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -1439,6 +1439,8 @@ in { nodejs gnupg + "${cfg.packages.gitlab}/share/gitlab/vendor/gems/sidekiq-${cfg.packages.gitlab.rubyEnv.gems.sidekiq.version}" + # Needed for GitLab project imports gnutar gzip @@ -1452,7 +1454,12 @@ in { TimeoutSec = "infinity"; Restart = "always"; WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab"; - ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production"; + ExecStart = utils.escapeSystemdExecArgs [ + "${cfg.packages.gitlab}/share/gitlab/bin/sidekiq-cluster" + "-e" "production" + "-r" "." + "*" # all queue groups + ]; }; }; @@ -1550,7 +1557,7 @@ in { gnutar gzip openssh - gitlab-workhorse + cfg.packages.gitlab-workhorse ]; serviceConfig = { Type = "simple"; diff --git a/nixos/modules/services/misc/llama-cpp.nix b/nixos/modules/services/misc/llama-cpp.nix index 4d76456fb2fd..305d4538e89a 100644 --- a/nixos/modules/services/misc/llama-cpp.nix +++ b/nixos/modules/services/misc/llama-cpp.nix @@ -56,7 +56,7 @@ in { serviceConfig = { Type = "idle"; KillSignal = "SIGINT"; - ExecStart = "${cfg.package}/bin/llama-cpp-server --log-disable --host ${cfg.host} --port ${builtins.toString cfg.port} -m ${cfg.model} ${utils.escapeSystemdExecArgs cfg.extraFlags}"; + ExecStart = "${cfg.package}/bin/llama-server --log-disable --host ${cfg.host} --port ${builtins.toString cfg.port} -m ${cfg.model} ${utils.escapeSystemdExecArgs cfg.extraFlags}"; Restart = "on-failure"; RestartSec = 300; diff --git a/nixos/modules/services/misc/ollama.nix b/nixos/modules/services/misc/ollama.nix index 3ac3beb4de07..7a5661510e25 100644 --- a/nixos/modules/services/misc/ollama.nix +++ b/nixos/modules/services/misc/ollama.nix @@ -13,48 +13,60 @@ in { options = { services.ollama = { - enable = lib.mkEnableOption ( - lib.mdDoc "Server for local large language models" - ); + enable = lib.mkEnableOption "ollama server for local large language models"; + package = lib.mkPackageOption pkgs "ollama" { }; listenAddress = lib.mkOption { type = types.str; default = "127.0.0.1:11434"; - description = lib.mdDoc '' - Specifies the bind address on which the ollama server HTTP interface listens. + example = "0.0.0.0:11111"; + description = '' + The address which the ollama server HTTP interface binds and listens to. ''; }; acceleration = lib.mkOption { type = types.nullOr (types.enum [ "rocm" "cuda" ]); default = null; example = "rocm"; - description = lib.mdDoc '' - Specifies the interface to use for hardware acceleration. + description = '' + What interface to use for hardware acceleration. - `rocm`: supported by modern AMD GPUs - `cuda`: supported by modern NVIDIA GPUs ''; }; - package = lib.mkPackageOption pkgs "ollama" { }; + environmentVariables = lib.mkOption { + type = types.attrsOf types.str; + default = { }; + example = { + HOME = "/tmp"; + OLLAMA_LLM_LIBRARY = "cpu"; + }; + description = '' + Set arbitrary environment variables for the ollama service. + + Be aware that these are only seen by the ollama server (systemd service), + not normal invocations like `ollama run`. + Since `ollama run` is mostly a shell around the ollama server, this is usually sufficient. + ''; + }; }; }; config = lib.mkIf cfg.enable { - systemd = { - services.ollama = { - wantedBy = [ "multi-user.target" ]; - description = "Server for local large language models"; - after = [ "network.target" ]; - environment = { - HOME = "%S/ollama"; - OLLAMA_MODELS = "%S/ollama/models"; - OLLAMA_HOST = cfg.listenAddress; - }; - serviceConfig = { - ExecStart = "${lib.getExe ollamaPackage} serve"; - WorkingDirectory = "/var/lib/ollama"; - StateDirectory = [ "ollama" ]; - DynamicUser = true; - }; + systemd.services.ollama = { + description = "Server for local large language models"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + environment = cfg.environmentVariables // { + HOME = "%S/ollama"; + OLLAMA_MODELS = "%S/ollama/models"; + OLLAMA_HOST = cfg.listenAddress; + }; + serviceConfig = { + ExecStart = "${lib.getExe ollamaPackage} serve"; + WorkingDirectory = "%S/ollama"; + StateDirectory = [ "ollama" ]; + DynamicUser = true; }; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 6be6ba7edf72..8c5ec2992eda 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, options, ... }: +{ config, pkgs, lib, options, utils, ... }: let inherit (lib) concatStrings foldl foldl' genAttrs literalExpression maintainers @@ -35,6 +35,7 @@ let "dovecot" "fastly" "flow" + "fritz" "fritzbox" "graphite" "idrac" @@ -94,10 +95,10 @@ let "zfs" ] (name: - import (./. + "/exporters/${name}.nix") { inherit config lib pkgs options; } + import (./. + "/exporters/${name}.nix") { inherit config lib pkgs options utils; } )) // (mapAttrs (name: params: - import (./. + "/exporters/${params.name}.nix") { inherit config lib pkgs options; type = params.type ; }) + import (./. + "/exporters/${params.name}.nix") { inherit config lib pkgs options utils; type = params.type ; }) { exportarr-bazarr = { name = "exportarr"; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix b/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix index a8a9f84ea8ea..de6cda18bc37 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix b/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix index bc67fe59b3b8..b3afdb596686 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bind.nix b/nixos/modules/services/monitoring/prometheus/exporters/bind.nix index bd2003f06504..100446c1a4eb 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/bind.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/bind.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bird.nix b/nixos/modules/services/monitoring/prometheus/exporters/bird.nix index 5f6c36f4c567..fc52135e3b45 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/bird.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/bird.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix index 330d54126448..45f00a04a86c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix index ce2c391de523..e8399e1bec80 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix b/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix index 0515b72b13f9..6bfadc3b7632 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix index f67596f05a3a..3b2b123bbd07 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix index 437cece588a7..a4a917b473ce 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix index ece42a34cb06..4cfee7c54a41 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/domain.nix b/nixos/modules/services/monitoring/prometheus/exporters/domain.nix index 61e2fc80afde..b2c8e6664c0f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/domain.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/domain.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix index 6fb438353a4c..df6b1ef3200c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix b/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix index 8511abbee1bd..c632b0290262 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/exportarr.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options, type }: +{ config, lib, pkgs, options, type, ... }: let cfg = config.services.prometheus.exporters."exportarr-${type}"; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix b/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix index 2a8b7fc0818d..097ea3959478 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix @@ -2,6 +2,7 @@ , lib , pkgs , options +, ... }: let diff --git a/nixos/modules/services/monitoring/prometheus/exporters/flow.nix b/nixos/modules/services/monitoring/prometheus/exporters/flow.nix index 81099aaf1704..42292abeada2 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/flow.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/flow.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fritz.nix b/nixos/modules/services/monitoring/prometheus/exporters/fritz.nix new file mode 100644 index 000000000000..c3a962b576a5 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/fritz.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, utils, ... }: +let + inherit (lib) mkOption types mdDoc; + cfg = config.services.prometheus.exporters.fritz; + yaml = pkgs.formats.yaml { }; + configFile = yaml.generate "fritz-exporter.yaml" cfg.settings; +in +{ + port = 9787; + + extraOpts = { + settings = mkOption { + description = mdDoc "Configuration settings for fritz-exporter."; + type = types.submodule { + freeformType = yaml.type; + + options = { + # Pull existing port option into config file. + port = mkOption { + type = types.port; + default = cfg.port; + internal = true; + visible = false; + }; + # Pull existing listen address option into config file. + listen_address = mkOption { + type = types.str; + default = cfg.listenAddress; + internal = true; + visible = false; + }; + log_level = mkOption { + type = types.enum [ "DEBUG" "INFO" "WARNING" "ERROR" "CRITICAL" ]; + default = "INFO"; + description = mdDoc '' + Log level to use for the exporter. + ''; + }; + devices = mkOption { + default = []; + description = "Fritz!-devices to monitor using the exporter."; + type = with types; listOf (submodule { + freeformType = yaml.type; + + options = { + name = mkOption { + type = types.str; + default = ""; + description = mdDoc '' + Name to use for the device. + ''; + }; + hostname = mkOption { + type = types.str; + default = "fritz.box"; + description = mdDoc '' + Hostname under which the target device is reachable. + ''; + }; + username = mkOption { + type = types.str; + description = mdDoc '' + Username to authenticate with the target device. + ''; + }; + password_file = mkOption { + type = types.path; + description = mdDoc '' + Path to a file which contains the password to authenticate with the target device. + Needs to be readable by the user the exporter runs under. + ''; + }; + host_info = mkOption { + type = types.bool; + description = mdDoc '' + Enable extended host info for this device. *Warning*: This will heavily increase scrape time. + ''; + default = false; + }; + }; + }); + }; + }; + }; + }; + }; + + serviceOpts = { + serviceConfig = { + ExecStart = utils.escapeSystemdExecArgs ([ + (lib.getExe pkgs.fritz-exporter) + "--config" configFile + ] ++ cfg.extraFlags); + DynamicUser = false; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix index dc53d21406ff..7b881a8e2693 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/graphite.nix b/nixos/modules/services/monitoring/prometheus/exporters/graphite.nix index 34a887104212..07c06afe1409 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/graphite.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/graphite.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: let cfg = config.services.prometheus.exporters.graphite; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix b/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix index f5604bc00ee0..78ae4826215c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; let diff --git a/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix b/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix index c5024a258e71..68fc63e40fcd 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix index 61c0c08d2250..d0d7f16bdadf 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix b/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix index 9adbe31d84d6..fe9734d33c7c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix b/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix index 024602718602..bc670ba9cc0e 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/json.nix b/nixos/modules/services/monitoring/prometheus/exporters/json.nix index 473f3a7e47e3..7f78985d80cd 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/json.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/json.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix b/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix index 15e0c9ecb177..72119d17fcb7 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix index 3abb6ff6bdf8..ccfdd98b8db9 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix @@ -1,7 +1,8 @@ { config , lib , pkgs -, options +, utils +, ... }: with lib; @@ -9,18 +10,22 @@ with lib; let cfg = config.services.prometheus.exporters.kea; in { + imports = [ + (mkRenamedOptionModule [ "controlSocketPaths" ] [ "targets" ]) + ]; port = 9547; extraOpts = { - controlSocketPaths = mkOption { + targets = mkOption { type = types.listOf types.str; example = literalExpression '' [ "/run/kea/kea-dhcp4.socket" "/run/kea/kea-dhcp6.socket" + "http://127.0.0.1:8547" ] ''; description = lib.mdDoc '' - Paths to kea control sockets + Paths or URLs to the Kea control socket. ''; }; }; @@ -32,12 +37,11 @@ in { serviceConfig = { User = "kea"; DynamicUser = true; - ExecStart = '' - ${pkgs.prometheus-kea-exporter}/bin/kea-exporter \ - --address ${cfg.listenAddress} \ - --port ${toString cfg.port} \ - ${concatStringsSep " " cfg.controlSocketPaths} - ''; + ExecStart = utils.escapeSystemdExecArgs ([ + (lib.getExe pkgs.prometheus-kea-exporter) + "--address" cfg.listenAddress + "--port" cfg.port + ] ++ cfg.extraFlags ++ cfg.targets); RuntimeDirectory = "kea"; RuntimeDirectoryPreserve = true; RestrictAddressFamilies = [ diff --git a/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix b/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix index dfa56343b871..afdb664a0de5 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/knot.nix b/nixos/modules/services/monitoring/prometheus/exporters/knot.nix index 775848750803..0352aff8b013 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/knot.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/knot.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix b/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix index 9f914b1dc146..66d9c02f904b 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix index 15079f5841f4..8c88f47ab86a 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix index 54dab4b5581a..a8dba75251d8 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix index 82cc3fc314f2..e24d4f766e30 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix b/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix index 222ea3e5384f..0eb193c0021f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix b/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix index b36a09c60920..1ed6bbf0325d 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mysqld.nix b/nixos/modules/services/monitoring/prometheus/exporters/mysqld.nix index 849c514de681..c6da052ccdf3 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/mysqld.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/mysqld.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: let cfg = config.services.prometheus.exporters.mysqld; inherit (lib) types mkOption mdDoc mkIf mkForce cli concatStringsSep optionalString escapeShellArgs; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix index 28a3eb6a134c..82deea6864e8 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix index 88dc79fc2503..339749226aa4 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix index 674dc9dd4158..b79a034e1384 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/node.nix b/nixos/modules/services/monitoring/prometheus/exporters/node.nix index dd8602e2c63d..9b8a0d2c6bc2 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/node.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/node.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nut.nix b/nixos/modules/services/monitoring/prometheus/exporters/nut.nix index e58a394456a3..a14e379079b0 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nut.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nut.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix index 9e55cadae523..9587403c7802 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix b/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix index 8238f1ac1856..4ea5f64012c0 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/php-fpm.nix @@ -2,6 +2,7 @@ , lib , pkgs , options +, ... }: let diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix b/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix index 6f403b3e58c8..4b7eca7493a6 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/ping.nix b/nixos/modules/services/monitoring/prometheus/exporters/ping.nix index af78b6bef625..bda5038a0c64 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/ping.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/ping.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix index 9f402b123110..ead8e806f85a 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix b/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix index 755d771ecdff..514b2d0c8f2d 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/process.nix b/nixos/modules/services/monitoring/prometheus/exporters/process.nix index 278d6cd78074..86c71a88e28b 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/process.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/process.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix index 83e740320df2..96db49d9591f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; let diff --git a/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix index f03b3c4df916..60243e0ed069 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/redis.nix b/nixos/modules/services/monitoring/prometheus/exporters/redis.nix index befbcb21f766..71f94a700efd 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/redis.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/redis.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/restic.nix b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix index 977bd42e9812..12962af5f111 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/restic.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix b/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix index f9dcfad07d30..8169d4075a9f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix b/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix index 1f7235cb7830..42b659501161 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/rtl_433.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: let cfg = config.services.prometheus.exporters.rtl_433; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/sabnzbd.nix b/nixos/modules/services/monitoring/prometheus/exporters/sabnzbd.nix index b9ab305f7c08..0d937ac6673f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/sabnzbd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/sabnzbd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: let inherit (lib) mkOption types; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/scaphandre.nix b/nixos/modules/services/monitoring/prometheus/exporters/scaphandre.nix index 3b6ebf65b090..d4c929d88b9c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/scaphandre.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/scaphandre.nix @@ -2,6 +2,7 @@ , lib , pkgs , options +, ... }: let diff --git a/nixos/modules/services/monitoring/prometheus/exporters/script.nix b/nixos/modules/services/monitoring/prometheus/exporters/script.nix index eab0e1d8a6b5..f37fa456d27c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/script.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/script.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix b/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix index b9cfd1b1e84a..1d2329dfbae1 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix index 50e1321a1e9c..1040e9ecadbd 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix b/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix index 459f5842f546..2bacc9cd7cac 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix index 452cb154bcf6..207446e39f49 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/sql.nix b/nixos/modules/services/monitoring/prometheus/exporters/sql.nix index 678bc348679d..dbfa69678a0c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/sql.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/sql.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; let cfg = config.services.prometheus.exporters.sql; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix b/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix index d9d732d8c125..94df86167e8c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix b/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix index b1d6760b40b3..337ebd4ed66f 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/tor.nix b/nixos/modules/services/monitoring/prometheus/exporters/tor.nix index 7a9167110a27..b91f69aded3d 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/tor.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/tor.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix b/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix index f2336429d42f..2f4444a96c69 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix @@ -2,6 +2,7 @@ , lib , pkgs , options +, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix index 70f26d9783be..b7addcd56827 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix b/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix index 3b7f978528cd..aff1197a8775 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix b/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix index a019157c664b..7b21e5fc7cb7 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix index a7e5b41dffc6..98fbba82c8e9 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix index 9b7590314936..127c8021a9f0 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix b/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix index ff12a52d49a9..21f6354cc4a2 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, options }: +{ config, lib, pkgs, options, ... }: with lib; diff --git a/nixos/modules/services/monitoring/scrutiny.nix b/nixos/modules/services/monitoring/scrutiny.nix index 2862cdd80128..031f5a30cada 100644 --- a/nixos/modules/services/monitoring/scrutiny.nix +++ b/nixos/modules/services/monitoring/scrutiny.nix @@ -2,7 +2,7 @@ let inherit (lib) maintainers; inherit (lib.meta) getExe; - inherit (lib.modules) mkIf; + inherit (lib.modules) mkIf mkMerge; inherit (lib.options) literalExpression mkEnableOption mkOption mkPackageOption; inherit (lib.types) bool enum nullOr port str submodule; @@ -156,43 +156,47 @@ in }; }; - config = mkIf (cfg.enable || cfg.collector.enable) { - services.influxdb2.enable = cfg.influxdb.enable; + config = mkMerge [ + (mkIf cfg.enable { + services.influxdb2.enable = cfg.influxdb.enable; - networking.firewall = mkIf cfg.openFirewall { - allowedTCPPorts = [ cfg.settings.web.listen.port ]; - }; - - services.smartd = mkIf cfg.collector.enable { - enable = true; - extraOptions = [ - "-A /var/log/smartd/" - "--interval=600" - ]; - }; + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.settings.web.listen.port ]; + }; - systemd = { - services = { - scrutiny = mkIf cfg.enable { - description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - environment = { - SCRUTINY_VERSION = "1"; - SCRUTINY_WEB_DATABASE_LOCATION = "/var/lib/scrutiny/scrutiny.db"; - SCRUTINY_WEB_SRC_FRONTEND_PATH = "${cfg.package}/share/scrutiny"; - }; - serviceConfig = { - DynamicUser = true; - ExecStart = "${getExe cfg.package} start --config ${settingsFormat.generate "scrutiny.yaml" cfg.settings}"; - Restart = "always"; - StateDirectory = "scrutiny"; - StateDirectoryMode = "0750"; - }; + systemd.services.scrutiny = { + description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ] ++ lib.optional cfg.influxdb.enable "influxdb2.service"; + wants = lib.optional cfg.influxdb.enable "influxdb2.service"; + environment = { + SCRUTINY_VERSION = "1"; + SCRUTINY_WEB_DATABASE_LOCATION = "/var/lib/scrutiny/scrutiny.db"; + SCRUTINY_WEB_SRC_FRONTEND_PATH = "${cfg.package}/share/scrutiny"; + }; + serviceConfig = { + DynamicUser = true; + ExecStart = "${getExe cfg.package} start --config ${settingsFormat.generate "scrutiny.yaml" cfg.settings}"; + Restart = "always"; + StateDirectory = "scrutiny"; + StateDirectoryMode = "0750"; }; + }; + }) + (mkIf cfg.collector.enable { + services.smartd = { + enable = true; + extraOptions = [ + "-A /var/log/smartd/" + "--interval=600" + ]; + }; - scrutiny-collector = mkIf cfg.collector.enable { + systemd = { + services.scrutiny-collector = { description = "Scrutiny Collector Service"; + after = lib.optional cfg.enable "scrutiny.service"; + wants = lib.optional cfg.enable "scrutiny.service"; environment = { COLLECTOR_VERSION = "1"; COLLECTOR_API_ENDPOINT = cfg.collector.settings.api.endpoint; @@ -203,13 +207,11 @@ in }; startAt = cfg.collector.schedule; }; - }; - timers = mkIf cfg.collector.enable { - scrutiny-collector.timerConfig.Persistent = true; + timers.scrutiny-collector.timerConfig.Persistent = true; }; - }; - }; + }) + ]; meta.maintainers = [ maintainers.jnsgruk ]; } diff --git a/nixos/modules/services/networking/dnscache.nix b/nixos/modules/services/networking/dnscache.nix index eff13f69f470..4f5b77a5b685 100644 --- a/nixos/modules/services/networking/dnscache.nix +++ b/nixos/modules/services/networking/dnscache.nix @@ -86,7 +86,11 @@ in { config = mkIf config.services.dnscache.enable { environment.systemPackages = [ pkgs.djbdns ]; - users.users.dnscache.isSystemUser = true; + users.users.dnscache = { + isSystemUser = true; + group = "dnscache"; + }; + users.groups.dnscache = {}; systemd.services.dnscache = { description = "djbdns dnscache server"; diff --git a/nixos/modules/services/networking/mihomo.nix b/nixos/modules/services/networking/mihomo.nix new file mode 100644 index 000000000000..ae700603b529 --- /dev/null +++ b/nixos/modules/services/networking/mihomo.nix @@ -0,0 +1,118 @@ +# NOTE: +# cfg.configFile contains secrets such as proxy servers' credential! +# we dont want plaintext secrets in world-readable `/nix/store`. + +{ lib +, config +, pkgs +, ... +}: +let + cfg = config.services.mihomo; +in +{ + options.services.mihomo = { + enable = lib.mkEnableOption "Mihomo, A rule-based proxy in Go."; + + package = lib.mkPackageOption pkgs "mihomo" { }; + + configFile = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.path; + description = "Configuration file to use."; + }; + + webui = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.path; + description = '' + Local web interface to use. + + You can also use the following website, just in case: + - metacubexd: + - https://d.metacubex.one + - https://metacubex.github.io/metacubexd + - https://metacubexd.pages.dev + - yacd: + - https://yacd.haishan.me + - clash-dashboard (buggy): + - https://clash.razord.top + ''; + }; + + extraOpts = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + description = "Extra command line options to use."; + }; + + tunMode = lib.mkEnableOption '' + necessary permission for Mihomo's systemd service for TUN mode to function properly. + + Keep in mind, that you still need to enable TUN mode manually in Mihomo's configuration. + ''; + }; + + config = lib.mkIf cfg.enable { + ### systemd service + systemd.services."mihomo" = { + description = "Mihomo daemon, A rule-based proxy in Go."; + documentation = [ "https://wiki.metacubex.one/" ]; + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = + { + ExecStart = lib.concatStringsSep " " [ + (lib.getExe cfg.package) + "-d /var/lib/private/mihomo" + (lib.optionalString (cfg.configFile != null) "-f \${CREDENTIALS_DIRECTORY}/config.yaml") + (lib.optionalString (cfg.webui != null) "-ext-ui ${cfg.webui}") + (lib.optionalString (cfg.extraOpts != null) cfg.extraOpts) + ]; + + DynamicUser = true; + StateDirectory = "mihomo"; + LoadCredential = "config.yaml:${cfg.configFile}"; + + ### Hardening + AmbientCapabilities = ""; + CapabilityBoundingSet = ""; + DeviceAllow = ""; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RestrictNamespaces = true; + RestrictAddressFamilies = "AF_INET AF_INET6"; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service bpf"; + UMask = "0077"; + } + // lib.optionalAttrs cfg.tunMode { + AmbientCapabilities = "CAP_NET_ADMIN"; + CapabilityBoundingSet = "CAP_NET_ADMIN"; + PrivateDevices = false; + PrivateUsers = false; + RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK"; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ Guanran928 ]; +} diff --git a/nixos/modules/services/networking/mycelium.nix b/nixos/modules/services/networking/mycelium.nix new file mode 100644 index 000000000000..9c4bca7c6861 --- /dev/null +++ b/nixos/modules/services/networking/mycelium.nix @@ -0,0 +1,133 @@ +{ config, pkgs, lib, ... }: + +let + cfg = config.services.mycelium; +in +{ + options.services.mycelium = { + enable = lib.mkEnableOption "mycelium network"; + peers = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = '' + List of peers to connect to, in the formats: + - `quic://[2001:0db8::1]:9651` + - `quic://192.0.2.1:9651` + - `tcp://[2001:0db8::1]:9651` + - `tcp://192.0.2.1:9651` + + If addHostedPublicNodes is set to true, the hosted public nodes will also be added. + ''; + default = [ ]; + }; + keyFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = '' + Optional path to a file containing the mycelium key material. + If unset, the default location (`/var/lib/mycelium/key.bin`) will be used. + If no key exist at this location, it will be generated on startup. + ''; + }; + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Open the firewall for mycelium"; + }; + package = lib.mkOption { + type = lib.types.package; + default = pkgs.mycelium; + defaultText = lib.literalExpression ''"''${pkgs.mycelium}"''; + description = "The mycelium package to use"; + }; + addHostedPublicNodes = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Adds the hosted peers from https://github.com/threefoldtech/mycelium#hosted-public-nodes. + ''; + }; + }; + config = lib.mkIf cfg.enable { + networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [ 9651 ]; + networking.firewall.allowedUDPPorts = lib.optionals cfg.openFirewall [ 9650 9651 ]; + + systemd.services.mycelium = { + description = "Mycelium network"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + restartTriggers = [ + cfg.keyFile + ]; + + unitConfig.Documentation = "https://github.com/threefoldtech/mycelium"; + + serviceConfig = { + User = "mycelium"; + DynamicUser = true; + StateDirectory = "mycelium"; + ProtectHome = true; + ProtectSystem = true; + LoadCredential = lib.mkIf (cfg.keyFile != null) "keyfile:${cfg.keyFile}"; + SyslogIdentifier = "mycelium"; + AmbientCapabilities = [ "CAP_NET_ADMIN" ]; + MemoryDenyWriteExecute = true; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged @keyring" ]; + ExecStart = lib.concatStringsSep " " ([ + (lib.getExe cfg.package) + (if (cfg.keyFile != null) then + "--key-file \${CREDENTIALS_DIRECTORY}/keyfile" else + "--key-file %S/mycelium/key.bin" + ) + "--tun-name" + "mycelium" + ] ++ + (lib.optional (cfg.addHostedPublicNodes || cfg.peers != [ ]) "--peers") + ++ cfg.peers ++ (lib.optionals cfg.addHostedPublicNodes [ + "tcp://188.40.132.242:9651" # DE 01 + "tcp://[2a01:4f8:221:1e0b::2]:9651" + "quic://188.40.132.242:9651" + "quic://[2a01:4f8:221:1e0b::2]:9651" + + "tcp://136.243.47.186:9651" # DE 02 + "tcp://[2a01:4f8:212:fa6::2]:9651" + "quic://136.243.47.186:9651" + "quic://[2a01:4f8:212:fa6::2]:9651" + + "tcp://185.69.166.7:9651" # BE 03 + "tcp://[2a02:1802:5e:0:8478:51ff:fee2:3331]:9651" + "quic://185.69.166.7:9651" + "quic://[2a02:1802:5e:0:8478:51ff:fee2:3331]:9651" + + "tcp://185.69.166.8:9651" # BE 04 + "tcp://[2a02:1802:5e:0:8c9e:7dff:fec9:f0d2]:9651" + "quic://185.69.166.8:9651" + "quic://[2a02:1802:5e:0:8c9e:7dff:fec9:f0d2]:9651" + + "tcp://65.21.231.58:9651" # FI 05 + "tcp://[2a01:4f9:6a:1dc5::2]:9651" + "quic://65.21.231.58:9651" + "quic://[2a01:4f9:6a:1dc5::2]:9651" + + "tcp://65.109.18.113:9651" # FI 06 + "tcp://[2a01:4f9:5a:1042::2]:9651" + "quic://65.109.18.113:9651" + "quic://[2a01:4f9:5a:1042::2]:9651" + ])); + Restart = "always"; + RestartSec = 5; + TimeoutStopSec = 5; + }; + }; + }; + meta = { + maintainers = with lib.maintainers; [ flokli lassulus ]; + }; +} + diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 63804a3b1c54..573a02cbda9e 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -101,7 +101,23 @@ let pre-down = "pre-down.d/"; }; - macAddressOpt = mkOption { + macAddressOptWifi = mkOption { + type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" "stable-ssid" ]); + default = "preserve"; + example = "00:11:22:33:44:55"; + description = lib.mdDoc '' + Set the MAC address of the interface. + + - `"XX:XX:XX:XX:XX:XX"`: MAC address of the interface + - `"permanent"`: Use the permanent MAC address of the device + - `"preserve"`: Don’t change the MAC address of the device upon activation + - `"random"`: Generate a randomized value upon each connect + - `"stable"`: Generate a stable, hashed MAC address + - `"stable-ssid"`: Generate a stable MAC addressed based on Wi-Fi network + ''; + }; + + macAddressOptEth = mkOption { type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" ]); default = "preserve"; example = "00:11:22:33:44:55"; @@ -258,10 +274,10 @@ in ''; }; - ethernet.macAddress = macAddressOpt; + ethernet.macAddress = macAddressOptEth; wifi = { - macAddress = macAddressOpt; + macAddress = macAddressOptWifi; backend = mkOption { type = types.enum [ "wpa_supplicant" "iwd" ]; @@ -584,6 +600,7 @@ in description = "Ensure that NetworkManager declarative profiles are created"; wantedBy = [ "multi-user.target" ]; before = [ "network-online.target" ]; + after = [ "NetworkManager.service" ]; script = let path = id: "/run/NetworkManager/system-connections/${id}.nmconnection"; in '' @@ -593,9 +610,7 @@ in ${pkgs.envsubst}/bin/envsubst -i ${ini.generate (lib.escapeShellArg profile.n) profile.v} > ${path (lib.escapeShellArg profile.n)} '') (lib.mapAttrsToList (n: v: { inherit n v; }) cfg.ensureProfiles.profiles) + '' - if systemctl is-active --quiet NetworkManager; then - ${pkgs.networkmanager}/bin/nmcli connection reload - fi + ${pkgs.networkmanager}/bin/nmcli connection reload ''; serviceConfig = { EnvironmentFile = cfg.ensureProfiles.environmentFiles; diff --git a/nixos/modules/services/networking/tinyproxy.nix b/nixos/modules/services/networking/tinyproxy.nix index 8ff12b52f10c..2b7509e99ca4 100644 --- a/nixos/modules/services/networking/tinyproxy.nix +++ b/nixos/modules/services/networking/tinyproxy.nix @@ -7,6 +7,7 @@ let mkValueStringTinyproxy = with lib; v: if true == v then "yes" else if false == v then "no" + else if types.path.check v then ''"${v}"'' else generators.mkValueStringDefault {} v; mkKeyValueTinyproxy = { mkValueString ? mkValueStringDefault {} diff --git a/nixos/modules/services/web-apps/engelsystem.nix b/nixos/modules/services/web-apps/engelsystem.nix index 669620debce5..ae7b2b9e7d0c 100644 --- a/nixos/modules/services/web-apps/engelsystem.nix +++ b/nixos/modules/services/web-apps/engelsystem.nix @@ -99,7 +99,6 @@ in { ''; services.phpfpm.pools.engelsystem = { - phpPackage = pkgs.php81; user = "engelsystem"; settings = { "listen.owner" = config.services.nginx.user; diff --git a/nixos/modules/services/web-apps/hedgedoc.nix b/nixos/modules/services/web-apps/hedgedoc.nix index adcfe80a7332..8b17c6cbc3be 100644 --- a/nixos/modules/services/web-apps/hedgedoc.nix +++ b/nixos/modules/services/web-apps/hedgedoc.nix @@ -236,9 +236,9 @@ in }; services.hedgedoc.settings = { - defaultNotePath = lib.mkDefault "${cfg.package}/public/default.md"; - docsPath = lib.mkDefault "${cfg.package}/public/docs"; - viewPath = lib.mkDefault "${cfg.package}/public/views"; + defaultNotePath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/default.md"; + docsPath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/docs"; + viewPath = lib.mkDefault "${cfg.package}/share/hedgedoc/public/views"; }; systemd.services.hedgedoc = { @@ -263,7 +263,7 @@ in Group = name; Restart = "always"; - ExecStart = "${cfg.package}/bin/hedgedoc"; + ExecStart = lib.getExe cfg.package; RuntimeDirectory = [ name ]; StateDirectory = [ name ]; WorkingDirectory = "/run/${name}"; diff --git a/nixos/modules/services/web-apps/komga.nix b/nixos/modules/services/web-apps/komga.nix index 31f475fc7b04..d7ab2a9e612e 100644 --- a/nixos/modules/services/web-apps/komga.nix +++ b/nixos/modules/services/web-apps/komga.nix @@ -1,99 +1,122 @@ -{ config, pkgs, lib, ... }: - -with lib; +{ + config, + pkgs, + lib, + ... +}: let cfg = config.services.komga; - -in { + inherit (lib) mkOption mkEnableOption maintainers; + inherit (lib.types) port str bool; +in +{ options = { services.komga = { - enable = mkEnableOption (lib.mdDoc "Komga, a free and open source comics/mangas media server"); + enable = mkEnableOption "Komga, a free and open source comics/mangas media server"; port = mkOption { - type = types.port; + type = port; default = 8080; - description = lib.mdDoc '' - The port that Komga will listen on. - ''; + description = "The port that Komga will listen on."; }; user = mkOption { - type = types.str; + type = str; default = "komga"; - description = lib.mdDoc '' - User account under which Komga runs. - ''; + description = "User account under which Komga runs."; }; group = mkOption { - type = types.str; + type = str; default = "komga"; - description = lib.mdDoc '' - Group under which Komga runs. - ''; + description = "Group under which Komga runs."; }; stateDir = mkOption { - type = types.str; + type = str; default = "/var/lib/komga"; - description = lib.mdDoc '' - State and configuration directory Komga will use. - ''; + description = "State and configuration directory Komga will use."; }; openFirewall = mkOption { - type = types.bool; + type = bool; default = false; - description = lib.mdDoc '' - Whether to open the firewall for the port in {option}`services.komga.port`. - ''; + description = "Whether to open the firewall for the port in {option}`services.komga.port`."; }; }; }; - config = mkIf cfg.enable { - - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; + config = + let + inherit (lib) mkIf getExe; + in + mkIf cfg.enable { - users.groups = mkIf (cfg.group == "komga") { - komga = {}; - }; + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; - users.users = mkIf (cfg.user == "komga") { - komga = { - group = cfg.group; - home = cfg.stateDir; - description = "Komga Daemon user"; - isSystemUser = true; - }; - }; + users.groups = mkIf (cfg.group == "komga") { komga = { }; }; - systemd.services.komga = { - environment = { - SERVER_PORT = builtins.toString cfg.port; - KOMGA_CONFIGDIR = cfg.stateDir; + users.users = mkIf (cfg.user == "komga") { + komga = { + group = cfg.group; + home = cfg.stateDir; + description = "Komga Daemon user"; + isSystemUser = true; + }; }; - description = "Komga is a free and open source comics/mangas media server"; - - wantedBy = [ "multi-user.target" ]; - wants = [ "network-online.target" ]; - after = [ "network-online.target" ]; - - serviceConfig = { - User = cfg.user; - Group = cfg.group; - - Type = "simple"; - Restart = "on-failure"; - ExecStart = "${pkgs.komga}/bin/komga"; - - StateDirectory = mkIf (cfg.stateDir == "/var/lib/komga") "komga"; + systemd.services.komga = { + environment = { + SERVER_PORT = builtins.toString cfg.port; + KOMGA_CONFIGDIR = cfg.stateDir; + }; + + description = "Komga is a free and open source comics/mangas media server"; + + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + + Type = "simple"; + Restart = "on-failure"; + ExecStart = getExe pkgs.komga; + + StateDirectory = mkIf (cfg.stateDir == "/var/lib/komga") "komga"; + + RemoveIPC = true; + NoNewPrivileges = true; + CapabilityBoundingSet = ""; + SystemCallFilter = [ "@system-service" ]; + ProtectSystem = "full"; + PrivateTmp = true; + ProtectProc = "invisible"; + ProtectClock = true; + ProcSubset = "pid"; + PrivateUsers = true; + PrivateDevices = true; + ProtectHostname = true; + ProtectKernelTunables = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + ]; + LockPersonality = true; + RestrictNamespaces = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + ProtectKernelModules = true; + SystemCallArchitectures = "native"; + RestrictSUIDSGID = true; + RestrictRealtime = true; + }; }; - }; - }; meta.maintainers = with maintainers; [ govanify ]; } diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 5cda4a00a9de..7f998207c434 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -14,7 +14,6 @@ let expose_php = "Off"; error_reporting = "E_ALL & ~E_DEPRECATED & ~E_STRICT"; display_errors = "stderr"; - "opcache.enable_cli" = "1"; "opcache.interned_strings_buffer" = "8"; "opcache.max_accelerated_files" = "10000"; "opcache.memory_consumption" = "128"; diff --git a/nixos/modules/services/web-apps/pretix.nix b/nixos/modules/services/web-apps/pretix.nix new file mode 100644 index 000000000000..2355f8c450a1 --- /dev/null +++ b/nixos/modules/services/web-apps/pretix.nix @@ -0,0 +1,581 @@ +{ config +, lib +, pkgs +, utils +, ... +}: + +let + inherit (lib) + concatMapStringsSep + escapeShellArgs + filter + filterAttrs + getExe + getExe' + isAttrs + isList + literalExpression + mapAttrs + mkDefault + mkEnableOption + mkIf + mkOption + mkPackageOption + optionals + optionalString + recursiveUpdate + types + ; + + filterRecursiveNull = o: + if isAttrs o then + mapAttrs (_: v: filterRecursiveNull v) (filterAttrs (_: v: v != null) o) + else if isList o then + map filterRecursiveNull (filter (v: v != null) o) + else + o; + + cfg = config.services.pretix; + format = pkgs.formats.ini { }; + + configFile = format.generate "pretix.cfg" (filterRecursiveNull cfg.settings); + + finalPackage = cfg.package.override { + inherit (cfg) plugins; + }; + + pythonEnv = cfg.package.python.buildEnv.override { + extraLibs = with cfg.package.python.pkgs; [ + (toPythonModule finalPackage) + gunicorn + ] + ++ lib.optionals (cfg.settings.memcached.location != null) + cfg.package.optional-dependencies.memcached + ; + }; + + withRedis = cfg.settings.redis.location != null; +in +{ + meta = with lib; { + maintainers = with maintainers; [ hexa ]; + }; + + options.services.pretix = { + enable = mkEnableOption "pretix"; + + package = mkPackageOption pkgs "pretix" { }; + + group = mkOption { + type = types.str; + default = "pretix"; + description = '' + Group under which pretix should run. + ''; + }; + + user = mkOption { + type = types.str; + default = "pretix"; + description = '' + User under which pretix should run. + ''; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/pretix-secrets.env"; + description = '' + Environment file to pass secret configuration values. + + Each line must follow the `PRETIX_SECTION_KEY=value` pattern. + ''; + }; + + plugins = mkOption { + type = types.listOf types.package; + default = []; + example = literalExpression '' + with config.services.pretix.package.plugins; [ + passbook + pages + ]; + ''; + description = '' + Pretix plugins to install into the Python environment. + ''; + }; + + gunicorn.extraArgs = mkOption { + type = with types; listOf str; + default = [ + "--name=pretix" + ]; + example = [ + "--name=pretix" + "--workers=4" + "--max-requests=1200" + "--max-requests-jitter=50" + "--log-level=info" + ]; + description = '' + Extra arguments to pass to gunicorn. + See <https://docs.pretix.eu/en/latest/admin/installation/manual_smallscale.html#start-pretix-as-a-service> for details. + ''; + apply = escapeShellArgs; + }; + + celery = { + extraArgs = mkOption { + type = with types; listOf str; + default = [ ]; + description = '' + Extra arguments to pass to celery. + + See <https://docs.celeryq.dev/en/stable/reference/cli.html#celery-worker> for more info. + ''; + apply = utils.escapeSystemdExecArgs; + }; + }; + + nginx = { + enable = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to set up an nginx virtual host. + ''; + }; + + domain = mkOption { + type = types.str; + example = "talks.example.com"; + description = '' + The domain name under which to set up the virtual host. + ''; + }; + }; + + database.createLocally = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to automatically set up the database on the local DBMS instance. + + Only supported for PostgreSQL. Not required for sqlite. + ''; + }; + + settings = mkOption { + type = types.submodule { + freeformType = format.type; + options = { + pretix = { + instance_name = mkOption { + type = types.str; + example = "tickets.example.com"; + description = '' + The name of this installation. + ''; + }; + + url = mkOption { + type = types.str; + example = "https://tickets.example.com"; + description = '' + The installation’s full URL, without a trailing slash. + ''; + }; + + cachedir = mkOption { + type = types.path; + default = "/var/cache/pretix"; + description = '' + Directory for storing temporary files. + ''; + }; + + datadir = mkOption { + type = types.path; + default = "/var/lib/pretix"; + description = '' + Directory for storing user uploads and similar data. + ''; + }; + + logdir = mkOption { + type = types.path; + default = "/var/log/pretix"; + description = '' + Directory for storing log files. + ''; + }; + + currency = mkOption { + type = types.str; + default = "EUR"; + example = "USD"; + description = '' + Default currency for events in its ISO 4217 three-letter code. + ''; + }; + + registration = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to allow registration of new admin users. + ''; + }; + }; + + database = { + backend = mkOption { + type = types.enum [ + "sqlite3" + "postgresql" + ]; + default = "postgresql"; + description = '' + Database backend to use. + + Only postgresql is recommended for production setups. + ''; + }; + + host = mkOption { + type = with types; nullOr types.path; + default = if cfg.settings.database.backend == "postgresql" then "/run/postgresql" else null; + defaultText = literalExpression '' + if config.services.pretix.settings..database.backend == "postgresql" then "/run/postgresql" + else null + ''; + description = '' + Database host or socket path. + ''; + }; + + name = mkOption { + type = types.str; + default = "pretix"; + description = '' + Database name. + ''; + }; + + user = mkOption { + type = types.str; + default = "pretix"; + description = '' + Database username. + ''; + }; + }; + + mail = { + from = mkOption { + type = types.str; + example = "tickets@example.com"; + description = '' + E-Mail address used in the `FROM` header of outgoing mails. + ''; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + example = "mail.example.com"; + description = '' + Hostname of the SMTP server use for mail delivery. + ''; + }; + + port = mkOption { + type = types.port; + default = 25; + example = 587; + description = '' + Port of the SMTP server to use for mail delivery. + ''; + }; + }; + + celery = { + backend = mkOption { + type = types.str; + default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=1"; + defaultText = literalExpression '' + optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=1" + ''; + description = '' + URI to the celery backend used for the asynchronous job queue. + ''; + }; + + broker = mkOption { + type = types.str; + default = "redis+socket://${config.services.redis.servers.pretix.unixSocket}?virtual_host=2"; + defaultText = literalExpression '' + optionalString config.services.pretix.celery.enable "redis+socket://''${config.services.redis.servers.pretix.unixSocket}?virtual_host=2" + ''; + description = '' + URI to the celery broker used for the asynchronous job queue. + ''; + }; + }; + + redis = { + location = mkOption { + type = with types; nullOr str; + default = "unix://${config.services.redis.servers.pretix.unixSocket}?db=0"; + defaultText = literalExpression '' + "unix://''${config.services.redis.servers.pretix.unixSocket}?db=0" + ''; + description = '' + URI to the redis server, used to speed up locking, caching and session storage. + ''; + }; + + sessions = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to use redis as the session storage. + ''; + }; + }; + + memcached = { + location = mkOption { + type = with types; nullOr str; + default = null; + example = "127.0.0.1:11211"; + description = '' + The `host:port` combination or the path to the UNIX socket of a memcached instance. + + Can be used instead of Redis for caching. + ''; + }; + }; + + tools = { + pdftk = mkOption { + type = types.path; + default = getExe pkgs.pdftk; + defaultText = literalExpression '' + lib.getExe pkgs.pdftk + ''; + description = '' + Path to the pdftk executable. + ''; + }; + }; + }; + }; + default = { }; + description = '' + pretix configuration as a Nix attribute set. All settings can also be passed + from the environment. + + See <https://docs.pretix.eu/en/latest/admin/config.html> for possible options. + ''; + }; + }; + + config = mkIf cfg.enable { + # https://docs.pretix.eu/en/latest/admin/installation/index.html + + environment.systemPackages = [ + (pkgs.writeScriptBin "pretix-manage" '' + cd ${cfg.settings.pretix.datadir} + sudo=exec + if [[ "$USER" != ${cfg.user} ]]; then + sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} ${optionalString withRedis "-g redis-pretix"} --preserve-env=PRETIX_CONFIG_FILE' + fi + export PRETIX_CONFIG_FILE=${configFile} + $sudo ${getExe' pythonEnv "pretix-manage"} "$@" + '') + ]; + + services = { + nginx = mkIf cfg.nginx.enable { + enable = true; + recommendedGzipSettings = mkDefault true; + recommendedOptimisation = mkDefault true; + recommendedProxySettings = mkDefault true; + recommendedTlsSettings = mkDefault true; + upstreams.pretix.servers."unix:/run/pretix/pretix.sock" = { }; + virtualHosts.${cfg.nginx.domain} = { + # https://docs.pretix.eu/en/latest/admin/installation/manual_smallscale.html#ssl + extraConfig = '' + more_set_headers Referrer-Policy same-origin; + more_set_headers X-Content-Type-Options nosniff; + ''; + locations = { + "/".proxyPass = "http://pretix"; + "/media/" = { + alias = "${cfg.settings.pretix.datadir}/media/"; + extraConfig = '' + access_log off; + expires 7d; + ''; + }; + "^~ /media/(cachedfiles|invoices)" = { + extraConfig = '' + deny all; + return 404; + ''; + }; + "/static/" = { + alias = "${finalPackage}/${cfg.package.python.sitePackages}/pretix/static.dist/"; + extraConfig = '' + access_log off; + more_set_headers Cache-Control "public"; + expires 365d; + ''; + }; + }; + }; + }; + + postgresql = mkIf (cfg.database.createLocally && cfg.settings.database.backend == "postgresql") { + enable = true; + ensureUsers = [ { + name = cfg.settings.database.user; + ensureDBOwnership = true; + } ]; + ensureDatabases = [ cfg.settings.database.name ]; + }; + + redis.servers.pretix.enable = withRedis; + }; + + systemd.services = let + commonUnitConfig = { + environment.PRETIX_CONFIG_FILE = configFile; + serviceConfig = { + User = "pretix"; + Group = "pretix"; + EnvironmentFile = optionals (cfg.environmentFile != null) [ + cfg.environmentFile + ]; + StateDirectory = [ + "pretix" + ]; + StateDirectoryMode = "0755"; + CacheDirectory = "pretix"; + LogsDirectory = "pretix"; + WorkingDirectory = cfg.settings.pretix.datadir; + SupplementaryGroups = optionals withRedis [ + "redis-pretix" + ]; + AmbientCapabilities = ""; + CapabilityBoundingSet = [ "" ]; + DevicePolicy = "closed"; + LockPersonality = true; + MemoryDenyWriteExecute = false; # required by pdftk + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProcSubset = "pid"; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "@chown" + ]; + UMask = "0022"; + }; + }; + in { + pretix-web = recursiveUpdate commonUnitConfig { + description = "pretix web service"; + after = [ + "network.target" + "redis-pretix.service" + "postgresql.service" + ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + versionFile="${cfg.settings.pretix.datadir}/.version" + version=$(cat "$versionFile" 2>/dev/null || echo 0) + + pluginsFile="${cfg.settings.pretix.datadir}/.plugins" + plugins=$(cat "$pluginsFile" 2>/dev/null || echo "") + configuredPlugins="${concatMapStringsSep "|" (package: package.name) cfg.plugins}" + + if [[ $version != ${cfg.package.version} || $plugins != $configuredPlugins ]]; then + ${getExe' pythonEnv "pretix-manage"} migrate + + echo "${cfg.package.version}" > "$versionFile" + echo "$configuredPlugins" > "$pluginsFile" + fi + ''; + serviceConfig = { + TimeoutStartSec = "5min"; + ExecStart = "${getExe' pythonEnv "gunicorn"} --bind unix:/run/pretix/pretix.sock ${cfg.gunicorn.extraArgs} pretix.wsgi"; + RuntimeDirectory = "pretix"; + }; + }; + + pretix-periodic = recursiveUpdate commonUnitConfig { + description = "pretix periodic task runner"; + # every 15 minutes + startAt = [ "*:3,18,33,48" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${getExe' pythonEnv "pretix-manage"} runperiodic"; + }; + }; + + pretix-worker = recursiveUpdate commonUnitConfig { + description = "pretix asynchronous job runner"; + after = [ + "network.target" + "redis-pretix.service" + "postgresql.service" + ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${getExe' pythonEnv "celery"} -A pretix.celery_app worker ${cfg.celery.extraArgs}"; + }; + }; + + systemd.sockets.pretix-web.socketConfig = { + ListenStream = "/run/pretix/pretix.sock"; + SocketUser = "nginx"; + }; + + users = { + groups."${cfg.group}" = {}; + users."${cfg.user}" = { + isSystemUser = true; + createHome = true; + home = cfg.settings.pretix.datadir; + inherit (cfg) group; + }; + }; + }; +} diff --git a/nixos/modules/services/web-apps/suwayomi-server.md b/nixos/modules/services/web-apps/suwayomi-server.md index ff1e06c8a53a..18e7a631443f 100644 --- a/nixos/modules/services/web-apps/suwayomi-server.md +++ b/nixos/modules/services/web-apps/suwayomi-server.md @@ -101,6 +101,9 @@ Not all the configuration options are available directly in this module, but you port = 4567; autoDownloadNewChapters = false; maxSourcesInParallel" = 6; + extensionRepos = [ + "https://raw.githubusercontent.com/MY_ACCOUNT/MY_REPO/repo/index.min.json" + ]; }; }; }; diff --git a/nixos/modules/services/web-apps/suwayomi-server.nix b/nixos/modules/services/web-apps/suwayomi-server.nix index 94dbe6f99356..99c6ea2a36e6 100644 --- a/nixos/modules/services/web-apps/suwayomi-server.nix +++ b/nixos/modules/services/web-apps/suwayomi-server.nix @@ -102,6 +102,17 @@ in ''; }; + extensionRepos = mkOption { + type = types.listOf types.str; + default = []; + example = [ + "https://raw.githubusercontent.com/MY_ACCOUNT/MY_REPO/repo/index.min.json" + ]; + description = mdDoc '' + URL of repositories from which the extensions can be installed. + ''; + }; + localSourcePath = mkOption { type = types.path; default = cfg.dataDir; diff --git a/nixos/modules/services/web-servers/garage.nix b/nixos/modules/services/web-servers/garage.nix index 48dd5b34757c..616be978b6e5 100644 --- a/nixos/modules/services/web-servers/garage.nix +++ b/nixos/modules/services/web-servers/garage.nix @@ -75,7 +75,19 @@ in source = configFile; }; - environment.systemPackages = [ cfg.package ]; # For administration + # For administration + environment.systemPackages = [ + (pkgs.writeScriptBin "garage" '' + # make it so all future variables set are automatically exported as environment variables + set -a + + # source the set environmentFile (since systemd EnvironmentFile is supposed to be a minor subset of posix sh parsing) (with shell arg escaping to avoid quoting issues) + [ -f ${lib.escapeShellArg cfg.environmentFile} ] && . ${lib.escapeShellArg cfg.environmentFile} + + # exec the program with quoted args (also with shell arg escaping for the program path to avoid quoting issues there) + exec ${lib.escapeShellArg (lib.getExe cfg.package)} "$@" + '') + ]; systemd.services.garage = { description = "Garage Object Storage (S3 compatible)"; diff --git a/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixos/modules/services/x11/desktop-managers/budgie.nix index fe39097a22e8..466ef5c565b7 100644 --- a/nixos/modules/services/x11/desktop-managers/budgie.nix +++ b/nixos/modules/services/x11/desktop-managers/budgie.nix @@ -44,6 +44,8 @@ let enableSshSocket = config.services.openssh.startWhenNeeded; }; in { + meta.maintainers = lib.teams.budgie.members; + options = { services.xserver.desktopManager.budgie = { enable = mkEnableOption (mdDoc "the Budgie desktop"); @@ -144,7 +146,6 @@ in { mate.atril mate.engrampa mate.mate-calc - mate.mate-terminal mate.mate-system-monitor vlc @@ -158,8 +159,11 @@ in { ] config.environment.budgie.excludePackages) ++ cfg.sessionPath; + # Both budgie-desktop-view and nemo defaults to this emulator. + programs.gnome-terminal.enable = mkDefault true; + # Fonts. - fonts.packages = mkDefault [ + fonts.packages = [ pkgs.noto-fonts pkgs.hack-font ]; @@ -212,7 +216,6 @@ in { services.colord.enable = mkDefault true; # for BCC's Color panel. services.gnome.at-spi2-core.enable = mkDefault true; # for BCC's A11y panel. services.accounts-daemon.enable = mkDefault true; # for BCC's Users panel. - services.fprintd.enable = mkDefault true; # for BCC's Users panel. services.udisks2.enable = mkDefault true; # for BCC's Details panel. # For BCC's Online Accounts panel. diff --git a/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixos/modules/services/x11/desktop-managers/deepin.nix index e6f221201013..902e3a9317dd 100644 --- a/nixos/modules/services/x11/desktop-managers/deepin.nix +++ b/nixos/modules/services/x11/desktop-managers/deepin.nix @@ -66,7 +66,7 @@ in services.upower.enable = mkDefault config.powerManagement.enable; networking.networkmanager.enable = mkDefault true; programs.dconf.enable = mkDefault true; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt; + programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt; fonts.packages = with pkgs; [ noto-fonts ]; xdg.mime.enable = true; diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix index d3bdc4326a90..3d02deba6fc7 100644 --- a/nixos/modules/services/x11/desktop-managers/lxqt.nix +++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix @@ -62,7 +62,7 @@ in # Link some extra directories in /run/current-system/software/share environment.pathsToLink = [ "/share" ]; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt; + programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt; # virtual file systems support for PCManFM-QT services.gvfs.enable = true; diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix index f535a1d298b9..957eac7848e7 100644 --- a/nixos/modules/services/x11/desktop-managers/mate.nix +++ b/nixos/modules/services/x11/desktop-managers/mate.nix @@ -20,6 +20,22 @@ in }; debug = mkEnableOption (lib.mdDoc "mate-session debug messages"); + + extraPanelApplets = mkOption { + default = [ ]; + example = literalExpression "with pkgs.mate; [ mate-applets ]"; + type = types.listOf types.package; + description = lib.mdDoc "Extra applets to add to mate-panel."; + }; + + extraCajaExtensions = mkOption { + default = [ ]; + example = lib.literalExpression "with pkgs.mate; [ caja-extensions ]"; + type = types.listOf types.package; + description = lib.mdDoc "Extra extensions to add to caja."; + }; + + enableWaylandSession = mkEnableOption (lib.mdDoc "MATE Wayland session"); }; environment.mate.excludePackages = mkOption { @@ -31,55 +47,63 @@ in }; - config = mkIf cfg.enable { - - services.xserver.displayManager.sessionPackages = [ - pkgs.mate.mate-session-manager - ]; - - # Let caja find extensions - environment.sessionVariables.CAJA_EXTENSION_DIRS = [ "${config.system.path}/lib/caja/extensions-2.0" ]; - - # Let mate-panel find applets - environment.sessionVariables."MATE_PANEL_APPLETS_DIR" = "${config.system.path}/share/mate-panel/applets"; - environment.sessionVariables."MATE_PANEL_EXTRA_MODULES" = "${config.system.path}/lib/mate-panel/applets"; - - # Debugging - environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1"; - - environment.systemPackages = utils.removePackagesByName - (pkgs.mate.basePackages ++ - pkgs.mate.extraPackages ++ - [ - pkgs.desktop-file-utils - pkgs.glib - pkgs.gtk3.out - pkgs.shared-mime-info - pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/ - pkgs.yelp # for 'Contents' in 'Help' menus - ]) - config.environment.mate.excludePackages; - - programs.dconf.enable = true; - # Shell integration for VTE terminals - programs.bash.vteIntegration = mkDefault true; - programs.zsh.vteIntegration = mkDefault true; - - # Mate uses this for printing - programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true)); - - services.gnome.at-spi2-core.enable = true; - services.gnome.gnome-keyring.enable = true; - services.udev.packages = [ pkgs.mate.mate-settings-daemon ]; - services.gvfs.enable = true; - services.upower.enable = config.powerManagement.enable; - services.xserver.libinput.enable = mkDefault true; - - security.pam.services.mate-screensaver.unixAuth = true; - - xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ]; - - environment.pathsToLink = [ "/share" ]; - }; - + config = mkMerge [ + (mkIf (cfg.enable || cfg.enableWaylandSession) { + services.xserver.displayManager.sessionPackages = [ + pkgs.mate.mate-session-manager + ]; + + # Debugging + environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1"; + + environment.systemPackages = utils.removePackagesByName + (pkgs.mate.basePackages ++ + pkgs.mate.extraPackages ++ + [ + (pkgs.mate.caja-with-extensions.override { + extensions = cfg.extraCajaExtensions; + }) + (pkgs.mate.mate-panel-with-applets.override { + applets = cfg.extraPanelApplets; + }) + pkgs.desktop-file-utils + pkgs.glib + pkgs.gtk3.out + pkgs.shared-mime-info + pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/ + pkgs.yelp # for 'Contents' in 'Help' menus + ]) + config.environment.mate.excludePackages; + + programs.dconf.enable = true; + # Shell integration for VTE terminals + programs.bash.vteIntegration = mkDefault true; + programs.zsh.vteIntegration = mkDefault true; + + # Mate uses this for printing + programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true)); + + services.gnome.at-spi2-core.enable = true; + services.gnome.gnome-keyring.enable = true; + services.udev.packages = [ pkgs.mate.mate-settings-daemon ]; + services.gvfs.enable = true; + services.upower.enable = config.powerManagement.enable; + services.xserver.libinput.enable = mkDefault true; + + security.pam.services.mate-screensaver.unixAuth = true; + + xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ]; + + environment.pathsToLink = [ "/share" ]; + }) + (mkIf cfg.enableWaylandSession { + programs.wayfire.enable = true; + programs.wayfire.plugins = [ pkgs.wayfirePlugins.firedecor ]; + + environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${pkgs.mate.mate-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas"; + + environment.systemPackages = [ pkgs.mate.mate-wayland-session ]; + services.xserver.displayManager.sessionPackages = [ pkgs.mate.mate-wayland-session ]; + }) + ]; } diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index c884b4487e24..f516a29fb5db 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -336,7 +336,7 @@ in serif = [ "Noto Serif" ]; }; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt; + programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt; programs.ssh.askPassword = mkDefault "${pkgs.plasma5Packages.ksshaskpass.out}/bin/ksshaskpass"; # Enable helpful DBus services. diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 6bc964f4c6ed..3ba27b201507 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -131,7 +131,7 @@ in xfdesktop ] ++ optional cfg.enableScreensaver xfce4-screensaver) excludePackages; - programs.gnupg.agent.pinentryPackage = pkgs.pinentry-gtk2; + programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-gtk2; programs.xfconf.enable = true; programs.thunar.enable = true; diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix index 5b7f4bc58d80..a315a3ebf322 100644 --- a/nixos/modules/services/x11/display-managers/sddm.nix +++ b/nixos/modules/services/x11/display-managers/sddm.nix @@ -1,19 +1,24 @@ { config, lib, pkgs, ... }: -with lib; let xcfg = config.services.xserver; dmcfg = xcfg.displayManager; cfg = dmcfg.sddm; xEnv = config.systemd.services.display-manager.environment; - sddm = cfg.package.override(old: { + sddm = cfg.package.override (old: { withWayland = cfg.wayland.enable; - extraPackages = old.extraPackages or [] ++ cfg.extraPackages; + extraPackages = old.extraPackages or [ ] ++ cfg.extraPackages; }); iniFmt = pkgs.formats.ini { }; + inherit (lib) + concatMapStrings concatStringsSep getExe + attrNames getAttr optionalAttrs optionalString + mkRemovedOptionModule mkRenamedOptionModule mkIf mkEnableOption mkOption mkPackageOption types + ; + xserverWrapper = pkgs.writeShellScript "xserver-wrapper" '' ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} exec systemd-cat -t xserver-wrapper ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} "$@" @@ -38,12 +43,21 @@ let DefaultSession = optionalString (dmcfg.defaultSession != null) "${dmcfg.defaultSession}.desktop"; DisplayServer = if cfg.wayland.enable then "wayland" else "x11"; + } // optionalAttrs (cfg.wayland.compositor == "kwin") { + GreeterEnvironment = concatStringsSep " " [ + "LANG=C.UTF-8" + "QT_WAYLAND_SHELL_INTEGRATION=layer-shell" + ]; + InputMethod = ""; # needed if we are using --inputmethod with kwin }; Theme = { Current = cfg.theme; ThemeDir = "/run/current-system/sw/share/sddm/themes"; FacesDir = "/run/current-system/sw/share/sddm/faces"; + } // optionalAttrs (cfg.theme == "breeze") { + CursorTheme = "breeze_cursors"; + CursorSize = 24; }; Users = { @@ -69,7 +83,7 @@ let SessionDir = "${dmcfg.sessionData.desktops}/share/wayland-sessions"; CompositorCommand = lib.optionalString cfg.wayland.enable cfg.wayland.compositorCommand; }; - } // lib.optionalAttrs dmcfg.autoLogin.enable { + } // optionalAttrs dmcfg.autoLogin.enable { Autologin = { User = dmcfg.autoLogin.user; Session = autoLoginSessionName; @@ -83,6 +97,34 @@ let autoLoginSessionName = "${dmcfg.sessionData.autologinSession}.desktop"; + compositorCmds = { + kwin = concatStringsSep " " [ + "${lib.getBin pkgs.kdePackages.kwin}/bin/kwin_wayland" + "--no-global-shortcuts" + "--no-kactivities" + "--no-lockscreen" + "--locale1" + ]; + # This is basically the upstream default, but with Weston referenced by full path + # and the configuration generated from NixOS options. + weston = + let + westonIni = (pkgs.formats.ini { }).generate "weston.ini" { + libinput = { + enable-tap = xcfg.libinput.mouse.tapping; + left-handed = xcfg.libinput.mouse.leftHanded; + }; + keyboard = { + keymap_model = xcfg.xkb.model; + keymap_layout = xcfg.xkb.layout; + keymap_variant = xcfg.xkb.variant; + keymap_options = xcfg.xkb.options; + }; + }; + in + "${getExe pkgs.weston} --shell=kiosk -c ${westonIni}"; + }; + in { imports = [ @@ -111,7 +153,7 @@ in ''; }; - package = mkPackageOption pkgs [ "plasma5Packages" "sddm" ] {}; + package = mkPackageOption pkgs [ "plasma5Packages" "sddm" ] { }; enableHidpi = mkOption { type = types.bool; @@ -145,7 +187,7 @@ in extraPackages = mkOption { type = types.listOf types.package; - default = []; + default = [ ]; defaultText = "[]"; description = lib.mdDoc '' Extra Qt plugins / QML libraries to add to the environment. @@ -206,24 +248,16 @@ in wayland = { enable = mkEnableOption "experimental Wayland support"; + compositor = mkOption { + description = lib.mdDoc "The compositor to use: ${lib.concatStringsSep ", " (builtins.attrNames compositorCmds)}"; + type = types.enum (builtins.attrNames compositorCmds); + default = "weston"; + }; + compositorCommand = mkOption { type = types.str; internal = true; - - # This is basically the upstream default, but with Weston referenced by full path - # and the configuration generated from NixOS options. - default = let westonIni = (pkgs.formats.ini {}).generate "weston.ini" { - libinput = { - enable-tap = xcfg.libinput.mouse.tapping; - left-handed = xcfg.libinput.mouse.leftHanded; - }; - keyboard = { - keymap_model = xcfg.xkb.model; - keymap_layout = xcfg.xkb.layout; - keymap_variant = xcfg.xkb.variant; - keymap_options = xcfg.xkb.options; - }; - }; in "${pkgs.weston}/bin/weston --shell=kiosk -c ${westonIni}"; + default = compositorCmds.${cfg.wayland.compositor}; description = lib.mdDoc "Command used to start the selected compositor"; }; }; @@ -247,8 +281,6 @@ in } ]; - services.xserver.displayManager.job.execCmd = "exec /run/current-system/sw/bin/sddm"; - security.pam.services = { sddm.text = '' auth substack login @@ -293,30 +325,41 @@ in uid = config.ids.uids.sddm; }; - environment.etc."sddm.conf".source = cfgFile; - environment.pathsToLink = [ - "/share/sddm" - ]; + environment = { + etc."sddm.conf".source = cfgFile; + pathsToLink = [ + "/share/sddm" + ]; + systemPackages = [ sddm ]; + }; users.groups.sddm.gid = config.ids.gids.sddm; - environment.systemPackages = [ sddm ]; - services.dbus.packages = [ sddm ]; - systemd.tmpfiles.packages = [ sddm ]; - - # We're not using the upstream unit, so copy these: https://github.com/sddm/sddm/blob/develop/services/sddm.service.in - systemd.services.display-manager.after = [ - "systemd-user-sessions.service" - "getty@tty7.service" - "plymouth-quit.service" - "systemd-logind.service" - ]; - systemd.services.display-manager.conflicts = [ - "getty@tty7.service" - ]; + services = { + dbus.packages = [ sddm ]; + xserver = { + displayManager.job.execCmd = "exec /run/current-system/sw/bin/sddm"; + # To enable user switching, allow sddm to allocate TTYs/displays dynamically. + tty = null; + display = null; + }; + }; - # To enable user switching, allow sddm to allocate TTYs/displays dynamically. - services.xserver.tty = null; - services.xserver.display = null; + systemd = { + tmpfiles.packages = [ sddm ]; + + # We're not using the upstream unit, so copy these: https://github.com/sddm/sddm/blob/develop/services/sddm.service.in + services.display-manager = { + after = [ + "systemd-user-sessions.service" + "getty@tty7.service" + "plymouth-quit.service" + "systemd-logind.service" + ]; + conflicts = [ + "getty@tty7.service" + ]; + }; + }; }; } diff --git a/nixos/modules/services/x11/window-managers/nimdow.nix b/nixos/modules/services/x11/window-managers/nimdow.nix index de3192876024..9cee4bb271a5 100644 --- a/nixos/modules/services/x11/window-managers/nimdow.nix +++ b/nixos/modules/services/x11/window-managers/nimdow.nix @@ -8,16 +8,23 @@ in { options = { services.xserver.windowManager.nimdow.enable = mkEnableOption (lib.mdDoc "nimdow"); + services.xserver.windowManager.nimdow.package = mkOption { + type = types.package; + default = pkgs.nimdow; + defaultText = "pkgs.nimdow"; + description = lib.mdDoc "nimdow package to use"; + }; }; + config = mkIf cfg.enable { services.xserver.windowManager.session = singleton { name = "nimdow"; start = '' - ${pkgs.nimdow}/bin/nimdow & + ${cfg.package}/bin/nimdow & waitPID=$! ''; }; - environment.systemPackages = [ pkgs.nimdow ]; + environment.systemPackages = [ cfg.package pkgs.st ]; }; } diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix index c35446bf405b..2962f2851fa9 100644 --- a/nixos/modules/services/x11/window-managers/xmonad.nix +++ b/nixos/modules/services/x11/window-managers/xmonad.nix @@ -37,7 +37,7 @@ let xmonad = if (cfg.config != null) then xmonad-config else xmonad-vanilla; in { - meta.maintainers = with maintainers; [ lassulus xaverdh ivanbrennan ]; + meta.maintainers = with maintainers; [ lassulus xaverdh ivanbrennan slotThe ]; options = { services.xserver.windowManager.xmonad = { diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 3d7474e18263..4e0235f9ad1d 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -749,7 +749,7 @@ in boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288; boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288; - programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3; + programs.gnupg.agent.pinentryPackage = lib.mkOverride 1100 pkgs.pinentry-gnome3; systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix index b0ac857feb4b..950cff386d02 100644 --- a/nixos/modules/system/boot/kernel.nix +++ b/nixos/modules/system/boot/kernel.nix @@ -233,7 +233,9 @@ in symlinks because modprobe only supports one directory. ''; # Convert the list of path to only one path. - apply = pkgs.aggregateModules; + apply = let + kernel-name = config.boot.kernelPackages.kernel.name or "kernel"; + in modules: (pkgs.aggregateModules modules).override { name = kernel-name + "-modules"; }; }; system.requiredKernelConfig = mkOption { @@ -299,6 +301,7 @@ in "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" + "hid_corsair" ] ++ optionals pkgs.stdenv.hostPlatform.isx86 [ # Misc. x86 keyboard stuff. diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 86a3875e2c67..3020734783e7 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -982,8 +982,10 @@ in } { assertion = config.boot.initrd.systemd.enable -> !luks.fido2Support; message = '' - systemd stage 1 does not support configuring FIDO2 unlocking through `boot.initrd.luks.devices.<name>.fido2`. - Use systemd-cryptenroll(1) to configure FIDO2 support. + systemd stage 1 does not support configuring FIDO2 unlocking through `boot.initrd.luks.fido2Support`. + Use systemd-cryptenroll(1) to configure FIDO2 support, and set + `boot.initrd.luks.devices.''${DEVICE}.crypttabExtraOpts` as appropriate per crypttab(5) + (e.g. `fido2-device=auto`). ''; } # TODO diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index b6b0f64b94c8..9b0d750d12ce 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -729,8 +729,8 @@ let (assertInt "FirewallMark") (assertRange "FirewallMark" 1 4294967295) (assertInt "Priority") - (assertPort "SourcePort") - (assertPort "DestinationPort") + (assertPortOrPortRange "SourcePort") + (assertPortOrPortRange "DestinationPort") (assertValueOneOf "InvertRule" boolValues) (assertValueOneOf "Family" ["ipv4" "ipv6" "both"]) (assertInt "SuppressPrefixLength") diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 90a74c0ac578..02a3f5113cc0 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -13,15 +13,11 @@ let kernel-name = config.boot.kernelPackages.kernel.name or "kernel"; - modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; }; - firmware = config.hardware.firmware; - - # Determine the set of modules that we need to mount the root FS. modulesClosure = pkgs.makeModulesClosure { rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules; - kernel = modulesTree; - firmware = firmware; + kernel = config.system.modulesTree; + firmware = config.hardware.firmware; allowMissing = false; }; @@ -688,7 +684,7 @@ in config = mkIf config.boot.initrd.enable { assertions = [ - { assertion = any (fs: fs.mountPoint == "/") fileSystems; + { assertion = !config.boot.initrd.systemd.enable -> any (fs: fs.mountPoint == "/") fileSystems; message = "The ‘fileSystems’ option does not specify your root file system."; } { assertion = let inherit (config.boot) resumeDevice; in diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index f83837fbc6d4..e4f61db0cd02 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -91,13 +91,11 @@ let }; kernel-name = config.boot.kernelPackages.kernel.name or "kernel"; - modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; }; - firmware = config.hardware.firmware; # Determine the set of modules that we need to mount the root FS. modulesClosure = pkgs.makeModulesClosure { rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules; - kernel = modulesTree; - firmware = firmware; + kernel = config.system.modulesTree; + firmware = config.hardware.firmware; allowMissing = false; }; @@ -212,6 +210,19 @@ in { default = []; }; + root = lib.mkOption { + type = lib.types.enum [ "fstab" "gpt-auto" ]; + default = "fstab"; + example = "gpt-auto"; + description = '' + Controls how systemd will interpret the root FS in initrd. See + {manpage}`kernel-command-line(7)`. NixOS currently does not + allow specifying the root file system itself this + way. Instead, the `fstab` value is used in order to interpret + the root file system specified with the `fileSystems` option. + ''; + }; + emergencyAccess = mkOption { type = with types; oneOf [ bool (nullOr (passwdEntry str)) ]; description = lib.mdDoc '' @@ -342,7 +353,12 @@ in { }; config = mkIf (config.boot.initrd.enable && cfg.enable) { - assertions = map (name: { + assertions = [ + { + assertion = cfg.root == "fstab" -> any (fs: fs.mountPoint == "/") (builtins.attrValues config.fileSystems); + message = "The ‘fileSystems’ option does not specify your root file system."; + } + ] ++ map (name: { assertion = lib.attrByPath name (throw "impossible") config.boot.initrd == ""; message = '' systemd stage 1 does not support 'boot.initrd.${lib.concatStringsSep "." name}'. Please @@ -371,7 +387,12 @@ in { "autofs" # systemd-cryptenroll ] ++ lib.optional cfg.enableTpm2 "tpm-tis" - ++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb"; + ++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb" + ++ lib.optional cfg.package.withEfi "efivarfs"; + + boot.kernelParams = [ + "root=${config.boot.initrd.systemd.root}" + ] ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}"; boot.initrd.systemd = { initrdBin = [pkgs.bash pkgs.coreutils cfg.package.kmod cfg.package]; @@ -495,7 +516,7 @@ in { case $o in init=*) IFS== read -r -a initParam <<< "$o" - closure="$(dirname "''${initParam[1]}")" + closure="''${initParam[1]}" ;; esac done @@ -506,6 +527,13 @@ in { exit 1 fi + # Resolve symlinks in the init parameter. We need this for some boot loaders + # (e.g. boot.loader.generationsDir). + closure="$(chroot /sysroot ${pkgs.coreutils}/bin/realpath "$closure")" + + # Assume the directory containing the init script is the closure. + closure="$(dirname "$closure")" + # If we are not booting a NixOS closure (e.g. init=/bin/sh), # we don't know what root to prepare so we don't do anything if ! [ -x "/sysroot$(readlink "/sysroot$closure/prepare-root" || echo "$closure/prepare-root")" ]; then @@ -554,7 +582,5 @@ in { serviceConfig.Type = "oneshot"; }; }; - - boot.kernelParams = lib.mkIf (config.boot.resumeDevice != "") [ "resume=${config.boot.resumeDevice}" ]; }; } diff --git a/nixos/modules/system/boot/timesyncd.nix b/nixos/modules/system/boot/timesyncd.nix index 2666e4cd6b28..ef17c1481abb 100644 --- a/nixos/modules/system/boot/timesyncd.nix +++ b/nixos/modules/system/boot/timesyncd.nix @@ -21,6 +21,9 @@ with lib; type = types.listOf types.str; description = lib.mdDoc '' The set of NTP servers from which to synchronise. + Note if this is set to an empty list, the defaults systemd itself is + compiled with ({0..4}.nixos.pool.ntp.org) apply, + In case you want to disable timesyncd altogether, use the `enable` option. ''; }; extraConfig = mkOption { diff --git a/nixos/modules/system/boot/uki.nix b/nixos/modules/system/boot/uki.nix index 0965b887c12e..c8d3c2f6605f 100644 --- a/nixos/modules/system/boot/uki.nix +++ b/nixos/modules/system/boot/uki.nix @@ -7,8 +7,6 @@ let inherit (pkgs.stdenv.hostPlatform) efiArch; format = pkgs.formats.ini { }; - ukifyConfig = format.generate "ukify.conf" cfg.settings; - in { @@ -48,6 +46,15 @@ in contains and how it is built. ''; }; + + configFile = lib.mkOption { + type = lib.types.path; + description = lib.mdDoc '' + The configuration file passed to {manpage}`ukify(1)` to create the UKI. + + By default this configuration file is created from {option}`boot.uki.settings`. + ''; + }; }; system.boot.loader.ukiFile = lib.mkOption { @@ -80,6 +87,8 @@ in }; }; + boot.uki.configFile = lib.mkOptionDefault (format.generate "ukify.conf" cfg.settings); + system.boot.loader.ukiFile = let name = config.boot.uki.name; @@ -92,7 +101,7 @@ in system.build.uki = pkgs.runCommand config.system.boot.loader.ukiFile { } '' mkdir -p $out ${pkgs.buildPackages.systemdUkify}/lib/systemd/ukify build \ - --config=${ukifyConfig} \ + --config=${cfg.configFile} \ --output="$out/${config.system.boot.loader.ukiFile}" ''; diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 6aa718c1975d..50a54a006415 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -42,8 +42,10 @@ let # Otherwise we get errors on the terminal because bash tries to # setup things like job control. # Note: calling bash explicitly here instead of sh makes sure that - # we can also run non-NixOS guests during tests. - PS1= exec /usr/bin/env bash --norc /dev/hvc0 + # we can also run non-NixOS guests during tests. This, however, is + # mostly futureproofing as the test instrumentation is still very + # tightly coupled to NixOS. + PS1= exec ${pkgs.coreutils}/bin/env bash --norc /dev/hvc0 ''; serviceConfig.KillSignal = "SIGHUP"; }; @@ -121,7 +123,9 @@ in } ]; - contents."/usr/bin/env".source = "${pkgs.coreutils}/bin/env"; + storePaths = [ + "${pkgs.coreutils}/bin/env" + ]; }) ]; diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index c7fe1bed5159..77730178422c 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -79,6 +79,10 @@ in serviceConfig.StandardOutput = "journal+console"; }; + # Amazon-issued AMIs include the SSM Agent by default, so we do the same. + # https://docs.aws.amazon.com/systems-manager/latest/userguide/ami-preinstalled-agent.html + services.amazon-ssm-agent.enable = true; + # Allow root logins only using the SSH key that the user specified # at instance creation time. services.openssh.enable = true; diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index d4fa707b2dd5..5db3a336f85d 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -509,6 +509,12 @@ in for details). ''; } + { + assertion = !lib.strings.hasInfix "_" name; + message = '' + Names containing underscores are not allowed in nixos-containers. Please rename the container '${name}' + ''; + } ]; }; }; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index ac64b85dd486..2c08fdba6c98 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -290,8 +290,8 @@ in { activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix; activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix; activation-perlless = runTest ./activation/perlless.nix; - etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {}; - etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {}; + etcd = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./etcd/etcd.nix {}; + etcd-cluster = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./etcd/etcd-cluster.nix {}; etebase-server = handleTest ./etebase-server.nix {}; etesync-dav = handleTest ./etesync-dav.nix {}; evcc = handleTest ./evcc.nix {}; @@ -464,7 +464,7 @@ in { keymap = handleTest ./keymap.nix {}; knot = handleTest ./knot.nix {}; komga = handleTest ./komga.nix {}; - krb5 = discoverTests (import ./krb5 {}); + krb5 = discoverTests (import ./krb5); ksm = handleTest ./ksm.nix {}; kthxbye = handleTest ./kthxbye.nix {}; kubernetes = handleTestOn ["x86_64-linux"] ./kubernetes {}; @@ -513,6 +513,7 @@ in { mastodon = discoverTests (import ./web-apps/mastodon { inherit handleTestOn; }); pixelfed = discoverTests (import ./web-apps/pixelfed { inherit handleTestOn; }); mate = handleTest ./mate.nix {}; + mate-wayland = handleTest ./mate-wayland.nix {}; matter-server = handleTest ./matter-server.nix {}; matomo = handleTest ./matomo.nix {}; matrix-appservice-irc = handleTest ./matrix/appservice-irc.nix {}; @@ -528,6 +529,7 @@ in { memcached = handleTest ./memcached.nix {}; merecat = handleTest ./merecat.nix {}; metabase = handleTest ./metabase.nix {}; + mihomo = handleTest ./mihomo.nix {}; mindustry = handleTest ./mindustry.nix {}; minecraft = handleTest ./minecraft.nix {}; minecraft-server = handleTest ./minecraft-server.nix {}; @@ -560,6 +562,7 @@ in { munin = handleTest ./munin.nix {}; mutableUsers = handleTest ./mutable-users.nix {}; mxisd = handleTest ./mxisd.nix {}; + mycelium = handleTest ./mycelium {}; mympd = handleTest ./mympd.nix {}; mysql = handleTest ./mysql/mysql.nix {}; mysql-autobackup = handleTest ./mysql/mysql-autobackup.nix {}; @@ -579,6 +582,7 @@ in { ndppd = handleTest ./ndppd.nix {}; nebula = handleTest ./nebula.nix {}; netbird = handleTest ./netbird.nix {}; + nimdow = handleTest ./nimdow.nix {}; neo4j = handleTest ./neo4j.nix {}; netdata = handleTest ./netdata.nix {}; networking.networkd = handleTest ./networking.nix { networkd = true; }; @@ -613,6 +617,7 @@ in { nginx-variants = handleTest ./nginx-variants.nix {}; nifi = handleTestOn ["x86_64-linux"] ./web-apps/nifi.nix {}; nitter = handleTest ./nitter.nix {}; + nix-config = handleTest ./nix-config.nix {}; nix-ld = handleTest ./nix-ld.nix {}; nix-serve = handleTest ./nix-serve.nix {}; nix-serve-ssh = handleTest ./nix-serve-ssh.nix {}; @@ -683,6 +688,7 @@ in { peering-manager = handleTest ./web-apps/peering-manager.nix {}; peertube = handleTestOn ["x86_64-linux"] ./web-apps/peertube.nix {}; peroxide = handleTest ./peroxide.nix {}; + pg_anonymizer = handleTest ./pg_anonymizer.nix {}; pgadmin4 = handleTest ./pgadmin4.nix {}; pgbouncer = handleTest ./pgbouncer.nix {}; pgjwt = handleTest ./pgjwt.nix {}; @@ -727,6 +733,7 @@ in { pppd = handleTest ./pppd.nix {}; predictable-interface-names = handleTest ./predictable-interface-names.nix {}; pretalx = runTest ./web-apps/pretalx.nix; + pretix = runTest ./web-apps/pretix.nix; printing-socket = handleTest ./printing.nix { socket = true; }; printing-service = handleTest ./printing.nix { socket = false; }; privoxy = handleTest ./privoxy.nix {}; diff --git a/nixos/tests/budgie.nix b/nixos/tests/budgie.nix index ca898bba1bc4..5228e869b056 100644 --- a/nixos/tests/budgie.nix +++ b/nixos/tests/budgie.nix @@ -29,6 +29,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { testScript = { nodes, ... }: let user = nodes.machine.users.users.alice; + env = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${toString user.uid}/bus DISPLAY=:0"; + su = command: "su - ${user.name} -c '${env} ${command}'"; in '' with subtest("Wait for login"): @@ -47,21 +49,46 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.succeed("getfacl -p /dev/snd/timer | grep -q ${user.name}") with subtest("Check if Budgie session components actually start"): - machine.wait_until_succeeds("pgrep budgie-daemon") + for i in ["budgie-daemon", "budgie-panel", "budgie-wm", "budgie-desktop-view", "gsd-media-keys"]: + machine.wait_until_succeeds(f"pgrep -f {i}") + # We don't check xwininfo for budgie-wm. + # See https://github.com/NixOS/nixpkgs/pull/216737#discussion_r1155312754 machine.wait_for_window("budgie-daemon") - machine.wait_until_succeeds("pgrep budgie-panel") machine.wait_for_window("budgie-panel") - # We don't check xwininfo for this one. - # See https://github.com/NixOS/nixpkgs/pull/216737#discussion_r1155312754 - machine.wait_until_succeeds("pgrep budgie-wm") - with subtest("Open MATE terminal"): - machine.succeed("su - ${user.name} -c 'DISPLAY=:0 mate-terminal >&2 &'") - machine.wait_for_window("Terminal") + with subtest("Check if various environment variables are set"): + cmd = "xargs --null --max-args=1 echo < /proc/$(pgrep -xf /run/current-system/sw/bin/budgie-wm)/environ" + machine.succeed(f"{cmd} | grep 'XDG_CURRENT_DESKTOP' | grep 'Budgie:GNOME'") + machine.succeed(f"{cmd} | grep 'BUDGIE_PLUGIN_DATADIR' | grep '${pkgs.budgie.budgie-desktop-with-plugins.pname}'") + + with subtest("Open run dialog"): + machine.send_key("alt-f2") + machine.wait_for_window("budgie-run-dialog") + machine.sleep(2) + machine.screenshot("run_dialog") + machine.send_key("esc") + + with subtest("Open Budgie Control Center"): + machine.succeed("${su "budgie-control-center >&2 &"}") + machine.wait_for_window("Budgie Control Center") + + with subtest("Lock the screen"): + machine.succeed("${su "budgie-screensaver-command -l >&2 &"}") + machine.wait_until_succeeds("${su "budgie-screensaver-command -q"} | grep 'The screensaver is active'") + machine.sleep(2) + machine.send_chars("${user.password}", delay=0.5) + machine.screenshot("budgie_screensaver") + machine.send_chars("\n") + machine.wait_until_succeeds("${su "budgie-screensaver-command -q"} | grep 'The screensaver is inactive'") + machine.sleep(2) + + with subtest("Open GNOME terminal"): + machine.succeed("${su "gnome-terminal"}") + machine.wait_for_window("${user.name}@machine: ~") - with subtest("Check if budgie-wm has ever coredumped"): - machine.fail("coredumpctl --json=short | grep budgie-wm") - machine.sleep(20) + with subtest("Check if Budgie has ever coredumped"): + machine.fail("coredumpctl --json=short | grep budgie") + machine.sleep(10) machine.screenshot("screen") ''; }) diff --git a/nixos/tests/drawterm.nix b/nixos/tests/drawterm.nix index 1d444bb55433..3594343853c0 100644 --- a/nixos/tests/drawterm.nix +++ b/nixos/tests/drawterm.nix @@ -38,11 +38,24 @@ let def drawterm_running(): machine.succeed("pgrep drawterm") + # cage is a bit wonky here. + # it seems to lag behind drawing + # and somehow needs a single input character + # in order to get the first prompt to show up. + # This is not present in any other compositor + # as far as I know, and after spending a couple + # hours with the upstream source trying to deduce + # how to perhaps fix it, I figured just polling is OK. + @polling_condition + def cpu_shown_up(): + machine.send_chars(".") + machine.wait_for_text("cpu", 1) + start_all() machine.wait_for_unit("graphical.target") drawterm_running.wait() # type: ignore[union-attr] - machine.wait_for_text("cpu") + cpu_shown_up.wait() # type: ignore[union-attr] machine.send_chars("cpu\n") machine.wait_for_text("auth") machine.send_chars("cpu\n") diff --git a/nixos/tests/etcd-cluster.nix b/nixos/tests/etcd/etcd-cluster.nix index c77c0dd73c25..734d56dbc223 100644 --- a/nixos/tests/etcd-cluster.nix +++ b/nixos/tests/etcd/etcd-cluster.nix @@ -1,6 +1,6 @@ # This test runs simple etcd cluster -import ./make-test-python.nix ({ pkgs, ... } : let +import ../make-test-python.nix ({ pkgs, ... } : let runWithOpenSSL = file: cmd: pkgs.runCommand file { buildInputs = [ pkgs.openssl ]; diff --git a/nixos/tests/etcd.nix b/nixos/tests/etcd/etcd.nix index 79857778ae1b..a32d0f9a55d1 100644 --- a/nixos/tests/etcd.nix +++ b/nixos/tests/etcd/etcd.nix @@ -1,6 +1,6 @@ # This test runs simple etcd node -import ./make-test-python.nix ({ pkgs, ... } : { +import ../make-test-python.nix ({ pkgs, ... } : { name = "etcd"; meta = with pkgs.lib.maintainers; { diff --git a/nixos/tests/freetube.nix b/nixos/tests/freetube.nix index faa534938227..10f0773cb884 100644 --- a/nixos/tests/freetube.nix +++ b/nixos/tests/freetube.nix @@ -40,4 +40,4 @@ let ''; }); in -builtins.mapAttrs (k: v: mkTest k v { }) tests +builtins.mapAttrs (k: v: mkTest k v) tests diff --git a/nixos/tests/hibernate.nix b/nixos/tests/hibernate.nix index 296aa9ba68b9..6de287f63e08 100644 --- a/nixos/tests/hibernate.nix +++ b/nixos/tests/hibernate.nix @@ -24,8 +24,8 @@ makeTest { virtualisation.useNixStoreImage = true; swapDevices = lib.mkOverride 0 [ { device = "/dev/vdc"; options = [ "x-systemd.makefs" ]; } ]; - boot.resumeDevice = "/dev/vdc"; boot.initrd.systemd.enable = systemdStage1; + virtualisation.useEFIBoot = true; }; }; diff --git a/nixos/tests/incus/default.nix b/nixos/tests/incus/default.nix index 474a621c5ce9..32bc5396a164 100644 --- a/nixos/tests/incus/default.nix +++ b/nixos/tests/incus/default.nix @@ -14,6 +14,7 @@ openvswitch = import ./openvswitch.nix { inherit system pkgs; }; preseed = import ./preseed.nix { inherit system pkgs; }; socket-activated = import ./socket-activated.nix { inherit system pkgs; }; + storage = import ./storage.nix { inherit system pkgs; }; ui = import ./ui.nix {inherit system pkgs;}; virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix { inherit system pkgs; }; } diff --git a/nixos/tests/incus/storage.nix b/nixos/tests/incus/storage.nix new file mode 100644 index 000000000000..190f4f7451c2 --- /dev/null +++ b/nixos/tests/incus/storage.nix @@ -0,0 +1,46 @@ +import ../make-test-python.nix ( + { pkgs, lib, ... }: + + { + name = "incus-storage"; + + meta = { + maintainers = lib.teams.lxc.members; + }; + + nodes.machine = + { lib, ... }: + { + boot.supportedFilesystems = [ "zfs" ]; + boot.zfs.forceImportRoot = false; + environment.systemPackages = [ pkgs.parted ]; + networking.hostId = "01234567"; + networking.nftables.enable = true; + + virtualisation = { + emptyDiskImages = [ 2048 ]; + incus.enable = true; + }; + }; + + testScript = '' + machine.wait_for_unit("incus.service") + + with subtest("Verify zfs pool created and usable"): + machine.succeed( + "zpool status", + "parted --script /dev/vdb mklabel gpt", + "zpool create zfs_pool /dev/vdb", + ) + + machine.succeed("incus storage create zfs_pool zfs source=zfs_pool/incus") + machine.succeed("zfs list zfs_pool/incus") + machine.succeed("incus storage volume create zfs_pool test_fs --type filesystem") + machine.succeed("incus storage volume create zfs_pool test_vol --type block") + machine.succeed("incus storage show zfs_pool") + machine.succeed("incus storage volume list zfs_pool") + machine.succeed("incus storage volume show zfs_pool test_fs") + machine.succeed("incus storage volume show zfs_pool test_vol") + ''; + } +) diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix index 662017935412..d10256d91d7f 100644 --- a/nixos/tests/installer-systemd-stage-1.nix +++ b/nixos/tests/installer-systemd-stage-1.nix @@ -37,6 +37,7 @@ clevisLuksFallback clevisZfs clevisZfsFallback + gptAutoRoot ; } diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 97bb7f8def59..1de886d6a0d1 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -82,6 +82,7 @@ let testScriptFun = { bootLoader, createPartitions, grubDevice, grubUseEfi, grubIdentifier , postInstallCommands, preBootCommands, postBootCommands, extraConfig , testSpecialisationConfig, testFlakeSwitch, clevisTest, clevisFallbackTest + , disableFileSystems }: let qemu-common = import ../lib/qemu-common.nix { inherit (pkgs) lib pkgs; }; @@ -163,7 +164,7 @@ let ${createPartitions} with subtest("Create the NixOS configuration"): - machine.succeed("nixos-generate-config --root /mnt") + machine.succeed("nixos-generate-config ${optionalString disableFileSystems "--no-filesystems"} --root /mnt") machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2") machine.copy_from_host( "${ makeConfig { @@ -433,6 +434,7 @@ let , testFlakeSwitch ? false , clevisTest ? false , clevisFallbackTest ? false + , disableFileSystems ? false }: makeTest { inherit enableOCR; @@ -541,7 +543,8 @@ let testScript = testScriptFun { inherit bootLoader createPartitions postInstallCommands preBootCommands postBootCommands grubDevice grubIdentifier grubUseEfi extraConfig - testSpecialisationConfig testFlakeSwitch clevisTest clevisFallbackTest; + testSpecialisationConfig testFlakeSwitch clevisTest clevisFallbackTest + disableFileSystems; }; }; @@ -1414,4 +1417,39 @@ in { }; }; }; + + gptAutoRoot = let + rootPartType = { + ia32 = "44479540-F297-41B2-9AF7-D131D5F0458A"; + x64 = "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709"; + arm = "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3"; + aa64 = "B921B045-1DF0-41C3-AF44-4C6F280D3FAE"; + }.${pkgs.stdenv.hostPlatform.efiArch}; + in makeInstallerTest "gptAutoRoot" { + disableFileSystems = true; + createPartitions = '' + machine.succeed( + "sgdisk --zap-all /dev/vda", + "sgdisk --new=1:0:+100M --typecode=0:ef00 /dev/vda", # /boot + "sgdisk --new=2:0:+1G --typecode=0:8200 /dev/vda", # swap + "sgdisk --new=3:0:+5G --typecode=0:${rootPartType} /dev/vda", # / + "udevadm settle", + + "mkfs.vfat /dev/vda1", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext4 -L root /dev/vda3", + "udevadm settle", + + "mount /dev/vda3 /mnt", + "mkdir -p /mnt/boot", + "mount /dev/vda1 /mnt/boot" + ) + ''; + bootLoader = "systemd-boot"; + extraConfig = '' + boot.initrd.systemd.root = "gpt-auto"; + boot.initrd.supportedFilesystems = ["ext4"]; + ''; + }; } diff --git a/nixos/tests/kea.nix b/nixos/tests/kea.nix index c8ecf771fa13..98a8e93a0760 100644 --- a/nixos/tests/kea.nix +++ b/nixos/tests/kea.nix @@ -44,6 +44,11 @@ import ./make-test-python.nix ({ pkgs, lib, ...}: { name = "/var/lib/kea/dhcp4.leases"; }; + control-socket = { + socket-type = "unix"; + socket-name = "/run/kea/dhcp4.sock"; + }; + interfaces-config = { dhcp-socket-type = "raw"; interfaces = [ @@ -89,6 +94,25 @@ import ./make-test-python.nix ({ pkgs, lib, ...}: { }; }; }; + + services.kea.ctrl-agent = { + enable = true; + settings = { + http-host = "127.0.0.1"; + http-port = 8000; + control-sockets.dhcp4 = { + socket-type = "unix"; + socket-name = "/run/kea/dhcp4.sock"; + }; + }; + }; + + services.prometheus.exporters.kea = { + enable = true; + controlSocketPaths = [ + "http://127.0.0.1:8000" + ]; + }; }; nameserver = { config, pkgs, ... }: { @@ -182,5 +206,7 @@ import ./make-test-python.nix ({ pkgs, lib, ...}: { client.wait_until_succeeds("ping -c 5 10.0.0.1") router.wait_until_succeeds("ping -c 5 10.0.0.3") nameserver.wait_until_succeeds("kdig +short client.lan.nixos.test @10.0.0.2 | grep -q 10.0.0.3") + router.log(router.execute("curl 127.0.0.1:9547")[1]) + router.succeed("curl --no-buffer 127.0.0.1:9547 | grep -qE '^kea_dhcp4_addresses_assigned_total.*1.0$'") ''; }) diff --git a/nixos/tests/keycloak.nix b/nixos/tests/keycloak.nix index 228e57d1cdd6..67b412c80961 100644 --- a/nixos/tests/keycloak.nix +++ b/nixos/tests/keycloak.nix @@ -6,8 +6,8 @@ let certs = import ./common/acme/server/snakeoil-certs.nix; frontendUrl = "https://${certs.domain}"; - keycloakTest = import ./make-test-python.nix ( - { pkgs, databaseType, ... }: + keycloakTest = databaseType: import ./make-test-python.nix ( + { pkgs, ... }: let initialAdminPassword = "h4Iho\"JFn't2>iQIR9"; adminPasswordFile = pkgs.writeText "admin-password" "${initialAdminPassword}"; @@ -76,16 +76,18 @@ let enabled = true; realm = "test-realm"; clients = [ client ]; - users = [( - user // { - enabled = true; - credentials = [{ - type = "password"; - temporary = false; - value = password; - }]; - } - )]; + users = [ + ( + user // { + enabled = true; + credentials = [{ + type = "password"; + temporary = false; + value = password; + }]; + } + ) + ]; }; realmDataJson = pkgs.writeText "realm-data.json" (builtins.toJSON realm); @@ -177,7 +179,7 @@ let ); in { - postgres = keycloakTest { databaseType = "postgresql"; }; - mariadb = keycloakTest { databaseType = "mariadb"; }; - mysql = keycloakTest { databaseType = "mysql"; }; + postgres = keycloakTest "postgresql"; + mariadb = keycloakTest "mariadb"; + mysql = keycloakTest "mysql"; } diff --git a/nixos/tests/krb5/default.nix b/nixos/tests/krb5/default.nix index ede085632c63..274ad580cebc 100644 --- a/nixos/tests/krb5/default.nix +++ b/nixos/tests/krb5/default.nix @@ -1,4 +1,3 @@ -{ system ? builtins.currentSystem }: { - example-config = import ./example-config.nix { inherit system; }; + example-config = import ./example-config.nix; } diff --git a/nixos/tests/ladybird.nix b/nixos/tests/ladybird.nix index 4e9ab9a36d13..8ed0f47887c7 100644 --- a/nixos/tests/ladybird.nix +++ b/nixos/tests/ladybird.nix @@ -21,7 +21,7 @@ import ./make-test-python.nix ({ pkgs, ... }: { '' machine.wait_for_x() machine.succeed("echo '<!DOCTYPE html><html><body><h1>Hello world</h1></body></html>' > page.html") - machine.execute("ladybird file://$(pwd)/page.html >&2 &") + machine.execute("Ladybird file://$(pwd)/page.html >&2 &") machine.wait_for_window("Ladybird") machine.sleep(5) machine.wait_for_text("Hello world") diff --git a/nixos/tests/make-test-python.nix b/nixos/tests/make-test-python.nix index 28569f1d2955..32531fffd2bf 100644 --- a/nixos/tests/make-test-python.nix +++ b/nixos/tests/make-test-python.nix @@ -1,5 +1,5 @@ f: { - system ? builtins.currentSystem, + system, pkgs ? import ../.. { inherit system; config = {}; overlays = []; }, ... } @ args: diff --git a/nixos/tests/mate-wayland.nix b/nixos/tests/mate-wayland.nix new file mode 100644 index 000000000000..df39ead286e1 --- /dev/null +++ b/nixos/tests/mate-wayland.nix @@ -0,0 +1,63 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "mate-wayland"; + + meta.maintainers = lib.teams.mate.members; + + nodes.machine = { ... }: { + imports = [ + ./common/user-account.nix + ]; + + services.xserver.enable = true; + services.xserver.displayManager = { + sddm.enable = true; # https://github.com/canonical/lightdm/issues/63 + sddm.wayland.enable = true; + defaultSession = "MATE"; + autoLogin = { + enable = true; + user = "alice"; + }; + }; + services.xserver.desktopManager.mate.enableWaylandSession = true; + + hardware.pulseaudio.enable = true; + + # Need to switch to a different GPU driver than the default one (-vga std) so that wayfire can launch: + virtualisation.qemu.options = [ "-vga none -device virtio-gpu-pci" ]; + }; + + enableOCR = true; + + testScript = { nodes, ... }: + let + user = nodes.machine.users.users.alice; + in + '' + machine.wait_for_unit("display-manager.service") + + with subtest("Wait for Wayland server"): + machine.wait_for_file("/run/user/${toString user.uid}/wayland-1") + + with subtest("Check if MATE session components actually start"): + for i in ["wayfire", "mate-panel", "mate-wayland.sh", "mate-wayland-components.sh"]: + machine.wait_until_succeeds(f"pgrep -f {i}") + machine.wait_for_text('(Applications|Places|System)') + # It is expected that this applet doesn't work in Wayland + machine.wait_for_text('WorkspaceSwitcherApplet') + + with subtest("Check if various environment variables are set"): + cmd = "xargs --null --max-args=1 echo < /proc/$(pgrep -xf mate-panel)/environ" + machine.succeed(f"{cmd} | grep 'XDG_SESSION_TYPE' | grep 'wayland'") + machine.succeed(f"{cmd} | grep 'XDG_SESSION_DESKTOP' | grep 'MATE'") + machine.succeed(f"{cmd} | grep 'MATE_PANEL_APPLETS_DIR' | grep '${pkgs.mate.mate-panel-with-applets.pname}'") + + with subtest("Check if Wayfire config is properly configured"): + for i in ["button_style = mate", "firedecor", "mate-wayland-components.sh"]: + machine.wait_until_succeeds(f"cat /home/${user.name}/.config/mate/wayfire.ini | grep '{i}'") + + with subtest("Check if Wayfire has ever coredumped"): + machine.fail("coredumpctl --json=short | grep wayfire") + machine.sleep(10) + machine.screenshot("screen") + ''; +}) diff --git a/nixos/tests/mate.nix b/nixos/tests/mate.nix index 48582e18d520..1252ec43cf3d 100644 --- a/nixos/tests/mate.nix +++ b/nixos/tests/mate.nix @@ -54,6 +54,15 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.wait_for_text('(Applications|Places|System)') machine.wait_for_text('(Computer|Home|Trash)') + with subtest("Check if various environment variables are set"): + machine.succeed("xargs --null --max-args=1 echo < /proc/$(pgrep -xf marco)/environ | grep 'XDG_CURRENT_DESKTOP' | grep 'MATE'") + # From mate-panel-with-applets packaging + machine.succeed("xargs --null --max-args=1 echo < /proc/$(pgrep -xf mate-panel)/environ | grep 'MATE_PANEL_APPLETS_DIR' | grep '${pkgs.mate.mate-panel-with-applets.pname}'") + + with subtest("Check if applets are built with in-process support"): + # This is needed for Wayland support + machine.fail("pgrep -fa clock-applet") + with subtest("Lock the screen"): machine.wait_until_succeeds("su - ${user.name} -c '${env} mate-screensaver-command -q' | grep 'The screensaver is inactive'") machine.succeed("su - ${user.name} -c '${env} mate-screensaver-command -l >&2 &'") diff --git a/nixos/tests/mihomo.nix b/nixos/tests/mihomo.nix new file mode 100644 index 000000000000..472d10050f7f --- /dev/null +++ b/nixos/tests/mihomo.nix @@ -0,0 +1,44 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "mihomo"; + meta.maintainers = with pkgs.lib.maintainers; [ Guanran928 ]; + + nodes.machine = { + environment.systemPackages = [ pkgs.curl ]; + + services.nginx = { + enable = true; + statusPage = true; + }; + + services.mihomo = { + enable = true; + configFile = pkgs.writeTextFile { + name = "config.yaml"; + text = '' + mixed-port: 7890 + external-controller: 127.0.0.1:9090 + authentication: + - "user:supersecret" + ''; + }; + }; + }; + + testScript = '' + # Wait until it starts + machine.wait_for_unit("nginx.service") + machine.wait_for_unit("mihomo.service") + machine.wait_for_open_port(80) + machine.wait_for_open_port(7890) + machine.wait_for_open_port(9090) + + # Proxy + machine.succeed("curl --fail --max-time 10 --proxy http://user:supersecret@localhost:7890 http://localhost") + machine.succeed("curl --fail --max-time 10 --proxy socks5://user:supersecret@localhost:7890 http://localhost") + machine.fail("curl --fail --max-time 10 --proxy http://user:supervillain@localhost:7890 http://localhost") + machine.fail("curl --fail --max-time 10 --proxy socks5://user:supervillain@localhost:7890 http://localhost") + + # Web UI + machine.succeed("curl --fail http://localhost:9090") == '{"hello":"clash"}' + ''; +}) diff --git a/nixos/tests/mycelium/default.nix b/nixos/tests/mycelium/default.nix new file mode 100644 index 000000000000..f0d72436843c --- /dev/null +++ b/nixos/tests/mycelium/default.nix @@ -0,0 +1,57 @@ +import ../make-test-python.nix ({ lib, ... }: let + peer1-ip = "531:c350:28c1:dfde:ea6d:77d1:a60b:7209"; + peer2-ip = "49f:3942:3a55:d100:4c78:c558:c4f:695b"; +in + { + name = "mycelium"; + meta.maintainers = with lib.maintainers; [ lassulus ]; + + nodes = { + + peer1 = { config, pkgs, ... }: { + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth1.ipv4.addresses = [{ + address = "192.168.1.11"; + prefixLength = 24; + }]; + + services.mycelium = { + enable = true; + addHostedPublicNodes = false; + openFirewall = true; + keyFile = ./peer1.key; + peers = [ + "quic://192.168.1.12:9651" + "tcp://192.168.1.12:9651" + ]; + }; + }; + + peer2 = { config, pkgs, ... }: { + virtualisation.vlans = [ 1 ]; + networking.interfaces.eth1.ipv4.addresses = [{ + address = "192.168.1.12"; + prefixLength = 24; + }]; + + services.mycelium = { + enable = true; + addHostedPublicNodes = false; + openFirewall = true; + keyFile = ./peer2.key; + }; + }; + }; + + testScript = '' + start_all() + + peer1.wait_for_unit("network-online.target") + peer2.wait_for_unit("network-online.target") + peer1.wait_for_unit("mycelium.service") + peer2.wait_for_unit("mycelium.service") + + peer1.succeed("ping -c5 ${peer2-ip}") + peer2.succeed("ping -c5 ${peer1-ip}") + ''; + }) diff --git a/nixos/tests/mycelium/peer1.key b/nixos/tests/mycelium/peer1.key new file mode 100644 index 000000000000..db1cf9e72fe4 --- /dev/null +++ b/nixos/tests/mycelium/peer1.key @@ -0,0 +1 @@ +s B0dRH5u?^ \ No newline at end of file diff --git a/nixos/tests/mycelium/peer2.key b/nixos/tests/mycelium/peer2.key new file mode 100644 index 000000000000..7e757de48efb --- /dev/null +++ b/nixos/tests/mycelium/peer2.key @@ -0,0 +1 @@ +X1yGՅSAMe7] \ No newline at end of file diff --git a/nixos/tests/nimdow.nix b/nixos/tests/nimdow.nix new file mode 100644 index 000000000000..cefe46edc5fb --- /dev/null +++ b/nixos/tests/nimdow.nix @@ -0,0 +1,25 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "nimdow"; + meta = with pkgs.lib.maintainers; { + maintainers = [ marcusramberg ]; + }; + + nodes.machine = { lib, ... }: { + imports = [ ./common/x11.nix ./common/user-account.nix ]; + test-support.displayManager.auto.user = "alice"; + services.xserver.displayManager.defaultSession = lib.mkForce "none+nimdow"; + services.xserver.windowManager.nimdow.enable = true; + }; + + testScript = { ... }: '' + with subtest("ensure x starts"): + machine.wait_for_x() + machine.wait_for_file("/home/alice/.Xauthority") + machine.succeed("xauth merge ~alice/.Xauthority") + + with subtest("ensure we can open a new terminal"): + machine.send_key("meta_l-ret") + machine.wait_for_window(r"alice.*?machine") + machine.screenshot("terminal") + ''; +}) diff --git a/nixos/tests/nix-config.nix b/nixos/tests/nix-config.nix new file mode 100644 index 000000000000..907e886def35 --- /dev/null +++ b/nixos/tests/nix-config.nix @@ -0,0 +1,18 @@ +import ./make-test-python.nix ({ pkgs, ... }: +{ + name = "nix-config"; + nodes.machine = { pkgs, ... }: { + nix.settings = { + nix-path = [ "nonextra=/etc/value.nix" ]; + extra-nix-path = [ "extra=/etc/value.nix" ]; + }; + environment.etc."value.nix".text = "42"; + }; + testScript = '' + start_all() + machine.wait_for_unit("nix-daemon.socket") + # regression test for the workaround for https://github.com/NixOS/nix/issues/9487 + print(machine.succeed("nix-instantiate --find-file extra")) + print(machine.succeed("nix-instantiate --find-file nonextra")) + ''; +}) diff --git a/nixos/tests/nixops/default.nix b/nixos/tests/nixops/default.nix index 8477e5059fca..6468b8c38224 100644 --- a/nixos/tests/nixops/default.nix +++ b/nixos/tests/nixops/default.nix @@ -93,23 +93,5 @@ let inherit (import ../ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; - /* - Return a store path with a closure containing everything including - derivations and all build dependency outputs, all the way down. - */ - allDrvOutputs = pkg: - let name = "allDrvOutputs-${pkg.pname or pkg.name or "unknown"}"; - in - pkgs.runCommand name { refs = pkgs.writeReferencesToFile pkg.drvPath; } '' - touch $out - while read ref; do - case $ref in - *.drv) - cat $ref >>$out - ;; - esac - done <$refs - ''; - in tests diff --git a/nixos/tests/opensearch.nix b/nixos/tests/opensearch.nix index 2887ac967765..7d37583464cb 100644 --- a/nixos/tests/opensearch.nix +++ b/nixos/tests/opensearch.nix @@ -1,7 +1,7 @@ let - opensearchTest = + opensearchTest = extraSettings: import ./make-test-python.nix ( - { pkgs, lib, extraSettings ? {} }: { + { pkgs, lib, ... }: { name = "opensearch"; meta.maintainers = with pkgs.lib.maintainers; [ shyim ]; @@ -27,20 +27,18 @@ in { opensearch = opensearchTest {}; opensearchCustomPathAndUser = opensearchTest { - extraSettings = { - services.opensearch.dataDir = "/var/opensearch_test"; - services.opensearch.user = "open_search"; - services.opensearch.group = "open_search"; - systemd.tmpfiles.rules = [ - "d /var/opensearch_test 0700 open_search open_search -" - ]; - users = { - groups.open_search = {}; - users.open_search = { - description = "OpenSearch daemon user"; - group = "open_search"; - isSystemUser = true; - }; + services.opensearch.dataDir = "/var/opensearch_test"; + services.opensearch.user = "open_search"; + services.opensearch.group = "open_search"; + systemd.tmpfiles.rules = [ + "d /var/opensearch_test 0700 open_search open_search -" + ]; + users = { + groups.open_search = { }; + users.open_search = { + description = "OpenSearch daemon user"; + group = "open_search"; + isSystemUser = true; }; }; }; diff --git a/nixos/tests/pg_anonymizer.nix b/nixos/tests/pg_anonymizer.nix new file mode 100644 index 000000000000..2960108e37c3 --- /dev/null +++ b/nixos/tests/pg_anonymizer.nix @@ -0,0 +1,94 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "pg_anonymizer"; + meta.maintainers = lib.teams.flyingcircus.members; + + nodes.machine = { pkgs, ... }: { + environment.systemPackages = [ pkgs.pg-dump-anon ]; + services.postgresql = { + enable = true; + extraPlugins = ps: [ ps.anonymizer ]; + settings.shared_preload_libraries = "anon"; + }; + }; + + testScript = '' + start_all() + machine.wait_for_unit("multi-user.target") + machine.wait_for_unit("postgresql.service") + + with subtest("Setup"): + machine.succeed("sudo -u postgres psql --command 'create database demo'") + machine.succeed( + "sudo -u postgres psql -d demo -f ${pkgs.writeText "init.sql" '' + create extension anon cascade; + select anon.init(); + create table player(id serial, name text, points int); + insert into player(id,name,points) values (1,'Foo', 23); + insert into player(id,name,points) values (2,'Bar',42); + security label for anon on column player.name is 'MASKED WITH FUNCTION anon.fake_last_name();'; + security label for anon on column player.points is 'MASKED WITH VALUE NULL'; + ''}" + ) + + def get_player_table_contents(): + return [ + x.split(',') for x in machine.succeed("sudo -u postgres psql -d demo --csv --command 'select * from player'").splitlines()[1:] + ] + + def check_anonymized_row(row, id, original_name): + assert row[0] == id, f"Expected first row to have ID {id}, but got {row[0]}" + assert row[1] != original_name, f"Expected first row to have a name other than {original_name}" + assert not bool(row[2]), "Expected points to be NULL in first row" + + def find_xsv_in_dump(dump, sep=','): + """ + Expecting to find a CSV (for pg_dump_anon) or TSV (for pg_dump) structure, looking like + + COPY public.player ... + 1,Shields, + 2,Salazar, + \. + + in the given dump (the commas are tabs in case of pg_dump). + Extract the CSV lines and split by `sep`. + """ + + try: + from itertools import dropwhile, takewhile + return [x.split(sep) for x in list(takewhile( + lambda x: x != "\\.", + dropwhile( + lambda x: not x.startswith("COPY public.player"), + dump.splitlines() + ) + ))[1:]] + except: + print(f"Dump to process: {dump}") + raise + + def check_original_data(output): + assert output[0] == ['1','Foo','23'], f"Expected first row from player table to be 1,Foo,23; got {output[0]}" + assert output[1] == ['2','Bar','42'], f"Expected first row from player table to be 2,Bar,42; got {output[1]}" + + def check_anonymized_rows(output): + check_anonymized_row(output[0], '1', 'Foo') + check_anonymized_row(output[1], '2', 'Bar') + + with subtest("Check initial state"): + check_original_data(get_player_table_contents()) + + with subtest("Anonymous dumps"): + check_original_data(find_xsv_in_dump( + machine.succeed("sudo -u postgres pg_dump demo"), + sep='\t' + )) + check_anonymized_rows(find_xsv_in_dump( + machine.succeed("sudo -u postgres pg_dump_anon -U postgres -h /run/postgresql -d demo"), + sep=',' + )) + + with subtest("Anonymize"): + machine.succeed("sudo -u postgres psql -d demo --command 'select anon.anonymize_database();'") + check_anonymized_rows(get_player_table_contents()) + ''; +}) diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 632656ad5795..3dc368e320ff 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -418,54 +418,6 @@ let ''; }; - kea = let - controlSocketPathV4 = "/run/kea/dhcp4.sock"; - controlSocketPathV6 = "/run/kea/dhcp6.sock"; - in - { - exporterConfig = { - enable = true; - controlSocketPaths = [ - controlSocketPathV4 - controlSocketPathV6 - ]; - }; - metricProvider = { - services.kea = { - dhcp4 = { - enable = true; - settings = { - control-socket = { - socket-type = "unix"; - socket-name = controlSocketPathV4; - }; - }; - }; - dhcp6 = { - enable = true; - settings = { - control-socket = { - socket-type = "unix"; - socket-name = controlSocketPathV6; - }; - }; - }; - }; - }; - - exporterTest = '' - wait_for_unit("kea-dhcp4-server.service") - wait_for_unit("kea-dhcp6-server.service") - wait_for_file("${controlSocketPathV4}") - wait_for_file("${controlSocketPathV6}") - wait_for_unit("prometheus-kea-exporter.service") - wait_for_open_port(9547) - succeed( - "curl --fail localhost:9547/metrics | grep 'packets_received_total'" - ) - ''; - }; - knot = { exporterConfig = { enable = true; diff --git a/nixos/tests/redlib.nix b/nixos/tests/redlib.nix new file mode 100644 index 000000000000..e4bde25e30a6 --- /dev/null +++ b/nixos/tests/redlib.nix @@ -0,0 +1,20 @@ +import ./make-test-python.nix ({ lib, pkgs, ... }: { + name = "redlib"; + meta.maintainers = with lib.maintainers; [ soispha ]; + + nodes.machine = { + services.libreddit = { + package = pkgs.redlib; + enable = true; + # Test CAP_NET_BIND_SERVICE + port = 80; + }; + }; + + testScript = '' + machine.wait_for_unit("libreddit.service") + machine.wait_for_open_port(80) + # Query a page that does not require Internet access + machine.succeed("curl --fail http://localhost:80/settings") + ''; +}) diff --git a/nixos/tests/systemd-machinectl.nix b/nixos/tests/systemd-machinectl.nix index b8ed0c33e8e4..02b4d9c590b5 100644 --- a/nixos/tests/systemd-machinectl.nix +++ b/nixos/tests/systemd-machinectl.nix @@ -42,8 +42,18 @@ import ./make-test-python.nix ({ pkgs, ... }: virtualisation.additionalPaths = [ containerSystem ]; - # not needed, but we want to test the nspawn file generation - systemd.nspawn.${containerName} = { }; + systemd.tmpfiles.rules = [ + "d /var/lib/machines/shared-decl 0755 root root - -" + ]; + systemd.nspawn.shared-decl = { + execConfig = { + Boot = false; + Parameters = "${containerSystem}/init"; + }; + filesConfig = { + BindReadOnly = "/nix/store"; + }; + }; systemd.services."systemd-nspawn@${containerName}" = { serviceConfig.Environment = [ @@ -52,14 +62,33 @@ import ./make-test-python.nix ({ pkgs, ... }: ]; overrideStrategy = "asDropin"; }; + + # open DHCP for container + networking.firewall.extraCommands = '' + ${pkgs.iptables}/bin/iptables -A nixos-fw -i ve-+ -p udp -m udp --dport 67 -j nixos-fw-accept + ''; }; testScript = '' start_all() machine.wait_for_unit("default.target"); - # Install container + # Test machinectl start stop of shared-decl + machine.succeed("machinectl start shared-decl"); + machine.wait_until_succeeds("systemctl -M shared-decl is-active default.target"); + machine.succeed("machinectl stop shared-decl"); + + # create containers root machine.succeed("mkdir -p ${containerRoot}"); + + # start container with shared nix store by using same arguments as for systemd-nspawn@.service + machine.succeed("systemd-run systemd-nspawn --machine=${containerName} --network-veth -U --bind-ro=/nix/store ${containerSystem}/init") + machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target"); + + # Test machinectl stop + machine.succeed("machinectl stop ${containerName}"); + + # Install container # Workaround for nixos-install machine.succeed("chmod o+rx /var/lib/machines"); machine.succeed("nixos-install --root ${containerRoot} --system ${containerSystem} --no-channel-copy --no-root-passwd"); @@ -77,6 +106,12 @@ import ./make-test-python.nix ({ pkgs, ... }: # Test nss_mymachines via nscd machine.succeed("getent hosts ${containerName}"); + # Test systemd-nspawn network configuration to container + machine.succeed("networkctl --json=short status ve-${containerName} | ${pkgs.jq}/bin/jq -e '.OperationalState == \"routable\"'"); + + # Test systemd-nspawn network configuration to host + machine.succeed("machinectl shell ${containerName} /run/current-system/sw/bin/networkctl --json=short status host0 | ${pkgs.jq}/bin/jq -r '.OperationalState == \"routable\"'"); + # Test systemd-nspawn network configuration machine.succeed("ping -n -c 1 ${containerName}"); diff --git a/nixos/tests/vscodium.nix b/nixos/tests/vscodium.nix index d817ce927ff8..76d5244b3ee3 100644 --- a/nixos/tests/vscodium.nix +++ b/nixos/tests/vscodium.nix @@ -76,4 +76,4 @@ let }); in -builtins.mapAttrs (k: v: mkTest k v { }) tests +builtins.mapAttrs (k: v: mkTest k v) tests diff --git a/nixos/tests/web-apps/pretix.nix b/nixos/tests/web-apps/pretix.nix new file mode 100644 index 000000000000..559316f9b85c --- /dev/null +++ b/nixos/tests/web-apps/pretix.nix @@ -0,0 +1,47 @@ +{ + lib, + pkgs, + ... +}: + +{ + name = "pretix"; + meta.maintainers = with lib.maintainers; [ hexa ]; + + nodes = { + pretix = { + networking.extraHosts = '' + 127.0.0.1 tickets.local + ''; + + services.pretix = { + enable = true; + nginx.domain = "tickets.local"; + plugins = with pkgs.pretix.plugins; [ + passbook + pages + ]; + settings = { + pretix = { + instance_name = "NixOS Test"; + url = "http://tickets.local"; + }; + mail.from = "hello@tickets.local"; + }; + }; + }; + }; + + testScript = '' + start_all() + + pretix.wait_for_unit("pretix-web.service") + pretix.wait_for_unit("pretix-worker.service") + + pretix.wait_until_succeeds("curl -q --fail http://tickets.local") + + pretix.succeed("pretix-manage --help") + + pretix.log(pretix.succeed("systemd-analyze security pretix-web.service")) + ''; +} |