diff options
Diffstat (limited to 'nixos')
29 files changed, 564 insertions, 166 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md index 4e8bd3642813b..d87d3b5c92f05 100644 --- a/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixos/doc/manual/release-notes/rl-2311.section.md @@ -18,6 +18,8 @@ - [wayfire](https://wayfire.org), A modular and extensible wayland compositor. Available as [programs.wayfire](#opt-programs.wayfire.enable). +- [mautrix-whatsapp](https://docs.mau.fi/bridges/go/whatsapp/index.html) A Matrix-WhatsApp puppeting bridge + - [GoToSocial](https://gotosocial.org/), an ActivityPub social network server, written in Golang. Available as [services.gotosocial](#opt-services.gotosocial.enable). - [Typesense](https://github.com/typesense/typesense), a fast, typo-tolerant search engine for building delightful search experiences. Available as [services.typesense](#opt-services.typesense.enable). @@ -40,6 +42,8 @@ - [systemd-sysupdate](https://www.freedesktop.org/software/systemd/man/systemd-sysupdate.html), atomically updates the host OS, container images, portable service images or other sources. Available as [systemd.sysupdate](opt-systemd.sysupdate). +- [eris-server](https://codeberg.org/eris/eris-go). [ERIS](https://eris.codeberg.page/) is an encoding for immutable storage and this server provides block exchange as well as content decoding over HTTP and through a FUSE file-system. Available as [services.eris-server](#opt-services.eris-server.enable). + ## Backward Incompatibilities {#sec-release-23.11-incompatibilities} - The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices. @@ -72,6 +76,22 @@ - The [services.caddy.acmeCA](#opt-services.caddy.acmeCA) option now defaults to `null` instead of `"https://acme-v02.api.letsencrypt.org/directory"`, to use all of Caddy's default ACME CAs and enable Caddy's automatic issuer fallback feature by default, as recommended by upstream. +- The default priorities of [`services.nextcloud.phpOptions`](#opt-services.nextcloud.phpOptions) have changed. This means that e.g. + `services.nextcloud.phpOptions."opcache.interned_strings_buffer" = "23";` doesn't discard all of the other defaults from this option + anymore. The attribute values of `phpOptions` are still defaults, these can be overridden as shown here. + + To override all of the options (including including `upload_max_filesize`, `post_max_size` + and `memory_limit` which all point to [`services.nextcloud.maxUploadSize`](#opt-services.nextcloud.maxUploadSize) + by default) can be done like this: + + ```nix + { + services.nextcloud.phpOptions = lib.mkForce { + /* ... */ + }; + } + ``` + - `php80` is no longer supported due to upstream not supporting this version anymore. - PHP now defaults to PHP 8.2, updated from 8.1. diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix index f8622be59a1b0..b2eb46f273b14 100644 --- a/nixos/modules/config/no-x-libs.nix +++ b/nixos/modules/config/no-x-libs.nix @@ -26,12 +26,7 @@ with lib; fonts.fontconfig.enable = false; - nixpkgs.overlays = singleton (self: super: let - packageOverrides = const (python-prev: { - # tk feature requires wayland which fails to compile - matplotlib = python-prev.matplotlib.override { enableGtk3 = false; enableTk = false; enableQt = false; }; - }); - in { + nixpkgs.overlays = singleton (const (super: { beam = super.beam_nox; cairo = super.cairo.override { x11Support = false; }; dbus = super.dbus.override { x11Support = false; }; @@ -67,8 +62,12 @@ with lib; pango = super.pango.override { x11Support = false; }; pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; }; pipewire = super.pipewire.override { x11Support = false; }; - python3 = super.python3.override { inherit packageOverrides; }; - python3Packages = self.python3.pkgs; # required otherwise overlays from above are not forwarded + pythonPackagesExtensions = super.pythonPackagesExtensions ++ [ + (python-final: python-prev: { + # tk feature requires wayland which fails to compile + matplotlib = python-prev.matplotlib.override { enableTk = false; }; + }) + ]; qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; }; qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; }); qt5 = super.qt5.overrideScope (const (super': { @@ -79,6 +78,6 @@ with lib; util-linux = super.util-linux.override { translateManpages = false; }; vim-full = super.vim-full.override { guiSupport = false; }; zbar = super.zbar.override { enableVideo = false; withXorg = false; }; - }); + })); }; } diff --git a/nixos/modules/i18n/input-method/fcitx5.nix b/nixos/modules/i18n/input-method/fcitx5.nix index 39952d6c3999e..b72f4be9b57a9 100644 --- a/nixos/modules/i18n/input-method/fcitx5.nix +++ b/nixos/modules/i18n/input-method/fcitx5.nix @@ -19,7 +19,7 @@ in ''; }; quickPhrase = mkOption { - type = with types; attrsOf string; + type = with types; attrsOf str; default = { }; example = literalExpression '' { diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 29fcabaefad51..5852843b8021d 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -600,6 +600,7 @@ ./services/matrix/dendrite.nix ./services/matrix/mautrix-facebook.nix ./services/matrix/mautrix-telegram.nix + ./services/matrix/mautrix-whatsapp.nix ./services/matrix/mjolnir.nix ./services/matrix/mx-puppet-discord.nix ./services/matrix/pantalaimon.nix @@ -806,6 +807,7 @@ ./services/network-filesystems/davfs2.nix ./services/network-filesystems/diod.nix ./services/network-filesystems/drbd.nix + ./services/network-filesystems/eris-server.nix ./services/network-filesystems/glusterfs.nix ./services/network-filesystems/kbfs.nix ./services/network-filesystems/kubo.nix @@ -863,6 +865,7 @@ ./services/networking/coturn.nix ./services/networking/create_ap.nix ./services/networking/croc.nix + ./services/networking/dae.nix ./services/networking/dante.nix ./services/networking/dhcpcd.nix ./services/networking/dnscache.nix diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index 4120d5919d7d7..19e7eb32e833f 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -120,5 +120,8 @@ with lib; [PStore] Unlink=no ''; + + # allow nix-copy to live system + nix.settings.trusted-users = [ "root" "nixos" ]; }; } diff --git a/nixos/modules/programs/firefox.nix b/nixos/modules/programs/firefox.nix index d67bbee9a7613..8653f066cf8fd 100644 --- a/nixos/modules/programs/firefox.nix +++ b/nixos/modules/programs/firefox.nix @@ -53,7 +53,7 @@ in }; preferences = mkOption { - type = with types; attrsOf (oneOf [ bool int string ]); + type = with types; attrsOf (oneOf [ bool int str ]); default = { }; description = mdDoc '' Preferences to set from `about:config`. diff --git a/nixos/modules/programs/gamescope.nix b/nixos/modules/programs/gamescope.nix index c4424849a41ed..a31295e736df2 100644 --- a/nixos/modules/programs/gamescope.nix +++ b/nixos/modules/programs/gamescope.nix @@ -42,7 +42,7 @@ in }; args = mkOption { - type = types.listOf types.string; + type = types.listOf types.str; default = [ ]; example = [ "--rt" "--prefer-vk-device 8086:9bc4" ]; description = mdDoc '' @@ -51,7 +51,7 @@ in }; env = mkOption { - type = types.attrsOf types.string; + type = types.attrsOf types.str; default = { }; example = literalExpression '' # for Prime render offload on Nvidia laptops. diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix index c63b31bde11f1..29c449c16946c 100644 --- a/nixos/modules/programs/steam.nix +++ b/nixos/modules/programs/steam.nix @@ -89,7 +89,7 @@ in { options = { enable = mkEnableOption (mdDoc "GameScope Session"); args = mkOption { - type = types.listOf types.string; + type = types.listOf types.str; default = [ ]; description = mdDoc '' Arguments to be passed to GameScope for the session. @@ -97,7 +97,7 @@ in { }; env = mkOption { - type = types.attrsOf types.string; + type = types.attrsOf types.str; default = { }; description = mdDoc '' Environmental variables to be passed to GameScope for the session. diff --git a/nixos/modules/security/ipa.nix b/nixos/modules/security/ipa.nix index 7075be95040ee..69a670cd5e4a3 100644 --- a/nixos/modules/security/ipa.nix +++ b/nixos/modules/security/ipa.nix @@ -86,7 +86,7 @@ in { }; ifpAllowedUids = mkOption { - type = types.listOf types.string; + type = types.listOf types.str; default = ["root"]; description = lib.mdDoc "A list of users allowed to access the ifp dbus interface."; }; diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index ac9da4a823b70..ee260a097c691 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -934,7 +934,7 @@ in }; authserver = mkOption { default = null; - type = with types; nullOr string; + type = with types; nullOr str; description = lib.mdDoc '' This controls the hostname for the 9front authentication server that users will be authenticated against. diff --git a/nixos/modules/services/audio/wyoming/faster-whisper.nix b/nixos/modules/services/audio/wyoming/faster-whisper.nix index 6317709b24750..1fb67ecfe5060 100644 --- a/nixos/modules/services/audio/wyoming/faster-whisper.nix +++ b/nixos/modules/services/audio/wyoming/faster-whisper.nix @@ -71,7 +71,7 @@ in ]; default = "cpu"; description = mdDoc '' - Id of a speaker in a multi-speaker model. + Determines the platform faster-whisper is run on. CPU works everywhere, CUDA requires a compatible NVIDIA GPU. ''; }; diff --git a/nixos/modules/services/cluster/patroni/default.nix b/nixos/modules/services/cluster/patroni/default.nix index 9bf3a285836c0..5ab016a9f59f0 100644 --- a/nixos/modules/services/cluster/patroni/default.nix +++ b/nixos/modules/services/cluster/patroni/default.nix @@ -105,7 +105,7 @@ in }; otherNodesIps = mkOption { - type = types.listOf types.string; + type = types.listOf types.str; example = [ "192.168.1.2" "192.168.1.3" ]; description = mdDoc '' IP addresses of the other nodes. diff --git a/nixos/modules/services/hardware/joycond.nix b/nixos/modules/services/hardware/joycond.nix index 1af18b3b63d37..df3239cb2a7df 100644 --- a/nixos/modules/services/hardware/joycond.nix +++ b/nixos/modules/services/hardware/joycond.nix @@ -2,7 +2,6 @@ let cfg = config.services.joycond; - kernelPackages = config.boot.kernelPackages; in with lib; @@ -24,8 +23,6 @@ with lib; config = mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; - boot.extraModulePackages = optional (versionOlder kernelPackages.kernel.version "5.16") kernelPackages.hid-nintendo; - services.udev.packages = [ cfg.package ]; systemd.packages = [ cfg.package ]; diff --git a/nixos/modules/services/hardware/keyd.nix b/nixos/modules/services/hardware/keyd.nix index 969383fd4dc78..ead2f456a2024 100644 --- a/nixos/modules/services/hardware/keyd.nix +++ b/nixos/modules/services/hardware/keyd.nix @@ -7,7 +7,7 @@ let keyboardOptions = { ... }: { options = { ids = mkOption { - type = types.listOf types.string; + type = types.listOf types.str; default = [ "*" ]; example = [ "*" "-0123:0456" ]; description = lib.mdDoc '' diff --git a/nixos/modules/services/mail/maddy.nix b/nixos/modules/services/mail/maddy.nix index 3b4a517fb8596..2c4d75e8391a4 100644 --- a/nixos/modules/services/mail/maddy.nix +++ b/nixos/modules/services/mail/maddy.nix @@ -142,7 +142,7 @@ in { user = mkOption { default = "maddy"; - type = with types; uniq string; + type = with types; uniq str; description = lib.mdDoc '' User account under which maddy runs. @@ -156,7 +156,7 @@ in { group = mkOption { default = "maddy"; - type = with types; uniq string; + type = with types; uniq str; description = lib.mdDoc '' Group account under which maddy runs. @@ -170,7 +170,7 @@ in { hostname = mkOption { default = "localhost"; - type = with types; uniq string; + type = with types; uniq str; example = ''example.com''; description = lib.mdDoc '' Hostname to use. It should be FQDN. @@ -179,7 +179,7 @@ in { primaryDomain = mkOption { default = "localhost"; - type = with types; uniq string; + type = with types; uniq str; example = ''mail.example.com''; description = lib.mdDoc '' Primary MX domain to use. It should be FQDN. diff --git a/nixos/modules/services/matrix/mautrix-whatsapp.nix b/nixos/modules/services/matrix/mautrix-whatsapp.nix new file mode 100644 index 0000000000000..80c85980196f3 --- /dev/null +++ b/nixos/modules/services/matrix/mautrix-whatsapp.nix @@ -0,0 +1,198 @@ +{ + lib, + config, + pkgs, + ... +}: let + cfg = config.services.mautrix-whatsapp; + dataDir = "/var/lib/mautrix-whatsapp"; + registrationFile = "${dataDir}/whatsapp-registration.yaml"; + settingsFile = "${dataDir}/config.json"; + settingsFileUnsubstituted = settingsFormat.generate "mautrix-whatsapp-config-unsubstituted.json" cfg.settings; + settingsFormat = pkgs.formats.json {}; + appservicePort = 29318; +in { + imports = []; + options.services.mautrix-whatsapp = { + enable = lib.mkEnableOption "mautrix-whatsapp, a puppeting/relaybot bridge between Matrix and WhatsApp."; + + settings = lib.mkOption { + type = settingsFormat.type; + default = { + appservice = { + address = "http://localhost:${toString appservicePort}"; + hostname = "[::]"; + port = appservicePort; + database = { + type = "sqlite3"; + uri = "${dataDir}/mautrix-whatsapp.db"; + }; + id = "whatsapp"; + bot = { + username = "whatsappbot"; + displayname = "WhatsApp Bridge Bot"; + }; + as_token = ""; + hs_token = ""; + }; + bridge = { + username_template = "whatsapp_{{.}}"; + displayname_template = "{{if .BusinessName}}{{.BusinessName}}{{else if .PushName}}{{.PushName}}{{else}}{{.JID}}{{end}} (WA)"; + double_puppet_server_map = {}; + login_shared_secret_map = {}; + command_prefix = "!wa"; + permissions."*" = "relay"; + relay.enabled = true; + }; + logging = { + min_level = "info"; + writers = [ + { + type = "stdout"; + format = "pretty-colored"; + } + { + type = "file"; + format = "json"; + } + ]; + }; + }; + description = lib.mdDoc '' + {file}`config.yaml` configuration as a Nix attribute set. + Configuration options should match those described in + [example-config.yaml](https://github.com/mautrix/whatsapp/blob/master/example-config.yaml). + Secret tokens should be specified using {option}`environmentFile` + instead of this world-readable attribute set. + ''; + example = { + appservice = { + database = { + type = "postgres"; + uri = "postgresql:///mautrix_whatsapp?host=/run/postgresql"; + }; + id = "whatsapp"; + ephemeral_events = false; + }; + bridge = { + history_sync = { + request_full_sync = true; + }; + private_chat_portal_meta = true; + mute_bridging = true; + encryption = { + allow = true; + default = true; + require = true; + }; + provisioning = { + shared_secret = "disable"; + }; + permissions = { + "example.com" = "user"; + }; + }; + }; + }; + environmentFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = lib.mdDoc '' + File containing environment variables to be passed to the mautrix-whatsapp service, + in which secret tokens can be specified securely by optionally defining a value for + `MAUTRIX_WHATSAPP_BRIDGE_LOGIN_SHARED_SECRET`. + ''; + }; + + serviceDependencies = lib.mkOption { + type = with lib.types; listOf str; + default = lib.optional config.services.matrix-synapse.enable "matrix-synapse.service"; + defaultText = lib.literalExpression '' + optional config.services.matrix-synapse.enable "matrix-synapse.service" + ''; + description = lib.mdDoc '' + List of Systemd services to require and wait for when starting the application service. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.mautrix-whatsapp.settings = { + homeserver.domain = lib.mkDefault config.services.matrix-synapse.settings.server_name; + }; + + systemd.services.mautrix-whatsapp = { + description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix"; + + wantedBy = ["multi-user.target"]; + wants = ["network-online.target"] ++ cfg.serviceDependencies; + after = ["network-online.target"] ++ cfg.serviceDependencies; + + preStart = '' + # substitute the settings file by environment variables + # in this case read from EnvironmentFile + test -f '${settingsFile}' && rm -f '${settingsFile}' + old_umask=$(umask) + umask 0177 + ${pkgs.envsubst}/bin/envsubst \ + -o '${settingsFile}' \ + -i '${settingsFileUnsubstituted}' + umask $old_umask + + # generate the appservice's registration file if absent + if [ ! -f '${registrationFile}' ]; then + ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp \ + --generate-registration \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + fi + chmod 640 ${registrationFile} + + umask 0177 + ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token + | .[0].appservice.hs_token = .[1].hs_token + | .[0]' '${settingsFile}' '${registrationFile}' \ + > '${settingsFile}.tmp' + mv '${settingsFile}.tmp' '${settingsFile}' + umask $old_umask + ''; + + serviceConfig = { + DynamicUser = true; + EnvironmentFile = cfg.environmentFile; + StateDirectory = baseNameOf dataDir; + WorkingDirectory = "${dataDir}"; + ExecStart = '' + ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp \ + --config='${settingsFile}' \ + --registration='${registrationFile}' + ''; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + Restart = "on-failure"; + RestartSec = "30s"; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = ["@system-service"]; + Type = "simple"; + UMask = 0027; + }; + restartTriggers = [settingsFileUnsubstituted]; + }; + }; + meta.maintainers = with lib.maintainers; [frederictobiasc]; +} diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index ec88de6da3ba8..f6ef2bb919107 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -666,6 +666,7 @@ in USER = cfg.user; HOME = cfg.stateDir; GITEA_WORK_DIR = cfg.stateDir; + GITEA_CUSTOM = cfg.customDir; }; serviceConfig = { diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix index 1845d8ad29b57..0683a1f922ab3 100644 --- a/nixos/modules/services/misc/paperless.nix +++ b/nixos/modules/services/misc/paperless.nix @@ -7,6 +7,7 @@ let defaultUser = "paperless"; nltkDir = "/var/cache/paperless/nltk"; + defaultFont = "${pkgs.liberation_ttf}/share/fonts/truetype/LiberationSerif-Regular.ttf"; # Don't start a redis instance if the user sets a custom redis connection enableRedis = !hasAttr "PAPERLESS_REDIS" cfg.extraConfig; @@ -17,6 +18,7 @@ let PAPERLESS_MEDIA_ROOT = cfg.mediaDir; PAPERLESS_CONSUMPTION_DIR = cfg.consumptionDir; PAPERLESS_NLTK_DIR = nltkDir; + PAPERLESS_THUMBNAIL_FONT_NAME = defaultFont; GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}"; } // optionalAttrs (config.time.timeZone != null) { PAPERLESS_TIME_ZONE = config.time.timeZone; diff --git a/nixos/modules/services/network-filesystems/eris-server.nix b/nixos/modules/services/network-filesystems/eris-server.nix new file mode 100644 index 0000000000000..66eccfac408c4 --- /dev/null +++ b/nixos/modules/services/network-filesystems/eris-server.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.eris-server; + stateDirectoryPath = "\${STATE_DIRECTORY}"; +in { + + options.services.eris-server = { + + enable = lib.mkEnableOption "an ERIS server"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.eris-go; + defaultText = lib.literalExpression "pkgs.eris-go"; + description = "Package to use for the ERIS server."; + }; + + decode = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether the HTTP service (when enabled) will decode ERIS content at /uri-res/N2R?urn:eris:. + Enabling this is recommended only for private or local-only servers. + ''; + }; + + listenCoap = lib.mkOption { + type = lib.types.str; + default = ":5683"; + example = "[::1]:5683"; + description = '' + Server CoAP listen address. Listen on all IP addresses at port 5683 by default. + Please note that the server can service client requests for ERIS-blocks by + querying other clients connected to the server. Whether or not blocks are + relayed back to the server depends on client configuration but be aware this + may leak sensitive metadata and trigger network activity. + ''; + }; + + listenHttp = lib.mkOption { + type = lib.types.str; + default = ""; + example = "[::1]:8080"; + description = "Server HTTP listen address. Do not listen by default."; + }; + + backends = lib.mkOption { + type = with lib.types; listOf str; + description = '' + List of backend URLs. + Add "get" and "put" as query elements to enable those operations. + ''; + example = [ + "bolt+file:///srv/eris.bolt?get&put" + "coap+tcp://eris.example.com:5683?get" + ]; + }; + + mountpoint = lib.mkOption { + type = lib.types.str; + default = ""; + example = "/eris"; + description = '' + Mountpoint for FUSE namespace that exposes "urn:eris:…" files. + ''; + }; + + }; + + config = lib.mkIf cfg.enable { + systemd.services.eris-server = let + cmd = + "${cfg.package}/bin/eris-go server --coap '${cfg.listenCoap}' --http '${cfg.listenHttp}' ${ + lib.optionalString cfg.decode "--decode " + }${ + lib.optionalString (cfg.mountpoint != "") + ''--mountpoint "${cfg.mountpoint}" '' + }${lib.strings.escapeShellArgs cfg.backends}"; + in { + description = "ERIS block server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + script = lib.mkIf (cfg.mountpoint != "") '' + export PATH=${config.security.wrapperDir}:$PATH + ${cmd} + ''; + serviceConfig = let + umounter = lib.mkIf (cfg.mountpoint != "") + "-${config.security.wrapperDir}/fusermount -uz ${cfg.mountpoint}"; + in { + ExecStartPre = umounter; + ExecStart = lib.mkIf (cfg.mountpoint == "") cmd; + ExecStopPost = umounter; + Restart = "always"; + RestartSec = 20; + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ ehmry ]; +} diff --git a/nixos/modules/services/network-filesystems/kubo.nix b/nixos/modules/services/network-filesystems/kubo.nix index a5c370b5be895..5a355f3441d8a 100644 --- a/nixos/modules/services/network-filesystems/kubo.nix +++ b/nixos/modules/services/network-filesystems/kubo.nix @@ -278,6 +278,12 @@ in You can't set services.kubo.settings.Pinning.RemoteServices because the ``config replace`` subcommand used at startup does not work with it. ''; } + { + assertion = !((lib.versionAtLeast cfg.package.version "0.21") && (builtins.hasAttr "Experimental" cfg.settings) && (builtins.hasAttr "AcceleratedDHTClient" cfg.settings.Experimental)); + message = '' + The `services.kubo.settings.Experimental.AcceleratedDHTClient` option was renamed to `services.kubo.settings.Routing.AcceleratedDHTClient` in Kubo 0.21. + ''; + } ]; environment.systemPackages = [ cfg.package ]; diff --git a/nixos/modules/services/networking/dae.nix b/nixos/modules/services/networking/dae.nix new file mode 100644 index 0000000000000..b0ad2c0d4bb06 --- /dev/null +++ b/nixos/modules/services/networking/dae.nix @@ -0,0 +1,41 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.services.dae; +in +{ + meta.maintainers = with lib.maintainers; [ pokon548 ]; + + options = { + services.dae = { + enable = lib.options.mkEnableOption (lib.mdDoc "the dae service"); + package = lib.mkPackageOptionMD pkgs "dae" { }; + }; + }; + + config = lib.mkIf config.services.dae.enable { + networking.firewall.allowedTCPPorts = [ 12345 ]; + networking.firewall.allowedUDPPorts = [ 12345 ]; + + systemd.services.dae = { + unitConfig = { + Description = "dae Service"; + Documentation = "https://github.com/daeuniverse/dae"; + After = [ "network.target" "systemd-sysctl.service" ]; + Wants = [ "network.target" ]; + }; + + serviceConfig = { + User = "root"; + ExecStartPre = "${lib.getExe cfg.package} validate -c /etc/dae/config.dae"; + ExecStart = "${lib.getExe cfg.package} run --disable-timestamp -c /etc/dae/config.dae"; + ExecReload = "${lib.getExe cfg.package} reload $MAINPID"; + LimitNPROC = 512; + LimitNOFILE = 1048576; + Restart = "on-abnormal"; + Type = "notify"; + }; + + wantedBy = [ "multi-user.target" ]; + }; + }; +} diff --git a/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixos/modules/services/networking/dnscrypt-wrapper.nix index 082e0195093ef..741f054cd88be 100644 --- a/nixos/modules/services/networking/dnscrypt-wrapper.nix +++ b/nixos/modules/services/networking/dnscrypt-wrapper.nix @@ -71,9 +71,9 @@ let if ! keyValid; then echo "certificate soon to become invalid; backing up old cert" mkdir -p oldkeys - mv -v ${cfg.providerName}.key oldkeys/${cfg.providerName}-$(date +%F-%T).key - mv -v ${cfg.providerName}.crt oldkeys/${cfg.providerName}-$(date +%F-%T).crt - systemctl restart dnscrypt-wrapper + mv -v "${cfg.providerName}.key" "oldkeys/${cfg.providerName}-$(date +%F-%T).key" + mv -v "${cfg.providerName}.crt" "oldkeys/${cfg.providerName}-$(date +%F-%T).crt" + kill "$(pidof -s dnscrypt-wrapper)" fi ''; @@ -222,17 +222,6 @@ in { }; users.groups.dnscrypt-wrapper = { }; - security.polkit.extraConfig = '' - // Allow dnscrypt-wrapper user to restart dnscrypt-wrapper.service - polkit.addRule(function(action, subject) { - if (action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "dnscrypt-wrapper.service" && - subject.user == "dnscrypt-wrapper") { - return polkit.Result.YES; - } - }); - ''; - systemd.services.dnscrypt-wrapper = { description = "dnscrypt-wrapper daemon"; after = [ "network.target" ]; @@ -242,7 +231,7 @@ in { serviceConfig = { User = "dnscrypt-wrapper"; WorkingDirectory = dataDir; - Restart = "on-failure"; + Restart = "always"; ExecStart = "${pkgs.dnscrypt-wrapper}/bin/dnscrypt-wrapper ${toString daemonArgs}"; }; @@ -255,7 +244,7 @@ in { requires = [ "dnscrypt-wrapper.service" ]; description = "Rotates DNSCrypt wrapper keys if soon to expire"; - path = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy1 gawk ]; + path = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy1 gawk procps ]; script = rotateKeys; serviceConfig.User = "dnscrypt-wrapper"; }; diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 06af9d933e084..e0a7e7d4859c8 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -8,6 +8,21 @@ let jsonFormat = pkgs.formats.json {}; + defaultPHPSettings = { + short_open_tag = "Off"; + 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"; + "opcache.revalidate_freq" = "1"; + "opcache.fast_shutdown" = "1"; + "openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt"; + catch_workers_output = "yes"; + }; + inherit (cfg) datadir; phpPackage = cfg.phpPackage.buildEnv { @@ -26,22 +41,13 @@ let ++ optional cfg.caching.memcached memcached ) ++ cfg.phpExtraExtensions all; # Enabled by user - extraConfig = toKeyValue phpOptions; + extraConfig = toKeyValue cfg.phpOptions; }; toKeyValue = generators.toKeyValue { mkKeyValue = generators.mkKeyValueDefault {} " = "; }; - phpOptions = { - upload_max_filesize = cfg.maxUploadSize; - post_max_size = cfg.maxUploadSize; - memory_limit = cfg.maxUploadSize; - } // cfg.phpOptions - // optionalAttrs cfg.caching.apcu { - "apc.enable_cli" = "1"; - }; - occ = pkgs.writeScriptBin "nextcloud-occ" '' #! ${pkgs.runtimeShell} cd ${cfg.package} @@ -136,8 +142,8 @@ in { default = config.services.nextcloud.home; defaultText = literalExpression "config.services.nextcloud.home"; description = lib.mdDoc '' - Data storage path of nextcloud. Will be [](#opt-services.nextcloud.home) by default. - This folder will be populated with a config.php and data folder which contains the state of the instance (excl the database)."; + Nextcloud's data storage path. Will be [](#opt-services.nextcloud.home) by default. + This folder will be populated with a config.php file and a data folder which contains the state of the instance (excluding the database)."; ''; example = "/mnt/nextcloud-file"; }; @@ -170,8 +176,8 @@ in { type = types.bool; default = true; description = lib.mdDoc '' - Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time nextcloud starts. - If set to false, apps need to be enabled in the Nextcloud user interface or with nextcloud-occ app:enable. + Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time Nextcloud starts. + If set to false, apps need to be enabled in the Nextcloud web user interface or with `nextcloud-occ app:enable`. ''; }; appstoreEnable = mkOption { @@ -179,16 +185,28 @@ in { default = null; example = true; description = lib.mdDoc '' - Allow the installation of apps and app updates from the store. + Allow the installation and updating of apps from the Nextcloud appstore. Enabled by default unless there are packages in [](#opt-services.nextcloud.extraApps). - Set to true to force enable the store even if [](#opt-services.nextcloud.extraApps) is used. - Set to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting. + Set this to true to force enable the store even if [](#opt-services.nextcloud.extraApps) is used. + Set this to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting. ''; }; logLevel = mkOption { type = types.ints.between 0 4; default = 2; - description = lib.mdDoc "Log level value between 0 (DEBUG) and 4 (FATAL)."; + description = lib.mdDoc '' + Log level value between 0 (DEBUG) and 4 (FATAL). + + - 0 (debug): Log all activity. + + - 1 (info): Log activity such as user logins and file activities, plus warnings, errors, and fatal errors. + + - 2 (warn): Log successful operations, as well as warnings of potential problems, errors and fatal errors. + + - 3 (error): Log failed operations and fatal errors. + + - 4 (fatal): Log only fatal errors that cause the server to stop. + ''; }; logType = mkOption { type = types.enum [ "errorlog" "file" "syslog" "systemd" ]; @@ -202,7 +220,7 @@ in { https = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Use https for generated links."; + description = lib.mdDoc "Use HTTPS for generated links."; }; package = mkOption { type = types.package; @@ -222,7 +240,7 @@ in { default = "512M"; type = types.str; description = lib.mdDoc '' - Defines the upload limit for files. This changes the relevant options + The upload limit for files. This changes the relevant options in php.ini and nginx if enabled. ''; }; @@ -251,10 +269,10 @@ in { default = all: []; defaultText = literalExpression "all: []"; description = lib.mdDoc '' - Additional PHP extensions to use for nextcloud. - By default, only extensions necessary for a vanilla nextcloud installation are enabled, + Additional PHP extensions to use for Nextcloud. + By default, only extensions necessary for a vanilla Nextcloud installation are enabled, but you may choose from the list of available extensions and add further ones. - This is sometimes necessary to be able to install a certain nextcloud app that has additional requirements. + This is sometimes necessary to be able to install a certain Nextcloud app that has additional requirements. ''; example = literalExpression '' all: [ all.pdlib all.bz2 ] @@ -263,22 +281,33 @@ in { phpOptions = mkOption { type = types.attrsOf types.str; - default = { - short_open_tag = "Off"; - 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"; - "opcache.revalidate_freq" = "1"; - "opcache.fast_shutdown" = "1"; - "openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt"; - catch_workers_output = "yes"; - }; + defaultText = literalExpression (generators.toPretty { } defaultPHPSettings); description = lib.mdDoc '' Options for PHP's php.ini file for nextcloud. + + Please note that this option is _additive_ on purpose while the + attribute values inside the default are option defaults: that means that + + ```nix + { + services.nextcloud.phpOptions."opcache.interned_strings_buffer" = "23"; + } + ``` + + will override the `php.ini` option `opcache.interned_strings_buffer` without + discarding the rest of the defaults. + + Overriding all of `phpOptions` (including `upload_max_filesize`, `post_max_size` + and `memory_limit` which all point to [](#opt-services.nextcloud.maxUploadSize) + by default) can be done like this: + + ```nix + { + services.nextcloud.phpOptions = lib.mkForce { + /* ... */ + }; + } + ``` ''; }; @@ -301,7 +330,7 @@ in { type = types.nullOr types.lines; default = null; description = lib.mdDoc '' - Options for nextcloud's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. + Options for Nextcloud's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. ''; }; @@ -319,7 +348,7 @@ in { type = types.bool; default = false; description = lib.mdDoc '' - Create the database and database user locally. + Whether to create the database and database user locally. ''; }; @@ -357,9 +386,10 @@ in { else "localhost"; defaultText = "localhost"; description = lib.mdDoc '' - Database host or socket path. Defaults to the correct unix socket - instead if `services.nextcloud.database.createLocally` is true and - `services.nextcloud.config.dbtype` is either `pgsql` or `mysql`. + Database host or socket path. + If [](#opt-services.nextcloud.database.createLocally) is true and + [](#opt-services.nextcloud.config.dbtype) is either `pgsql` or `mysql`, + defaults to the correct Unix socket instead. ''; }; dbport = mkOption { @@ -370,19 +400,23 @@ in { dbtableprefix = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc "Table prefix in Nextcloud database."; + description = lib.mdDoc "Table prefix in Nextcloud's database."; }; adminuser = mkOption { type = types.str; default = "root"; - description = lib.mdDoc "Admin username."; + description = lib.mdDoc '' + Username for the admin account. The username is only set during the + initial setup of Nextcloud! Since the username also acts as unique + ID internally, it cannot be changed later! + ''; }; adminpassFile = mkOption { type = types.str; description = lib.mdDoc '' The full path to a file that contains the admin's password. Must be readable by user `nextcloud`. The password is set only in the initial - setup of nextcloud by the systemd `nextcloud-setup.service`. + setup of Nextcloud by the systemd service `nextcloud-setup.service`. ''; }; @@ -390,7 +424,7 @@ in { type = types.listOf types.str; default = []; description = lib.mdDoc '' - Trusted domains, from which the nextcloud installation will be + Trusted domains from which the Nextcloud installation will be accessible. You don't need to add `services.nextcloud.hostname` here. ''; @@ -400,8 +434,8 @@ in { type = types.listOf types.str; default = []; description = lib.mdDoc '' - Trusted proxies, to provide if the nextcloud installation is being - proxied to secure against e.g. spoofing. + Trusted proxies to provide if the Nextcloud installation is being + proxied to secure against, e.g. spoofing. ''; }; @@ -411,10 +445,10 @@ in { example = "https"; description = lib.mdDoc '' - Force Nextcloud to always use HTTPS i.e. for link generation. Nextcloud - uses the currently used protocol by default, but when behind a reverse-proxy, - it may use `http` for everything although Nextcloud - may be served via HTTPS. + Force Nextcloud to always use HTTP or HTTPS i.e. for link generation. + Nextcloud uses the currently used protocol by default, but when + behind a reverse-proxy, it may use `http` for everything although + Nextcloud may be served via HTTPS. ''; }; @@ -423,16 +457,12 @@ in { type = types.nullOr types.str; example = "DE"; description = lib.mdDoc '' - ::: {.warning} - This option exists since Nextcloud 21! If older versions are used, - this will throw an eval-error! - ::: - - [ISO 3611-1](https://www.iso.org/iso-3166-country-codes.html) - country codes for automatic phone-number detection without a country code. + An [ISO 3166-1](https://www.iso.org/iso-3166-country-codes.html) + country code which replaces automatic phone-number detection + without a country code. - With e.g. `DE` set, the `+49` can be omitted for - phone-numbers. + As an example, with `DE` set as the default phone region, + the `+49` prefix can be omitted for phone numbers. ''; }; @@ -557,10 +587,10 @@ in { default = config.services.nextcloud.notify_push.enable; defaultText = literalExpression "config.services.nextcloud.notify_push.enable"; description = lib.mdDoc '' - Whether to configure nextcloud to use the recommended redis settings for small instances. + Whether to configure Nextcloud to use the recommended Redis settings for small instances. ::: {.note} - The `notify_push` app requires redis to be configured. If this option is turned off, this must be configured manually. + The `notify_push` app requires Redis to be configured. If this option is turned off, this must be configured manually. ::: ''; }; @@ -597,7 +627,7 @@ in { type = types.bool; default = false; description = lib.mdDoc '' - Run regular auto update of all apps installed from the nextcloud app store. + Run a regular auto-update of all apps installed from the Nextcloud app store. ''; }; startAt = mkOption { @@ -644,7 +674,7 @@ in { type = jsonFormat.type; default = {}; description = lib.mdDoc '' - Extra options which should be appended to nextcloud's config.php file. + Extra options which should be appended to Nextcloud's config.php file. ''; example = literalExpression '' { redis = { @@ -661,7 +691,7 @@ in { type = types.nullOr types.str; default = null; description = lib.mdDoc '' - Secret options which will be appended to nextcloud's config.php file (written as JSON, in the same + Secret options which will be appended to Nextcloud's config.php file (written as JSON, in the same form as the [](#opt-services.nextcloud.extraOptions) option), for example `{"redis":{"password":"secret"}}`. ''; @@ -695,7 +725,7 @@ in { A legacy Nextcloud install (from before NixOS ${nixos}) may be installed. After nextcloud${toString major} is installed successfully, you can safely upgrade - to ${toString (major + 1)}. The latest version available is nextcloud${toString latest}. + to ${toString (major + 1)}. The latest version available is Nextcloud${toString latest}. Please note that Nextcloud doesn't support upgrades across multiple major versions (i.e. an upgrade from 16 is possible to 17, but not 16 to 18). @@ -750,6 +780,18 @@ in { services.nextcloud.phpPackage = if versionOlder cfg.package.version "26" then pkgs.php81 else pkgs.php82; + + services.nextcloud.phpOptions = mkMerge [ + (mapAttrs (const mkOptionDefault) defaultPHPSettings) + { + upload_max_filesize = cfg.maxUploadSize; + post_max_size = cfg.maxUploadSize; + memory_limit = cfg.maxUploadSize; + } + (mkIf cfg.caching.apcu { + "apc.enable_cli" = "1"; + }) + ]; } { assertions = [ diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 3b4a39f5ff96b..a2235b106dc64 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -21,7 +21,7 @@ let if isAttrs val then if hasAttr "test" val then callTest val - else mapAttrs (n: s: discoverTests s) val + else mapAttrs (n: s: if n == "passthru" then s else discoverTests s) val else if isFunction val then # Tests based on make-test-python.nix will return the second lambda @@ -217,7 +217,7 @@ in { disable-installer-tools = handleTest ./disable-installer-tools.nix {}; discourse = handleTest ./discourse.nix {}; dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {}; - dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {}; + dnscrypt-wrapper = runTestOn ["x86_64-linux"] ./dnscrypt-wrapper; dnsdist = handleTest ./dnsdist.nix {}; doas = handleTest ./doas.nix {}; docker = handleTestOn ["aarch64-linux" "x86_64-linux"] ./docker.nix {}; @@ -252,6 +252,7 @@ in { envoy = handleTest ./envoy.nix {}; ergo = handleTest ./ergo.nix {}; ergochat = handleTest ./ergochat.nix {}; + eris-server = handleTest ./eris-server.nix {}; esphome = handleTest ./esphome.nix {}; etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; }; activation = pkgs.callPackage ../modules/system/activation/test.nix { }; diff --git a/nixos/tests/caddy.nix b/nixos/tests/caddy.nix index ed88f08739e85..238091ec606f5 100644 --- a/nixos/tests/caddy.nix +++ b/nixos/tests/caddy.nix @@ -22,22 +22,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { ''; services.caddy.enableReload = true; - specialisation.etag.configuration = { - services.caddy.extraConfig = lib.mkForce '' - http://localhost { - encode gzip - - file_server - root * ${ - pkgs.runCommand "testdir2" {} '' - mkdir "$out" - echo changed > "$out/example.html" - '' - } - } - ''; - }; - specialisation.config-reload.configuration = { services.caddy.extraConfig = '' http://localhost:8080 { @@ -55,7 +39,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { testScript = { nodes, ... }: let - etagSystem = "${nodes.webserver.system.build.toplevel}/specialisation/etag"; justReloadSystem = "${nodes.webserver.system.build.toplevel}/specialisation/config-reload"; multipleConfigs = "${nodes.webserver.system.build.toplevel}/specialisation/multiple-configs"; in @@ -65,33 +48,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { webserver.wait_for_open_port(80) - def check_etag(url): - etag = webserver.succeed( - "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format( - url - ) - ) - etag = etag.replace("\r\n", " ") - http_code = webserver.succeed( - "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format( - etag, url - ) - ) - assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code) - return etag - - - with subtest("check ETag if serving Nix store paths"): - old_etag = check_etag(url) - webserver.succeed( - "${etagSystem}/bin/switch-to-configuration test >&2" - ) - webserver.sleep(1) - new_etag = check_etag(url) - assert old_etag != new_etag, "Old ETag {} is the same as {}".format( - old_etag, new_etag - ) - with subtest("config is reloaded on nixos-rebuild switch"): webserver.succeed( "${justReloadSystem}/bin/switch-to-configuration test >&2" diff --git a/nixos/tests/dnscrypt-wrapper/default.nix b/nixos/tests/dnscrypt-wrapper/default.nix index 1bdd064e1130c..1c05376e097b3 100644 --- a/nixos/tests/dnscrypt-wrapper/default.nix +++ b/nixos/tests/dnscrypt-wrapper/default.nix @@ -1,4 +1,6 @@ -import ../make-test-python.nix ({ pkgs, ... }: { +{ lib, pkgs, ... }: + +{ name = "dnscrypt-wrapper"; meta = with pkgs.lib.maintainers; { maintainers = [ rnhmjoj ]; @@ -50,23 +52,23 @@ import ../make-test-python.nix ({ pkgs, ... }: { server.wait_for_unit("dnscrypt-wrapper") server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.key") server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.crt") + almost_expiration = server.succeed("date --date '4days 23 hours 56min'").strip() with subtest("The client can connect to the server"): server.wait_for_unit("tinydns") client.wait_for_unit("dnscrypt-proxy2") - assert "1.2.3.4" in client.succeed( + assert "1.2.3.4" in client.wait_until_succeeds( "host it.works" ), "The IP address of 'it.works' does not match 1.2.3.4" with subtest("The server rotates the ephemeral keys"): # advance time by a little less than 5 days - server.succeed("date -s \"$(date --date '4 days 6 hours')\"") - client.succeed("date -s \"$(date --date '4 days 6 hours')\"") + server.succeed(f"date -s '{almost_expiration}'") + client.succeed(f"date -s '{almost_expiration}'") server.wait_for_file("/var/lib/dnscrypt-wrapper/oldkeys") with subtest("The client can still connect to the server"): server.wait_for_unit("dnscrypt-wrapper") client.succeed("host it.works") ''; -}) - +} diff --git a/nixos/tests/eris-server.nix b/nixos/tests/eris-server.nix new file mode 100644 index 0000000000000..a50db3afebf5f --- /dev/null +++ b/nixos/tests/eris-server.nix @@ -0,0 +1,23 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "eris-server"; + meta.maintainers = with lib.maintainers; [ ehmry ]; + + nodes.server = { + environment.systemPackages = [ pkgs.eris-go pkgs.nim.pkgs.eris ]; + services.eris-server = { + enable = true; + decode = true; + listenHttp = "[::1]:80"; + backends = [ "badger+file:///var/cache/eris.badger?get&put" ]; + mountpoint = "/eris"; + }; + }; + + testScript = '' + start_all() + server.wait_for_unit("eris-server.service") + server.wait_for_open_port(5683) + server.wait_for_open_port(80) + server.succeed("eriscmd get http://[::1] $(echo 'Hail ERIS!' | eriscmd put coap+tcp://[::1]:5683)") + ''; +}) diff --git a/nixos/tests/kernel-generic.nix b/nixos/tests/kernel-generic.nix index e4a8e06df1ef3..e69dd550289c1 100644 --- a/nixos/tests/kernel-generic.nix +++ b/nixos/tests/kernel-generic.nix @@ -42,7 +42,9 @@ let }; in mapAttrs (_: lP: testsForLinuxPackages lP) kernels // { - inherit testsForLinuxPackages; + passthru = { + inherit testsForLinuxPackages; - testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel); + testsForKernel = kernel: testsForLinuxPackages (pkgs.linuxPackagesFor kernel); + }; } diff --git a/nixos/tests/paperless.nix b/nixos/tests/paperless.nix index 7f36de4c29b71..ce6a4d8128dfd 100644 --- a/nixos/tests/paperless.nix +++ b/nixos/tests/paperless.nix @@ -30,20 +30,27 @@ import ./make-test-python.nix ({ lib, ... }: { with subtest("Task-queue gets ready"): machine.wait_for_unit("paperless-task-queue.service") - with subtest("Add a document via the web interface"): + with subtest("Add a png document via the web interface"): machine.succeed( "convert -size 400x40 xc:white -font 'DejaVu-Sans' -pointsize 20 -fill black " "-annotate +5+20 'hello web 16-10-2005' /tmp/webdoc.png" ) machine.wait_until_succeeds("curl -u admin:admin -F document=@/tmp/webdoc.png -fs localhost:28981/api/documents/post_document/") + with subtest("Add a txt document via the web interface"): + machine.succeed( + "echo 'hello web 16-10-2005' > /tmp/webdoc.txt" + ) + machine.wait_until_succeeds("curl -u admin:admin -F document=@/tmp/webdoc.txt -fs localhost:28981/api/documents/post_document/") + with subtest("Documents are consumed"): machine.wait_until_succeeds( - "(($(curl -u admin:admin -fs localhost:28981/api/documents/ | jq .count) == 2))" + "(($(curl -u admin:admin -fs localhost:28981/api/documents/ | jq .count) == 3))" ) docs = json.loads(machine.succeed("curl -u admin:admin -fs localhost:28981/api/documents/"))['results'] assert "2005-10-16" in docs[0]['created'] assert "2005-10-16" in docs[1]['created'] + assert "2005-10-16" in docs[2]['created'] # Detects gunicorn issues, see PR #190888 with subtest("Document metadata can be accessed"): @@ -52,5 +59,8 @@ import ./make-test-python.nix ({ lib, ... }: { metadata = json.loads(machine.succeed("curl -u admin:admin -fs localhost:28981/api/documents/2/metadata/")) assert "original_checksum" in metadata + + metadata = json.loads(machine.succeed("curl -u admin:admin -fs localhost:28981/api/documents/3/metadata/")) + assert "original_checksum" in metadata ''; }) |