diff options
Diffstat (limited to 'nixos')
51 files changed, 756 insertions, 340 deletions
diff --git a/nixos/doc/manual/development/option-declarations.section.md b/nixos/doc/manual/development/option-declarations.section.md index 2e11218e82389..ef7255557a109 100644 --- a/nixos/doc/manual/development/option-declarations.section.md +++ b/nixos/doc/manual/development/option-declarations.section.md @@ -120,14 +120,14 @@ lib.mkOption { ```nix lib.mkPackageOption pkgs "GHC" { default = [ "ghc" ]; - example = "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])"; + example = "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])"; } # is like lib.mkOption { type = lib.types.package; default = pkgs.ghc; defaultText = lib.literalExpression "pkgs.ghc"; - example = lib.literalExpression "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])"; + example = lib.literalExpression "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])"; description = "The GHC package to use."; } ``` diff --git a/nixos/doc/manual/development/writing-nixos-tests.section.md b/nixos/doc/manual/development/writing-nixos-tests.section.md index e5ee1cb01ff16..f4f4056ad9889 100644 --- a/nixos/doc/manual/development/writing-nixos-tests.section.md +++ b/nixos/doc/manual/development/writing-nixos-tests.section.md @@ -332,6 +332,19 @@ repository): ''; ``` +Similarly, the type checking of test scripts can be disabled in the following +way: + +```nix +import ./make-test-python.nix { + skipTypeCheck = true; + nodes.machine = + { config, pkgs, ... }: + { configuration… + }; +} +``` + ## Failing tests early {#ssec-failing-tests-early} To fail tests early when certain invariables are no longer met (instead of waiting for the build to time out), the decorator `polling_condition` is provided. For example, if we are testing a program `foo` that should not quit after being started, we might write the following: @@ -380,3 +393,25 @@ with foo_running: def foo_running(): machine.succeed("pgrep -x foo") ``` + +## Adding Python packages to the test script {#ssec-python-packages-in-test-script} + +When additional Python libraries are required in the test script, they can be +added using the parameter `extraPythonPackages`. For example, you could add +`numpy` like this: + +```nix +import ./make-test-python.nix +{ + extraPythonPackages = p: [ p.numpy ]; + + nodes = { }; + + testScript = '' + import numpy as np + assert str(np.zeros(4) == "array([0., 0., 0., 0.])") + ''; +} +``` + +In that case, `numpy` is chosen from the generic `python3Packages`. diff --git a/nixos/doc/manual/from_md/development/option-declarations.section.xml b/nixos/doc/manual/from_md/development/option-declarations.section.xml index 91867c224107a..381163dd7c74d 100644 --- a/nixos/doc/manual/from_md/development/option-declarations.section.xml +++ b/nixos/doc/manual/from_md/development/option-declarations.section.xml @@ -183,14 +183,14 @@ lib.mkOption { <programlisting language="bash"> lib.mkPackageOption pkgs "GHC" { default = [ "ghc" ]; - example = "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])"; + example = "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])"; } # is like lib.mkOption { type = lib.types.package; default = pkgs.ghc; defaultText = lib.literalExpression "pkgs.ghc"; - example = lib.literalExpression "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])"; + example = lib.literalExpression "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])"; description = "The GHC package to use."; } </programlisting> diff --git a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml index 7ce3e4cb29065..46367bdd345d1 100644 --- a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml +++ b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml @@ -590,6 +590,19 @@ import ./make-test-python.nix { # fmt: on ''; </programlisting> + <para> + Similarly, the type checking of test scripts can be disabled in + the following way: + </para> + <programlisting language="bash"> +import ./make-test-python.nix { + skipTypeCheck = true; + nodes.machine = + { config, pkgs, ... }: + { configuration… + }; +} +</programlisting> </section> <section xml:id="ssec-failing-tests-early"> <title>Failing tests early</title> @@ -652,4 +665,30 @@ def foo_running(): ``` </programlisting> </section> + <section xml:id="ssec-python-packages-in-test-script"> + <title>Adding Python packages to the test script</title> + <para> + When additional Python libraries are required in the test script, + they can be added using the parameter + <literal>extraPythonPackages</literal>. For example, you could add + <literal>numpy</literal> like this: + </para> + <programlisting language="bash"> +import ./make-test-python.nix +{ + extraPythonPackages = p: [ p.numpy ]; + + nodes = { }; + + testScript = '' + import numpy as np + assert str(np.zeros(4) == "array([0., 0., 0., 0.])") + ''; +} +</programlisting> + <para> + In that case, <literal>numpy</literal> is chosen from the generic + <literal>python3Packages</literal>. + </para> + </section> </section> diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 8c090e6cc1a09..5208671e4dab0 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -2102,6 +2102,28 @@ cp /var/lib/redis/dump.rdb "/var/lib/redis-mastodon/dump.rdb" </listitem> <listitem> <para> + Peertube now uses services.redis.servers to start a new redis + server, instead of using a global redis server. This improves + compatibility with other services that use redis. + </para> + <para> + Redis database is used for storage only cache and job queue. + More information can be found here - + <link xlink:href="https://docs.joinpeertube.org/contribute-architecture">Peertube + architecture</link>. + </para> + <para> + If you do want to save the redis database, you can use the + following commands before upgrade OS: + </para> + <programlisting language="bash"> +redis-cli save +sudo mkdir /var/lib/redis-peertube +sudo cp /var/lib/redis/dump.rdb /var/lib/redis-peertube/dump.rdb +</programlisting> + </listitem> + <listitem> + <para> If you are using Wayland you can choose to use the Ozone Wayland support in Chrome and several Electron apps by setting the environment variable <literal>NIXOS_OZONE_WL=1</literal> diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index 55c20427cfdef..65ba6033c8341 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -40,7 +40,7 @@ </section> <section xml:id="sec-release-22.11-new-services"> <title>New Services</title> - <itemizedlist spacing="compact"> + <itemizedlist> <listitem> <para> <link xlink:href="https://github.com/jollheef/appvm">appvm</link>, @@ -48,6 +48,13 @@ <link xlink:href="options.html#opt-virtualisation.appvm.enable">virtualisation.appvm</link>. </para> </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/leetronics/infnoise">infnoise</link>, + a hardware True Random Number Generator dongle. Available as + <link xlink:href="options.html#opt-services.infnoise.enable">services.infnoise</link>. + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-22.11-incompatibilities"> @@ -89,7 +96,7 @@ </section> <section xml:id="sec-release-22.11-notable-changes"> <title>Other Notable Changes</title> - <itemizedlist spacing="compact"> + <itemizedlist> <listitem> <para> A new module was added for the Saleae Logic device family, @@ -98,6 +105,24 @@ <literal>hardware.saleae-logic.package</literal>. </para> </listitem> + <listitem> + <para> + Matrix Synapse now requires entries in the + <literal>state_group_edges</literal> table to be unique, in + order to prevent accidentally introducing duplicate + information (for example, because a database backup was + restored multiple times). If your Synapse database already has + duplicate rows in this table, this could fail with an error + and require manual remediation. + </para> + </listitem> + <listitem> + <para> + memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2. + It is now the upstream version from https://www.memtest.org/, + as coreboot’s fork is no longer available. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index e4dc540eaafe1..faf941f569966 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -765,6 +765,17 @@ In addition to numerous new and upgraded packages, this release has the followin redis-cli save cp /var/lib/redis/dump.rdb "/var/lib/redis-mastodon/dump.rdb" ``` +- Peertube now uses services.redis.servers to start a new redis server, instead of using a global redis server. + This improves compatibility with other services that use redis. + + Redis database is used for storage only cache and job queue. More information can be found here - [Peertube architecture](https://docs.joinpeertube.org/contribute-architecture). + + If you do want to save the redis database, you can use the following commands before upgrade OS: + ```bash + redis-cli save + sudo mkdir /var/lib/redis-peertube + sudo cp /var/lib/redis/dump.rdb /var/lib/redis-peertube/dump.rdb + ``` - If you are using Wayland you can choose to use the Ozone Wayland support in Chrome and several Electron apps by setting the environment variable diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index 97ecb725dfb5c..864fe5c693460 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -25,6 +25,9 @@ In addition to numerous new and upgraded packages, this release has the followin - [appvm](https://github.com/jollheef/appvm), Nix based app VMs. Available as [virtualisation.appvm](options.html#opt-virtualisation.appvm.enable). +- [infnoise](https://github.com/leetronics/infnoise), a hardware True Random Number Generator dongle. + Available as [services.infnoise](options.html#opt-services.infnoise.enable). + <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> ## Backward Incompatibilities {#sec-release-22.11-incompatibilities} @@ -44,6 +47,10 @@ In addition to numerous new and upgraded packages, this release has the followin ## Other Notable Changes {#sec-release-22.11-notable-changes} -* A new module was added for the Saleae Logic device family, providing the options `hardware.saleae-logic.enable` and `hardware.saleae-logic.package`. +- A new module was added for the Saleae Logic device family, providing the options `hardware.saleae-logic.enable` and `hardware.saleae-logic.package`. + +- Matrix Synapse now requires entries in the `state_group_edges` table to be unique, in order to prevent accidentally introducing duplicate information (for example, because a database backup was restored multiple times). If your Synapse database already has duplicate rows in this table, this could fail with an error and require manual remediation. + +- memtest86+ was updated from 5.00-coreboot-002 to 6.00-beta2. It is now the upstream version from https://www.memtest.org/, as coreboot's fork is no longer available. <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> diff --git a/nixos/lib/test-driver/default.nix b/nixos/lib/test-driver/default.nix index 3aee913431890..e3786622c3c58 100644 --- a/nixos/lib/test-driver/default.nix +++ b/nixos/lib/test-driver/default.nix @@ -10,6 +10,7 @@ , socat , tesseract4 , vde2 +, extraPythonPackages ? (_ : []) }: python3Packages.buildPythonApplication rec { @@ -17,14 +18,25 @@ python3Packages.buildPythonApplication rec { version = "1.1"; src = ./.; - propagatedBuildInputs = [ coreutils netpbm python3Packages.colorama python3Packages.ptpython qemu_pkg socat vde2 ] - ++ (lib.optionals enableOCR [ imagemagick_light tesseract4 ]); + propagatedBuildInputs = [ + coreutils + netpbm + python3Packages.colorama + python3Packages.ptpython + qemu_pkg + socat + vde2 + ] + ++ (lib.optionals enableOCR [ imagemagick_light tesseract4 ]) + ++ extraPythonPackages python3Packages; doCheck = true; checkInputs = with python3Packages; [ mypy pylint black ]; checkPhase = '' mypy --disallow-untyped-defs \ --no-implicit-optional \ + --pretty \ + --no-color-output \ --ignore-missing-imports ${src}/test_driver pylint --errors-only --enable=unused-import ${src}/test_driver black --check --diff ${src}/test_driver diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py index 035e3ffe89731..3ff3cf5645f82 100644 --- a/nixos/lib/test-driver/test_driver/machine.py +++ b/nixos/lib/test-driver/test_driver/machine.py @@ -682,7 +682,7 @@ class Machine: with self.nested("waiting for {} to appear on tty {}".format(regexp, tty)): retry(tty_matches) - def send_chars(self, chars: List[str]) -> None: + def send_chars(self, chars: str) -> None: with self.nested("sending keys ‘{}‘".format(chars)): for char in chars: self.send_key(char) diff --git a/nixos/lib/test-driver/test_driver/py.typed b/nixos/lib/test-driver/test_driver/py.typed new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/nixos/lib/test-driver/test_driver/py.typed diff --git a/nixos/lib/test-script-prepend.py b/nixos/lib/test-script-prepend.py new file mode 100644 index 0000000000000..15e59ce01047d --- /dev/null +++ b/nixos/lib/test-script-prepend.py @@ -0,0 +1,42 @@ +# This file contains type hints that can be prepended to Nix test scripts so they can be type +# checked. + +from test_driver.driver import Driver +from test_driver.vlan import VLan +from test_driver.machine import Machine +from test_driver.logger import Logger +from typing import Callable, Iterator, ContextManager, Optional, List, Dict, Any, Union +from typing_extensions import Protocol +from pathlib import Path + + +class RetryProtocol(Protocol): + def __call__(self, fn: Callable, timeout: int = 900) -> None: + raise Exception("This is just type information for the Nix test driver") + + +class PollingConditionProtocol(Protocol): + def __call__( + self, + fun_: Optional[Callable] = None, + *, + seconds_interval: float = 2.0, + description: Optional[str] = None, + ) -> Union[Callable[[Callable], ContextManager], ContextManager]: + raise Exception("This is just type information for the Nix test driver") + + +start_all: Callable[[], None] +subtest: Callable[[str], ContextManager[None]] +retry: RetryProtocol +test_script: Callable[[], None] +machines: List[Machine] +vlans: List[VLan] +driver: Driver +log: Logger +create_machine: Callable[[Dict[str, Any]], Machine] +run_tests: Callable[[], None] +join_all: Callable[[], None] +serial_stdout_off: Callable[[], None] +serial_stdout_on: Callable[[], None] +polling_condition: PollingConditionProtocol diff --git a/nixos/lib/testing-python.nix b/nixos/lib/testing-python.nix index c1015ec0aca0c..a6868a708aaf3 100644 --- a/nixos/lib/testing-python.nix +++ b/nixos/lib/testing-python.nix @@ -50,14 +50,16 @@ rec { , qemu_pkg ? pkgs.qemu_test , enableOCR ? false , skipLint ? false + , skipTypeCheck ? false , passthru ? {} , interactive ? false + , extraPythonPackages ? (_ :[]) }: let # Reifies and correctly wraps the python test driver for # the respective qemu version and with or without ocr support testDriver = pkgs.callPackage ./test-driver { - inherit enableOCR; + inherit enableOCR extraPythonPackages; qemu_pkg = qemu_test; imagemagick_light = imagemagick_light.override { inherit libtiff; }; tesseract4 = tesseract4.override { enableLanguages = [ "eng" ]; }; @@ -85,7 +87,7 @@ rec { nodeHostNames = let nodesList = map (c: c.config.system.name) (lib.attrValues nodes); - in nodesList ++ lib.optional (lib.length nodesList == 1) "machine"; + in nodesList ++ lib.optional (lib.length nodesList == 1 && !lib.elem "machine" nodesList) "machine"; # TODO: This is an implementation error and needs fixing # the testing famework cannot legitimately restrict hostnames further @@ -100,6 +102,9 @@ rec { then testScript { inherit nodes; } else testScript; + uniqueVlans = lib.unique (builtins.concatLists vlans); + vlanNames = map (i: "vlan${toString i}: VLan;") uniqueVlans; + machineNames = map (name: "${name}: Machine;") nodeHostNames; in if lib.length invalidNodeNames > 0 then throw '' @@ -113,7 +118,7 @@ rec { else lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName { inherit testName; - nativeBuildInputs = [ makeWrapper ]; + nativeBuildInputs = [ makeWrapper mypy ]; testScript = testScript'; preferLocalBuild = true; passthru = passthru // { @@ -125,7 +130,25 @@ rec { mkdir -p $out/bin vmStartScripts=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)) - echo -n "$testScript" > $out/test-script + + ${lib.optionalString (!skipTypeCheck) '' + # prepend type hints so the test script can be type checked with mypy + cat "${./test-script-prepend.py}" >> testScriptWithTypes + echo "${builtins.toString machineNames}" >> testScriptWithTypes + echo "${builtins.toString vlanNames}" >> testScriptWithTypes + echo -n "$testScript" >> testScriptWithTypes + + # set pythonpath so mypy knows where to find the imports. this requires the py.typed file. + export PYTHONPATH='${./test-driver}' + mypy --no-implicit-optional \ + --pretty \ + --no-color-output \ + testScriptWithTypes + unset PYTHONPATH + ''} + + echo -n "$testScript" >> $out/test-script + ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver ${testDriver}/bin/generate-driver-symbols @@ -152,6 +175,7 @@ rec { , testScript , enableOCR ? false , name ? "unnamed" + , skipTypeCheck ? false # Skip linting (mainly intended for faster dev cycles) , skipLint ? false , passthru ? {} @@ -161,6 +185,7 @@ rec { (if meta.description or null != null then builtins.unsafeGetAttrPos "description" meta else builtins.unsafeGetAttrPos "testScript" t) + , extraPythonPackages ? (_ : []) } @ t: let mkNodes = qemu_pkg: @@ -213,13 +238,13 @@ rec { ); driver = setupDriverForTest { - inherit testScript enableOCR skipLint passthru; + inherit testScript enableOCR skipTypeCheck skipLint passthru extraPythonPackages; testName = name; qemu_pkg = pkgs.qemu_test; nodes = mkNodes pkgs.qemu_test; }; driverInteractive = setupDriverForTest { - inherit testScript enableOCR skipLint passthru; + inherit testScript enableOCR skipTypeCheck skipLint passthru extraPythonPackages; testName = name; qemu_pkg = pkgs.qemu; nodes = mkNodes pkgs.qemu; diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 210d45ac84153..a9b04bcc85959 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -163,8 +163,19 @@ in ''; }; + hardware.nvidia.forceFullCompositionPipeline = lib.mkOption { + default = false; + type = types.bool; + description = '' + Whether to force-enable the full composition pipeline. + This sometimes fixes screen tearing issues. + This has been reported to reduce the performance of some OpenGL applications and may produce issues in WebGL. + It also drastically increases the time the driver needs to clock down after load. + ''; + }; + hardware.nvidia.package = lib.mkOption { - type = lib.types.package; + type = types.package; default = config.boot.kernelPackages.nvidiaPackages.stable; defaultText = literalExpression "config.boot.kernelPackages.nvidiaPackages.stable"; description = '' @@ -255,13 +266,18 @@ in '' BusID "${pCfg.nvidiaBusId}" ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""} - ${optionalString cfg.powerManagement.finegrained "Option \"NVreg_DynamicPowerManagement=0x02\""} ''; screenSection = '' Option "RandRRotation" "on" - ${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""} - ''; + '' + optionalString syncCfg.enable '' + Option "AllowEmptyInitialConfiguration" + '' + optionalString cfg.forceFullCompositionPipeline '' + Option "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}" + Option "AllowIndirectGLXProtocol" "off" + Option "TripleBuffer" "on" + '' + ; }; services.xserver.serverLayoutSection = optionalString syncCfg.enable '' @@ -367,7 +383,8 @@ in RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%c{3} c 195 %c{3}" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" - '' + optionalString cfg.powerManagement.finegrained '' + '' + optionalString cfg.powerManagement.finegrained ( + optionalString (versionOlder config.boot.kernelPackages.kernel.version "5.5") '' # Remove NVIDIA USB xHCI Host Controller devices, if present ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1" @@ -376,7 +393,7 @@ in # Remove NVIDIA Audio devices, if present ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1" - + '' + '' # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto" ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto" @@ -384,7 +401,7 @@ in # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on" ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on" - ''; + ''); boot.extraModprobeConfig = mkIf cfg.powerManagement.finegrained '' options nvidia "NVreg_DynamicPowerManagement=0x02" diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 902fffd60f9b9..d59d7bfe40d9f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -983,6 +983,7 @@ ./services/security/hologram-server.nix ./services/security/hologram-agent.nix ./services/security/kanidm.nix + ./services/security/infnoise.nix ./services/security/munge.nix ./services/security/nginx-sso.nix ./services/security/oauth2_proxy.nix diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix index 8ff8e31864be2..333fdd494e3b9 100644 --- a/nixos/modules/services/backup/restic.nix +++ b/nixos/modules/services/backup/restic.nix @@ -96,13 +96,22 @@ in }; repository = mkOption { - type = types.str; + type = with types; nullOr str; + default = null; description = '' repository to backup to. ''; example = "sftp:backup@192.168.1.100:/backups/${name}"; }; + repositoryFile = mkOption { + type = with types; nullOr path; + default = null; + description = '' + Path to the file containing the repository location to backup to. + ''; + }; + paths = mkOption { type = types.nullOr (types.listOf types.str); default = null; @@ -142,7 +151,7 @@ in extraBackupArgs = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Extra arguments passed to restic backup. ''; @@ -153,7 +162,7 @@ in extraOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Extra extended options to be passed to the restic --option flag. ''; @@ -172,7 +181,7 @@ in pruneOpts = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' A list of options (--keep-* et al.) for 'restic forget --prune', to automatically prune old snapshots. The @@ -197,9 +206,25 @@ in ''; example = "find /home/matt/git -type d -name .git"; }; + + backupPrepareCommand = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A script that must run before starting the backup process. + ''; + }; + + backupCleanupCommand = mkOption { + type = with types; nullOr str; + default = null; + description = '' + A script that must run after finishing the backup process. + ''; + }; }; })); - default = {}; + default = { }; example = { localbackup = { paths = [ "/home" ]; @@ -225,66 +250,85 @@ in config = { warnings = mapAttrsToList (n: v: "services.restic.backups.${n}.s3CredentialsFile is deprecated, please use services.restic.backups.${n}.environmentFile instead.") (filterAttrs (n: v: v.s3CredentialsFile != null) config.services.restic.backups); systemd.services = - mapAttrs' (name: backup: - let - extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions; - resticCmd = "${pkgs.restic}/bin/restic${extraOptions}"; - filesFromTmpFile = "/run/restic-backups-${name}/includes"; - backupPaths = if (backup.dynamicFilesFrom == null) - then if (backup.paths != null) then concatStringsSep " " backup.paths else "" - else "--files-from ${filesFromTmpFile}"; - pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [ - ( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) ) - ( resticCmd + " check" ) - ]; - # Helper functions for rclone remotes - rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1; - rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v); - rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v); - toRcloneVal = v: if lib.isBool v then lib.boolToString v else v; - in nameValuePair "restic-backups-${name}" ({ - environment = { - RESTIC_PASSWORD_FILE = backup.passwordFile; - RESTIC_REPOSITORY = backup.repository; - } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs' (name: value: - nameValuePair (rcloneAttrToOpt name) (toRcloneVal value) - ) backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) { - RCLONE_CONFIG = backup.rcloneConfigFile; - } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs' (name: value: - nameValuePair (rcloneAttrToConf name) (toRcloneVal value) - ) backup.rcloneConfig); - path = [ pkgs.openssh ]; - restartIfChanged = false; - serviceConfig = { - Type = "oneshot"; - ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ]) - ++ pruneCmd; - User = backup.user; - RuntimeDirectory = "restic-backups-${name}"; - CacheDirectory = "restic-backups-${name}"; - CacheDirectoryMode = "0700"; - } // optionalAttrs (backup.environmentFile != null) { - EnvironmentFile = backup.environmentFile; - }; - } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null) { - preStart = '' - ${optionalString (backup.initialize) '' - ${resticCmd} snapshots || ${resticCmd} init - ''} - ${optionalString (backup.dynamicFilesFrom != null) '' - ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile} - ''} - ''; - } // optionalAttrs (backup.dynamicFilesFrom != null) { - postStart = '' - rm ${filesFromTmpFile} - ''; - }) - ) config.services.restic.backups; + mapAttrs' + (name: backup: + let + extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions; + resticCmd = "${pkgs.restic}/bin/restic${extraOptions}"; + filesFromTmpFile = "/run/restic-backups-${name}/includes"; + backupPaths = + if (backup.dynamicFilesFrom == null) + then if (backup.paths != null) then concatStringsSep " " backup.paths else "" + else "--files-from ${filesFromTmpFile}"; + pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [ + (resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts)) + (resticCmd + " check") + ]; + # Helper functions for rclone remotes + rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1; + rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v); + rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v); + toRcloneVal = v: if lib.isBool v then lib.boolToString v else v; + in + nameValuePair "restic-backups-${name}" ({ + environment = { + RESTIC_PASSWORD_FILE = backup.passwordFile; + RESTIC_REPOSITORY = backup.repository; + RESTIC_REPOSITORY_FILE = backup.repositoryFile; + } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs' + (name: value: + nameValuePair (rcloneAttrToOpt name) (toRcloneVal value) + ) + backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) { + RCLONE_CONFIG = backup.rcloneConfigFile; + } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs' + (name: value: + nameValuePair (rcloneAttrToConf name) (toRcloneVal value) + ) + backup.rcloneConfig); + path = [ pkgs.openssh ]; + restartIfChanged = false; + serviceConfig = { + Type = "oneshot"; + ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ]) + ++ pruneCmd; + User = backup.user; + RuntimeDirectory = "restic-backups-${name}"; + CacheDirectory = "restic-backups-${name}"; + CacheDirectoryMode = "0700"; + } // optionalAttrs (backup.environmentFile != null) { + EnvironmentFile = backup.environmentFile; + }; + } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null || backup.backupPrepareCommand != null) { + preStart = '' + ${optionalString (backup.backupPrepareCommand != null) '' + ${pkgs.writeScript "backupPrepareCommand" backup.backupPrepareCommand} + ''} + ${optionalString (backup.initialize) '' + ${resticCmd} snapshots || ${resticCmd} init + ''} + ${optionalString (backup.dynamicFilesFrom != null) '' + ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile} + ''} + ''; + } // optionalAttrs (backup.dynamicFilesFrom != null || backup.backupCleanupCommand != null) { + postStart = '' + ${optionalString (backup.backupCleanupCommand != null) '' + ${pkgs.writeScript "backupCleanupCommand" backup.backupCleanupCommand} + ''} + ${optionalString (backup.dynamicFilesFrom != null) '' + rm ${filesFromTmpFile} + ''} + ''; + }) + ) + config.services.restic.backups; systemd.timers = - mapAttrs' (name: backup: nameValuePair "restic-backups-${name}" { - wantedBy = [ "timers.target" ]; - timerConfig = backup.timerConfig; - }) config.services.restic.backups; + mapAttrs' + (name: backup: nameValuePair "restic-backups-${name}" { + wantedBy = [ "timers.target" ]; + timerConfig = backup.timerConfig; + }) + config.services.restic.backups; }; } diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix index 9440382e66a19..87806d48e89f3 100644 --- a/nixos/modules/services/continuous-integration/hydra/default.nix +++ b/nixos/modules/services/continuous-integration/hydra/default.nix @@ -310,7 +310,11 @@ in mkdir -m 0700 -p ${baseDir}/queue-runner mkdir -m 0750 -p ${baseDir}/build-logs - chown hydra-queue-runner:hydra ${baseDir}/queue-runner ${baseDir}/build-logs + mkdir -m 0750 -p ${baseDir}/runcommand-logs + chown hydra-queue-runner.hydra \ + ${baseDir}/queue-runner \ + ${baseDir}/build-logs \ + ${baseDir}/runcommand-logs ${optionalString haveLocalDB '' if ! [ -e ${baseDir}/.db-created ]; then diff --git a/nixos/modules/services/desktops/pipewire/pipewire.nix b/nixos/modules/services/desktops/pipewire/pipewire.nix index 1323336d866e9..6459b22519dbe 100644 --- a/nixos/modules/services/desktops/pipewire/pipewire.nix +++ b/nixos/modules/services/desktops/pipewire/pipewire.nix @@ -239,7 +239,7 @@ in { }; environment.sessionVariables.LD_LIBRARY_PATH = - lib.optional cfg.jack.enable "${cfg.package.jack}/lib"; + lib.mkIf cfg.jack.enable [ "${cfg.package.jack}/lib" ]; users = lib.mkIf cfg.systemWide { users.pipewire = { diff --git a/nixos/modules/services/games/asf.nix b/nixos/modules/services/games/asf.nix index ea2bfd40fffaa..ed1a5544d7a48 100644 --- a/nixos/modules/services/games/asf.nix +++ b/nixos/modules/services/games/asf.nix @@ -13,6 +13,8 @@ let # is in theory not needed as this is already the default for default builds UpdateChannel = 0; Headless = true; + } // lib.optionalAttrs (cfg.ipcPasswordFile != null) { + IPCPassword = "#ipcPassword#"; }); ipc-config = format.generate "IPC.config" cfg.ipcSettings; @@ -81,8 +83,7 @@ in type = format.type; description = '' The ASF.json file, all the options are documented <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config">here</link>. - Do note that `AutoRestart` and `UpdateChannel` is always to `false` -respectively `0` because NixOS takes care of updating everything. + Do note that `AutoRestart` and `UpdateChannel` is always to `false` respectively `0` because NixOS takes care of updating everything. `Headless` is also always set to `true` because there is no way to provide inputs via a systemd service. You should try to keep ASF up to date since upstream does not provide support for anything but the latest version and you're exposing yourself to all kinds of issues - as is outlined <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#updateperiod">here</link>. ''; @@ -92,6 +93,12 @@ respectively `0` because NixOS takes care of updating everything. default = { }; }; + ipcPasswordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group."; + }; + ipcSettings = mkOption { type = format.type; description = '' @@ -115,14 +122,12 @@ respectively `0` because NixOS takes care of updating everything. options = { username = mkOption { type = types.str; - description = - "Name of the user to log in. Default is attribute name."; + description = "Name of the user to log in. Default is attribute name."; default = ""; }; passwordFile = mkOption { type = types.path; - description = - "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group."; + description = "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group."; }; enabled = mkOption { type = types.bool; @@ -131,8 +136,7 @@ respectively `0` because NixOS takes care of updating everything. }; settings = mkOption { type = types.attrs; - description = - "Additional settings that are documented <link xlink:href=\"https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config\">here</link>."; + description = "Additional settings that are documented <link xlink:href=\"https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config\">here</link>."; default = { }; }; }; @@ -170,14 +174,17 @@ respectively `0` because NixOS takes care of updating everything. wantedBy = [ "multi-user.target" ]; serviceConfig = mkMerge [ - (mkIf (cfg.dataDir == "/var/lib/asf") { StateDirectory = "asf"; }) + (mkIf (cfg.dataDir == "/var/lib/asf") { + StateDirectory = "asf"; + StateDirectoryMode = "700"; + }) { User = "asf"; Group = "asf"; WorkingDirectory = cfg.dataDir; Type = "simple"; - ExecStart = - "${cfg.package}/bin/ArchiSteamFarm --path ${cfg.dataDir} --process-required --no-restart --service --no-config-migrate"; + ExecStart = "${cfg.package}/bin/ArchiSteamFarm --path ${cfg.dataDir} --process-required --no-restart --service --no-config-migrate"; + Restart = "always"; # mostly copied from the default systemd service PrivateTmp = true; @@ -202,35 +209,47 @@ respectively `0` because NixOS takes care of updating everything. } ]; - preStart = '' - mkdir -p config - rm -f www - rm -f config/{*.json,*.config} - - ln -s ${asf-config} config/ASF.json - - ${strings.optionalString (cfg.ipcSettings != {}) '' - ln -s ${ipc-config} config/IPC.config - ''} - - ln -s ${pkgs.runCommandLocal "ASF-bots" {} '' - mkdir -p $out/lib/asf/bots - for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=","; - set -- $i - ln -s $2 $out/lib/asf/bots/$1 - done - ''}/lib/asf/bots/* config/ - - ${strings.optionalString cfg.web-ui.enable '' - ln -s ${cfg.web-ui.package}/lib/dist www - ''} - ''; + preStart = + let + createBotsScript = pkgs.runCommandLocal "ASF-bots" { } '' + mkdir -p $out + # clean potential removed bots + rm -rf $out/*.json + for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=","; + set -- $i + ln -fs $2 $out/$1 + done + ''; + replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret"; + in + '' + mkdir -p config + + cp --no-preserve=mode ${asf-config} config/ASF.json + + ${optionalString (cfg.ipcPasswordFile != null) '' + ${replaceSecretBin} '#ipcPassword#' '${cfg.ipcPasswordFile}' config/ASF.json + ''} + + ${optionalString (cfg.ipcSettings != {}) '' + ln -fs ${ipc-config} config/IPC.config + ''} + + ${optionalString (cfg.ipcSettings != {}) '' + ln -fs ${createBotsScript}/* config/ + ''} + + rm -f www + ${optionalString cfg.web-ui.enable '' + ln -s ${cfg.web-ui.package}/lib/dist www + ''} + ''; }; }; }; meta = { buildDocsInSandbox = false; - maintainers = with maintainers; [ lom ]; + maintainers = with maintainers; [ lom SuperSandro2000 ]; }; } diff --git a/nixos/modules/services/misc/uhub.nix b/nixos/modules/services/misc/uhub.nix index 0d0a8c2a4cb81..99774fbb920a0 100644 --- a/nixos/modules/services/misc/uhub.nix +++ b/nixos/modules/services/misc/uhub.nix @@ -80,11 +80,12 @@ in { tls_enable = cfg.enableTLS; file_plugins = pkgs.writeText "uhub-plugins.conf" (lib.strings.concatStringsSep "\n" (map ({ plugin, settings }: - "plugin ${plugin} ${ - toString - (lib.attrsets.mapAttrsToList (key: value: ''"${key}=${value}"'') - settings) - }") cfg.plugins)); + '' + plugin ${plugin} "${ + toString + (lib.attrsets.mapAttrsToList (key: value: "${key}=${value}") + settings) + }"'') cfg.plugins)); }; in { name = "uhub/${name}.conf"; @@ -104,6 +105,9 @@ in { ExecStart = "${pkg}/bin/uhub -c /etc/uhub/${name}.conf -L"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; DynamicUser = true; + + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; }; }; }) hubs; diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index f528d18304244..489dd337bb7cc 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -201,6 +201,8 @@ in { serviceConfig = { ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c /etc/netdata/netdata.conf"; ExecReload = "${pkgs.util-linux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID"; + ExecPostStart = ''while [ "$(netdatacli ping)" != pong ]; do sleep 0.5; done''; + TimeoutStopSec = 60; Restart = "on-failure"; # User and group diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix index a683c537f05b2..e88daae1fbbac 100644 --- a/nixos/modules/services/networking/unifi.nix +++ b/nixos/modules/services/networking/unifi.nix @@ -51,7 +51,7 @@ in services.unifi.openFirewall = mkOption { type = types.bool; - default = true; + default = false; description = '' Whether or not to open the minimum required ports on the firewall. @@ -85,10 +85,6 @@ in config = mkIf cfg.enable { - warnings = optional - (options.services.unifi.openFirewall.highestPrio >= (mkOptionDefault null).priority) - "The current services.unifi.openFirewall = true default is deprecated and will change to false in 22.11. Set it explicitly to silence this warning."; - users.users.unifi = { isSystemUser = true; group = "unifi"; diff --git a/nixos/modules/services/security/infnoise.nix b/nixos/modules/services/security/infnoise.nix new file mode 100644 index 0000000000000..4fb8adaf33f89 --- /dev/null +++ b/nixos/modules/services/security/infnoise.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.infnoise; +in { + options = { + services.infnoise = { + enable = mkEnableOption "the Infinite Noise TRNG driver"; + + fillDevRandom = mkOption { + description = '' + Whether to run the infnoise driver as a daemon to refill /dev/random. + + If disabled, you can use the `infnoise` command-line tool to + manually obtain randomness. + ''; + type = types.bool; + default = true; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.infnoise ]; + + services.udev.extraRules = '' + SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", SYMLINK+="infnoise", TAG+="systemd", GROUP="dialout", MODE="0664", ENV{SYSTEMD_WANTS}="infnoise.service" + ''; + + systemd.services.infnoise = mkIf cfg.fillDevRandom { + description = "Infinite Noise TRNG driver"; + + bindsTo = [ "dev-infnoise.device" ]; + after = [ "dev-infnoise.device" ]; + + serviceConfig = { + ExecStart = "${pkgs.infnoise}/bin/infnoise --dev-random --debug"; + Restart = "always"; + User = "infnoise"; + DynamicUser = true; + SupplementaryGroups = [ "dialout" ]; + DeviceAllow = [ "/dev/infnoise" ]; + DevicePolicy = "closed"; + PrivateNetwork = true; + ProtectSystem = "strict"; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; # only reads entropy pool size and watermark + RestrictNamespaces = true; + RestrictRealtime = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + }; + }; + }; +} diff --git a/nixos/modules/services/web-apps/peertube.nix b/nixos/modules/services/web-apps/peertube.nix index e195e6e6e8240..e6b6aa273e7fb 100644 --- a/nixos/modules/services/web-apps/peertube.nix +++ b/nixos/modules/services/web-apps/peertube.nix @@ -209,7 +209,7 @@ in { port = lib.mkOption { type = lib.types.nullOr lib.types.port; - default = if cfg.redis.createLocally && cfg.redis.enableUnixSocket then null else 6379; + default = if cfg.redis.createLocally && cfg.redis.enableUnixSocket then null else 31638; defaultText = lib.literalExpression '' if config.${opt.redis.createLocally} && config.${opt.redis.enableUnixSocket} then null @@ -344,7 +344,7 @@ in { }; }; } - (lib.mkIf cfg.redis.enableUnixSocket { redis = { socket = "/run/redis/redis.sock"; }; }) + (lib.mkIf cfg.redis.enableUnixSocket { redis = { socket = "/run/redis-peertube/redis.sock"; }; }) ]; systemd.tmpfiles.rules = [ @@ -441,13 +441,17 @@ in { enable = true; }; - services.redis = lib.mkMerge [ + services.redis.servers.peertube = lib.mkMerge [ (lib.mkIf cfg.redis.createLocally { enable = true; }) + (lib.mkIf (cfg.redis.createLocally && !cfg.redis.enableUnixSocket) { + bind = "127.0.0.1"; + port = cfg.redis.port; + }) (lib.mkIf (cfg.redis.createLocally && cfg.redis.enableUnixSocket) { - unixSocket = "/run/redis/redis.sock"; - unixSocketPerm = 770; + unixSocket = "/run/redis-peertube/redis.sock"; + unixSocketPerm = 660; }) ]; @@ -465,7 +469,7 @@ in { }; }) (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package peertubeEnv peertubeCli pkgs.ffmpeg pkgs.nodejs-16_x pkgs.yarn ]) - (lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis" ];}) + (lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis-peertube" ];}) ]; users.groups = lib.optionalAttrs (cfg.group == "peertube") { diff --git a/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix index 4bf78fa16e7d9..5efe645d8aa24 100644 --- a/nixos/modules/services/x11/desktop-managers/phosh.nix +++ b/nixos/modules/services/x11/desktop-managers/phosh.nix @@ -78,7 +78,13 @@ let description = '' Display scaling factor. ''; - type = types.nullOr types.ints.unsigned; + type = types.nullOr ( + types.addCheck + (types.either types.int types.float) + (x : x > 0) + ) // { + description = "null or positive integer or float"; + }; default = null; example = 2; }; diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index b0f160c1dbf95..66fdc61d28357 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -219,14 +219,15 @@ let cidr = "${route.address}/${toString route.prefixLength}"; via = optionalString (route.via != null) ''via "${route.via}"''; options = concatStrings (mapAttrsToList (name: val: "${name} ${val} ") route.options); + type = toString route.type; in '' echo "${cidr}" >> $state echo -n "adding route ${cidr}... " - if out=$(ip route add "${cidr}" ${options} ${via} dev "${i.name}" proto static 2>&1); then + if out=$(ip route add ${type} "${cidr}" ${options} ${via} dev "${i.name}" proto static 2>&1); then echo "done" elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then - echo "'ip route add "${cidr}" ${options} ${via} dev "${i.name}"' failed: $out" + echo "'ip route add ${type} "${cidr}" ${options} ${via} dev "${i.name}"' failed: $out" exit 1 fi '' diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 110e84494a3dc..80808e0c08fa5 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -142,6 +142,9 @@ in optionalAttrs (route.via != null) { Gateway = route.via; } // + optionalAttrs (route.type != null) { + Type = route.type; + } // optionalAttrs (route.options ? onlink) { GatewayOnLink = true; } // diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index d56159f15960d..07bccf98f407f 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -90,6 +90,22 @@ let ''; }; + type = mkOption { + type = types.nullOr (types.enum [ + "unicast" "local" "broadcast" "multicast" + ]); + default = null; + description = '' + Type of the route. See the <literal>Route types</literal> section + in the <literal>ip-route(8)</literal> manual page for the details. + + Note that <literal>prohibit</literal>, <literal>blackhole</literal>, + <literal>unreachable</literal>, and <literal>throw</literal> cannot + be configured per device, so they are not available here. Similarly, + <literal>nat</literal> hasn't been supported since kernel 2.6. + ''; + }; + via = mkOption { type = types.nullOr types.str; default = null; diff --git a/nixos/modules/virtualisation/docker-rootless.nix b/nixos/modules/virtualisation/docker-rootless.nix index d371f67ecdc84..b814fa1c4358c 100644 --- a/nixos/modules/virtualisation/docker-rootless.nix +++ b/nixos/modules/virtualisation/docker-rootless.nix @@ -51,7 +51,6 @@ in default = pkgs.docker; defaultText = literalExpression "pkgs.docker"; type = types.package; - example = literalExpression "pkgs.docker-edge"; description = '' Docker package to be used in the module. ''; diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index a69cbe55c7845..c6eca4d6ed584 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -155,7 +155,6 @@ in default = pkgs.docker; defaultText = literalExpression "pkgs.docker"; type = types.package; - example = literalExpression "pkgs.docker-edge"; description = '' Docker package to be used in the module. ''; diff --git a/nixos/release.nix b/nixos/release.nix index 0df443dd204cb..e0d782bcaec3d 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -17,6 +17,7 @@ let # Run the tests for each platform. You can run a test by doing # e.g. ‘nix-build -A tests.login.x86_64-linux’, or equivalently, # ‘nix-build tests/login.nix -A result’. + # See also nixosTests in pkgs/top-level/all-packages.nix allTestsForSystem = system: import ./tests/all-tests.nix { inherit system; @@ -24,7 +25,19 @@ let callTest = t: { ${system} = hydraJob t.test; }; + } // { + # for typechecking of the scripts and evaluation of + # the nodes, without running VMs. + allDrivers = + import ./tests/all-tests.nix { + inherit system; + pkgs = import ./.. { inherit system; }; + callTest = t: { + ${system} = hydraJob t.test.driver; + }; + }; }; + allTests = foldAttrs recursiveUpdate {} (map allTestsForSystem supportedSystems); diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e61798676a0de..0f75548ff6fda 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -26,8 +26,8 @@ let featureFlags.minimalModules = {}; }; evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; }; -in -{ + +in { _3proxy = handleTest ./3proxy.nix {}; acme = handleTest ./acme.nix {}; adguardhome = handleTest ./adguardhome.nix {}; @@ -123,7 +123,6 @@ in doas = handleTest ./doas.nix {}; docker = handleTestOn ["x86_64-linux"] ./docker.nix {}; docker-rootless = handleTestOn ["x86_64-linux"] ./docker-rootless.nix {}; - docker-edge = handleTestOn ["x86_64-linux"] ./docker-edge.nix {}; docker-registry = handleTest ./docker-registry.nix {}; docker-tools = handleTestOn ["x86_64-linux"] ./docker-tools.nix {}; docker-tools-cross = handleTestOn ["x86_64-linux" "aarch64-linux"] ./docker-tools-cross.nix {}; @@ -152,6 +151,7 @@ in etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {}; etebase-server = handleTest ./etebase-server.nix {}; etesync-dav = handleTest ./etesync-dav.nix {}; + extra-python-packages = handleTest ./extra-python-packages.nix {}; fancontrol = handleTest ./fancontrol.nix {}; fcitx = handleTest ./fcitx {}; fenics = handleTest ./fenics.nix {}; diff --git a/nixos/tests/docker-edge.nix b/nixos/tests/docker-edge.nix deleted file mode 100644 index c6a1a08301890..0000000000000 --- a/nixos/tests/docker-edge.nix +++ /dev/null @@ -1,49 +0,0 @@ -# This test runs docker and checks if simple container starts - -import ./make-test-python.nix ({ pkgs, ...} : { - name = "docker"; - meta = with pkgs.lib.maintainers; { - maintainers = [ nequissimus offline ]; - }; - - nodes = { - docker = - { pkgs, ... }: - { - virtualisation.docker.enable = true; - virtualisation.docker.package = pkgs.docker-edge; - - users.users = { - noprivs = { - isNormalUser = true; - description = "Can't access the docker daemon"; - password = "foobar"; - }; - - hasprivs = { - isNormalUser = true; - description = "Can access the docker daemon"; - password = "foobar"; - extraGroups = [ "docker" ]; - }; - }; - }; - }; - - testScript = '' - start_all() - - docker.wait_for_unit("sockets.target") - docker.succeed("tar cv --files-from /dev/null | docker import - scratchimg") - docker.succeed( - "docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10" - ) - docker.succeed("docker ps | grep sleeping") - docker.succeed("sudo -u hasprivs docker ps") - docker.fail("sudo -u noprivs docker ps") - docker.succeed("docker stop sleeping") - - # Must match version 4 times to ensure client and server git commits and versions are correct - docker.succeed('[ $(docker version | grep ${pkgs.docker-edge.version} | wc -l) = "4" ]') - ''; -}) diff --git a/nixos/tests/ecryptfs.nix b/nixos/tests/ecryptfs.nix index e3cfb2ed998c2..1c67d307a00e8 100644 --- a/nixos/tests/ecryptfs.nix +++ b/nixos/tests/ecryptfs.nix @@ -11,16 +11,16 @@ import ./make-test-python.nix ({ ... }: testScript = '' def login_as_alice(): - machine.wait_until_tty_matches(1, "login: ") + machine.wait_until_tty_matches("1", "login: ") machine.send_chars("alice\n") - machine.wait_until_tty_matches(1, "Password: ") + machine.wait_until_tty_matches("1", "Password: ") machine.send_chars("foobar\n") - machine.wait_until_tty_matches(1, "alice\@machine") + machine.wait_until_tty_matches("1", "alice\@machine") def logout(): machine.send_chars("logout\n") - machine.wait_until_tty_matches(1, "login: ") + machine.wait_until_tty_matches("1", "login: ") machine.wait_for_unit("default.target") @@ -36,7 +36,7 @@ import ./make-test-python.nix ({ ... }: with subtest("Log alice in (ecryptfs passwhrase is wrapped during first login)"): login_as_alice() machine.send_chars("logout\n") - machine.wait_until_tty_matches(1, "login: ") + machine.wait_until_tty_matches("1", "login: ") # Why do I need to do this?? machine.succeed("su alice -c ecryptfs-umount-private || true") diff --git a/nixos/tests/extra-python-packages.nix b/nixos/tests/extra-python-packages.nix new file mode 100644 index 0000000000000..7a48077cf98bc --- /dev/null +++ b/nixos/tests/extra-python-packages.nix @@ -0,0 +1,13 @@ +import ./make-test-python.nix ({ ... }: + { + name = "extra-python-packages"; + + extraPythonPackages = p: [ p.numpy ]; + + nodes = { }; + + testScript = '' + import numpy as np + assert str(np.zeros(4) == "array([0., 0., 0., 0.])") + ''; + }) diff --git a/nixos/tests/firefox.nix b/nixos/tests/firefox.nix index c773368a3e60a..63ccc6efb5bb4 100644 --- a/nixos/tests/firefox.nix +++ b/nixos/tests/firefox.nix @@ -54,7 +54,7 @@ import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }: { @contextmanager - def audio_recording(machine: Machine) -> None: + def record_audio(machine: Machine): """ Perform actions while recording the machine audio output. @@ -64,7 +64,7 @@ import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }: { machine.systemctl("stop audio-recorder") - def wait_for_sound(machine: Machine) -> None: + def wait_for_sound(machine: Machine): """ Wait until any sound has been emitted. """ @@ -94,7 +94,7 @@ import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }: { machine.sleep(40) with subtest("Check whether Firefox can play sound"): - with audio_recording(machine): + with record_audio(machine): machine.succeed( "firefox file://${pkgs.sound-theme-freedesktop}/share/sounds/freedesktop/stereo/phone-incoming-call.oga >&2 &" ) diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix index 10f9cb05c9cb1..f7b9d283e4572 100644 --- a/nixos/tests/home-assistant.nix +++ b/nixos/tests/home-assistant.nix @@ -111,6 +111,7 @@ in { pattern = re.compile(r"path=(?P<path>[\/a-z0-9-.]+)\/bin\/hass") response = hass.execute("systemctl show -p ExecStart home-assistant.service")[1] match = pattern.search(response) + assert match package = match.group('path') hass.wait_for_unit("home-assistant.service") diff --git a/nixos/tests/ihatemoney/default.nix b/nixos/tests/ihatemoney/default.nix index cd5f073343daa..894a97d43d35e 100644 --- a/nixos/tests/ihatemoney/default.nix +++ b/nixos/tests/ihatemoney/default.nix @@ -32,14 +32,7 @@ let }; }; # ihatemoney needs a local smtp server otherwise project creation just crashes - services.opensmtpd = { - enable = true; - serverConfiguration = '' - listen on lo - action foo relay - match from any for any action foo - ''; - }; + services.postfix.enable = true; }; testScript = '' machine.wait_for_open_port(8000) diff --git a/nixos/tests/login.nix b/nixos/tests/login.nix index 0d6f81b172191..2cff38d20059d 100644 --- a/nixos/tests/login.nix +++ b/nixos/tests/login.nix @@ -29,11 +29,11 @@ import ./make-test-python.nix ({ pkgs, latestKernel ? false, ... }: machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'") with subtest("Log in as alice on a virtual console"): - machine.wait_until_tty_matches(2, "login: ") + machine.wait_until_tty_matches("2", "login: ") machine.send_chars("alice\n") - machine.wait_until_tty_matches(2, "login: alice") + machine.wait_until_tty_matches("2", "login: alice") machine.wait_until_succeeds("pgrep login") - machine.wait_until_tty_matches(2, "Password: ") + machine.wait_until_tty_matches("2", "Password: ") machine.send_chars("foobar\n") machine.wait_until_succeeds("pgrep -u alice bash") machine.send_chars("touch done\n") diff --git a/nixos/tests/matrix/mjolnir.nix b/nixos/tests/matrix/mjolnir.nix index cb843e2e9e3e8..3864f0ff2bb6d 100644 --- a/nixos/tests/matrix/mjolnir.nix +++ b/nixos/tests/matrix/mjolnir.nix @@ -45,6 +45,7 @@ import ../make-test-python.nix ( enable_registration = true; enable_registration_without_verification = true; registration_shared_secret = "supersecret-registration"; + enable_registration_without_verification = true; listeners = [ { # The default but tls=false diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 2cc1e9b0942ca..1fe1229f24a4a 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -77,12 +77,14 @@ let testCases = { loopback = { name = "Loopback"; - machine.networking.useDHCP = false; - machine.networking.useNetworkd = networkd; + nodes.client = { pkgs, ... }: with pkgs.lib; { + networking.useDHCP = false; + networking.useNetworkd = networkd; + }; testScript = '' start_all() - machine.wait_for_unit("network.target") - loopback_addresses = machine.succeed("ip addr show lo") + client.wait_for_unit("network.target") + loopback_addresses = client.succeed("ip addr show lo") assert "inet 127.0.0.1/8" in loopback_addresses assert "inet6 ::1/128" in loopback_addresses ''; @@ -139,6 +141,25 @@ let client.wait_until_succeeds("ping -c 1 192.168.3.1") ''; }; + routeType = { + name = "RouteType"; + nodes.client = { pkgs, ... }: with pkgs.lib; { + networking = { + useDHCP = false; + useNetworkd = networkd; + interfaces.eth1.ipv4.routes = [{ + address = "192.168.1.127"; + prefixLength = 32; + type = "local"; + }]; + }; + }; + testScript = '' + start_all() + client.wait_for_unit("network.target") + client.succeed("ip -4 route list table local | grep 'local 192.168.1.127'") + ''; + }; dhcpDefault = { name = "useDHCP-by-default"; nodes.router = router; diff --git a/nixos/tests/nitter.nix b/nixos/tests/nitter.nix index 0e1a6d150f38e..8bc55ba8c69fc 100644 --- a/nixos/tests/nitter.nix +++ b/nixos/tests/nitter.nix @@ -12,7 +12,7 @@ import ./make-test-python.nix ({ pkgs, ... }: testScript = '' machine.wait_for_unit("nitter.service") - machine.wait_for_open_port("80") + machine.wait_for_open_port(80) machine.succeed("curl --fail http://localhost:80/") ''; }) diff --git a/nixos/tests/pam/pam-oath-login.nix b/nixos/tests/pam/pam-oath-login.nix index c532e81e674d7..dd6ef4a0abcb8 100644 --- a/nixos/tests/pam/pam-oath-login.nix +++ b/nixos/tests/pam/pam-oath-login.nix @@ -77,28 +77,28 @@ in machine.screenshot("postboot") with subtest("Invalid password"): - switch_to_tty(2) - enter_user_alice(2) + switch_to_tty("2") + enter_user_alice("2") machine.send_chars("${oathSnakeOilPassword1}\n") - machine.wait_until_tty_matches(2, "Password: ") + machine.wait_until_tty_matches("2", "Password: ") machine.send_chars("blorg\n") - machine.wait_until_tty_matches(2, "Login incorrect") + machine.wait_until_tty_matches("2", "Login incorrect") with subtest("Invalid oath token"): - switch_to_tty(3) - enter_user_alice(3) + switch_to_tty("3") + enter_user_alice("3") machine.send_chars("000000\n") - machine.wait_until_tty_matches(3, "Login incorrect") - machine.wait_until_tty_matches(3, "login:") + machine.wait_until_tty_matches("3", "Login incorrect") + machine.wait_until_tty_matches("3", "login:") with subtest("Happy path: Both passwords are mandatory to get us in"): - switch_to_tty(4) - enter_user_alice(4) + switch_to_tty("4") + enter_user_alice("4") machine.send_chars("${oathSnakeOilPassword2}\n") - machine.wait_until_tty_matches(4, "Password: ") + machine.wait_until_tty_matches("4", "Password: ") machine.send_chars("${alicePassword}\n") machine.wait_until_succeeds("pgrep -u alice bash") diff --git a/nixos/tests/restic.nix b/nixos/tests/restic.nix index 16979eab82170..7523d5e5ed5da 100644 --- a/nixos/tests/restic.nix +++ b/nixos/tests/restic.nix @@ -1,96 +1,119 @@ import ./make-test-python.nix ( { pkgs, ... }: - let - password = "some_password"; - repository = "/tmp/restic-backup"; - rcloneRepository = "rclone:local:/tmp/restic-rclone-backup"; + let + password = "some_password"; + repository = "/tmp/restic-backup"; + repositoryFile = "${pkgs.writeText "repositoryFile" "/tmp/restic-backup-from-file"}"; + rcloneRepository = "rclone:local:/tmp/restic-rclone-backup"; - passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}"; - initialize = true; - paths = [ "/opt" ]; - pruneOpts = [ - "--keep-daily 2" - "--keep-weekly 1" - "--keep-monthly 1" - "--keep-yearly 99" - ]; - in - { - name = "restic"; + backupPrepareCommand = '' + touch /opt/backupPrepareCommand + test ! -e /opt/backupCleanupCommand + ''; - meta = with pkgs.lib.maintainers; { - maintainers = [ bbigras i077 ]; - }; + backupCleanupCommand = '' + rm /opt/backupPrepareCommand + touch /opt/backupCleanupCommand + ''; - nodes = { - server = - { pkgs, ... }: - { - services.restic.backups = { - remotebackup = { - inherit repository passwordFile initialize paths pruneOpts; - }; - rclonebackup = { - repository = rcloneRepository; - rcloneConfig = { - type = "local"; - one_file_system = true; - }; + passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}"; + initialize = true; + paths = [ "/opt" ]; + pruneOpts = [ + "--keep-daily 2" + "--keep-weekly 1" + "--keep-monthly 1" + "--keep-yearly 99" + ]; + in + { + name = "restic"; - # This gets overridden by rcloneConfig.type - rcloneConfigFile = pkgs.writeText "rclone.conf" '' - [local] - type=ftp - ''; - inherit passwordFile initialize paths pruneOpts; - }; - remoteprune = { - inherit repository passwordFile; - pruneOpts = [ "--keep-last 1" ]; - }; - }; + meta = with pkgs.lib.maintainers; { + maintainers = [ bbigras i077 ]; + }; - environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local"; + nodes = { + server = + { pkgs, ... }: + { + services.restic.backups = { + remotebackup = { + inherit repository passwordFile initialize paths pruneOpts backupPrepareCommand backupCleanupCommand; + }; + remotebackup-from-file = { + inherit repositoryFile passwordFile initialize paths pruneOpts; + }; + rclonebackup = { + repository = rcloneRepository; + rcloneConfig = { + type = "local"; + one_file_system = true; }; + + # This gets overridden by rcloneConfig.type + rcloneConfigFile = pkgs.writeText "rclone.conf" '' + [local] + type=ftp + ''; + inherit passwordFile initialize paths pruneOpts; + }; + remoteprune = { + inherit repository passwordFile; + pruneOpts = [ "--keep-last 1" ]; + }; + }; + + environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local"; }; + }; - testScript = '' - server.start() - server.wait_for_unit("dbus.socket") - server.fail( - "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots", - "${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots", - ) - server.succeed( - "mkdir -p /opt", - "touch /opt/some_file", - "mkdir -p /tmp/restic-rclone-backup", - "timedatectl set-time '2016-12-13 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', - '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', - "timedatectl set-time '2017-12-13 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - "timedatectl set-time '2018-12-13 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - "timedatectl set-time '2018-12-14 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - "timedatectl set-time '2018-12-15 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - "timedatectl set-time '2018-12-16 13:45'", - "systemctl start restic-backups-remotebackup.service", - "systemctl start restic-backups-rclonebackup.service", - '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', - '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', - "systemctl start restic-backups-remoteprune.service", - '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', - ) - ''; - } + testScript = '' + server.start() + server.wait_for_unit("dbus.socket") + server.fail( + "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots", + '${pkgs.restic}/bin/restic --repository-file ${repositoryFile} -p ${passwordFile} snapshots"', + "${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots", + ) + server.succeed( + "mkdir -p /opt", + "touch /opt/some_file", + "mkdir -p /tmp/restic-rclone-backup", + "timedatectl set-time '2016-12-13 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-remotebackup-from-file.service", + "systemctl start restic-backups-rclonebackup.service", + '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', + '${pkgs.restic}/bin/restic --repository-file ${repositoryFile} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', + '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', + "timedatectl set-time '2017-12-13 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-rclonebackup.service", + "timedatectl set-time '2018-12-13 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-rclonebackup.service", + "timedatectl set-time '2018-12-14 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-rclonebackup.service", + "timedatectl set-time '2018-12-15 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-rclonebackup.service", + "timedatectl set-time '2018-12-16 13:45'", + "systemctl start restic-backups-remotebackup.service", + "rm /opt/backupCleanupCommand", + "systemctl start restic-backups-rclonebackup.service", + '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', + '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"', + "systemctl start restic-backups-remoteprune.service", + '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"', + ) + ''; + } ) diff --git a/nixos/tests/shadow.nix b/nixos/tests/shadow.nix index dd2a575b1935a..50a9f71246469 100644 --- a/nixos/tests/shadow.nix +++ b/nixos/tests/shadow.nix @@ -39,9 +39,9 @@ in import ./make-test-python.nix ({ pkgs, ... }: { shadow.wait_until_succeeds("[ $(fgconsole) = 2 ]") shadow.wait_for_unit("getty@tty2.service") shadow.wait_until_succeeds("pgrep -f 'agetty.*tty2'") - shadow.wait_until_tty_matches(2, "login: ") + shadow.wait_until_tty_matches("2", "login: ") shadow.send_chars("emma\n") - shadow.wait_until_tty_matches(2, "login: emma") + shadow.wait_until_tty_matches("2", "login: emma") shadow.wait_until_succeeds("pgrep login") shadow.sleep(2) shadow.send_chars("${password1}\n") @@ -63,9 +63,9 @@ in import ./make-test-python.nix ({ pkgs, ... }: { shadow.wait_until_succeeds("[ $(fgconsole) = 3 ]") shadow.wait_for_unit("getty@tty3.service") shadow.wait_until_succeeds("pgrep -f 'agetty.*tty3'") - shadow.wait_until_tty_matches(3, "login: ") + shadow.wait_until_tty_matches("3", "login: ") shadow.send_chars("emma\n") - shadow.wait_until_tty_matches(3, "login: emma") + shadow.wait_until_tty_matches("3", "login: emma") shadow.wait_until_succeeds("pgrep login") shadow.sleep(2) shadow.send_chars("${password1}\n") @@ -81,16 +81,16 @@ in import ./make-test-python.nix ({ pkgs, ... }: { shadow.wait_until_succeeds("[ $(fgconsole) = 4 ]") shadow.wait_for_unit("getty@tty4.service") shadow.wait_until_succeeds("pgrep -f 'agetty.*tty4'") - shadow.wait_until_tty_matches(4, "login: ") + shadow.wait_until_tty_matches("4", "login: ") shadow.send_chars("emma\n") - shadow.wait_until_tty_matches(4, "login: emma") + shadow.wait_until_tty_matches("4", "login: emma") shadow.wait_until_succeeds("pgrep login") shadow.sleep(2) shadow.send_chars("${password1}\n") - shadow.wait_until_tty_matches(4, "Login incorrect") - shadow.wait_until_tty_matches(4, "login:") + shadow.wait_until_tty_matches("4", "Login incorrect") + shadow.wait_until_tty_matches("4", "login:") shadow.send_chars("emma\n") - shadow.wait_until_tty_matches(4, "login: emma") + shadow.wait_until_tty_matches("4", "login: emma") shadow.wait_until_succeeds("pgrep login") shadow.sleep(2) shadow.send_chars("${password3}\n") @@ -109,11 +109,11 @@ in import ./make-test-python.nix ({ pkgs, ... }: { shadow.wait_until_succeeds("[ $(fgconsole) = 5 ]") shadow.wait_for_unit("getty@tty5.service") shadow.wait_until_succeeds("pgrep -f 'agetty.*tty5'") - shadow.wait_until_tty_matches(5, "login: ") + shadow.wait_until_tty_matches("5", "login: ") shadow.send_chars("layla\n") - shadow.wait_until_tty_matches(5, "login: layla") + shadow.wait_until_tty_matches("5", "login: layla") shadow.wait_until_succeeds("pgrep login") shadow.send_chars("${password2}\n") - shadow.wait_until_tty_matches(5, "login:") + shadow.wait_until_tty_matches("5", "login:") ''; }) diff --git a/nixos/tests/sway.nix b/nixos/tests/sway.nix index 8f95f2a030d1b..52e2c7c99ec4b 100644 --- a/nixos/tests/sway.nix +++ b/nixos/tests/sway.nix @@ -4,6 +4,12 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { maintainers = with lib.maintainers; [ primeos synthetica ]; }; + # testScriptWithTypes:49: error: Cannot call function of unknown type + # (machine.succeed if succeed else machine.execute)( + # ^ + # Found 1 error in 1 file (checked 1 source file) + skipTypeCheck = true; + nodes.machine = { config, ... }: { # Automatically login on tty1 as a normal user: imports = [ ./common/user-account.nix ]; diff --git a/nixos/tests/uptermd.nix b/nixos/tests/uptermd.nix index d504ef0641916..429e3c9dd5ff3 100644 --- a/nixos/tests/uptermd.nix +++ b/nixos/tests/uptermd.nix @@ -42,7 +42,7 @@ in client1.wait_for_unit("multi-user.target") client1.wait_until_succeeds("pgrep -f 'agetty.*tty1'") - client1.wait_until_tty_matches(1, "login: ") + client1.wait_until_tty_matches("1", "login: ") client1.send_chars("root\n") client1.wait_until_succeeds("pgrep -u root bash") diff --git a/nixos/tests/user-activation-scripts.nix b/nixos/tests/user-activation-scripts.nix index 9345735781873..5df072ce0508a 100644 --- a/nixos/tests/user-activation-scripts.nix +++ b/nixos/tests/user-activation-scripts.nix @@ -19,9 +19,9 @@ import ./make-test-python.nix ({ lib, ... }: { machine.wait_for_unit("multi-user.target") machine.wait_for_unit("getty@tty1.service") - machine.wait_until_tty_matches(1, "login: ") + machine.wait_until_tty_matches("1", "login: ") machine.send_chars("alice\n") - machine.wait_until_tty_matches(1, "Password: ") + machine.wait_until_tty_matches("1", "Password: ") machine.send_chars("pass1\n") machine.send_chars("touch login-ok\n") machine.wait_for_file("/home/alice/login-ok") diff --git a/nixos/tests/user-home-mode.nix b/nixos/tests/user-home-mode.nix index 1366d102a99b3..070cb0b75cc9d 100644 --- a/nixos/tests/user-home-mode.nix +++ b/nixos/tests/user-home-mode.nix @@ -17,9 +17,9 @@ import ./make-test-python.nix ({ lib, ... }: { testScript = '' machine.wait_for_unit("multi-user.target") machine.wait_for_unit("getty@tty1.service") - machine.wait_until_tty_matches(1, "login: ") + machine.wait_until_tty_matches("1", "login: ") machine.send_chars("alice\n") - machine.wait_until_tty_matches(1, "Password: ") + machine.wait_until_tty_matches("1", "Password: ") machine.send_chars("pass1\n") machine.succeed('[ "$(stat -c %a /home/alice)" == "700" ]') machine.succeed('[ "$(stat -c %a /home/bob)" == "750" ]') diff --git a/nixos/tests/web-apps/peertube.nix b/nixos/tests/web-apps/peertube.nix index d42b4e3d677bb..ecc45bff2e2ca 100644 --- a/nixos/tests/web-apps/peertube.nix +++ b/nixos/tests/web-apps/peertube.nix @@ -11,7 +11,7 @@ import ../make-test-python.nix ({pkgs, ...}: { address = "192.168.2.10"; prefixLength = 24; } ]; }; - firewall.allowedTCPPorts = [ 5432 6379 ]; + firewall.allowedTCPPorts = [ 5432 31638 ]; }; services.postgresql = { @@ -34,7 +34,7 @@ import ../make-test-python.nix ({pkgs, ...}: enable = true; bind = "0.0.0.0"; requirePass = "turrQfaQwnanGbcsdhxy"; - port = 6379; + port = 31638; }; }; @@ -76,6 +76,7 @@ import ../make-test-python.nix ({pkgs, ...}: redis = { host = "192.168.2.10"; + port = 31638; passwordFile = "/etc/peertube/password-redis-db"; }; @@ -113,7 +114,7 @@ import ../make-test-python.nix ({pkgs, ...}: database.wait_for_unit("redis-peertube.service") database.wait_for_open_port(5432) - database.wait_for_open_port(6379) + database.wait_for_open_port(31638) server.wait_for_unit("peertube.service") server.wait_for_open_port(9000) diff --git a/nixos/tests/zsh-history.nix b/nixos/tests/zsh-history.nix index 355687798406b..64f32a07e2158 100644 --- a/nixos/tests/zsh-history.nix +++ b/nixos/tests/zsh-history.nix @@ -21,13 +21,13 @@ import ./make-test-python.nix ({ pkgs, ...} : { default.wait_until_succeeds("pgrep -f 'agetty.*tty1'") # Login - default.wait_until_tty_matches(1, "login: ") + default.wait_until_tty_matches("1", "login: ") default.send_chars("root\n") - default.wait_until_tty_matches(1, r"\nroot@default\b") + default.wait_until_tty_matches("1", r"\nroot@default\b") # Generate some history default.send_chars("echo foobar\n") - default.wait_until_tty_matches(1, "foobar") + default.wait_until_tty_matches("1", "foobar") # Ensure that command was recorded in history default.succeed("/run/current-system/sw/bin/history list | grep -q foobar") |