Unverified Commit ffb0ba30 authored by K900's avatar K900 Committed by GitHub
Browse files

staging-nixos merge for 2026-03-08 (#497850)

parents f645ed53 f16227fa
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -23969,6 +23969,12 @@
    githubId = 15986681;
    name = "Simon Bruder";
  };
  scandiravian = {
    email = "nixos@scandiravian.com";
    github = "scandiravian";
    githubId = 13556969;
    name = "Scandiravian";
  };
  scd31 = {
    name = "scd31";
    github = "scd31";
+2 −0
Original line number Diff line number Diff line
@@ -249,6 +249,8 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
  `component.settings`. The unix module now supports using SSH keys from Kanidm via
  `services.kanidm.unix.sshIntegration = true`.

- `mdbook-linkcheck` has been removed as it is unmaintained and incompatible with the latest version of `mdbook`. Users can instead migrate to `mdbook-linkcheck2`.

- `glibc` has been updated to version 2.42.

  This version no longer makes the stack executable when a shared library requires this. A symptom
+3 −0
Original line number Diff line number Diff line
@@ -1130,6 +1130,9 @@ in
  nixos-rebuild-target-host = runTest {
    imports = [ ./nixos-rebuild-target-host.nix ];
  };
  nixos-rebuild-target-host-interrupted = runTest {
    imports = [ ./nixos-rebuild-target-host-interrupted.nix ];
  };
  nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; };
  nixpkgs-config-allow-unfree =
    pkgs.callPackage ../modules/misc/nixpkgs/test-nixpkgs-config-allow-unfree.nix
+237 −0
Original line number Diff line number Diff line
{ hostPkgs, ... }:

# This test recreates a remote deployment scenario where the connection
# between deployer and target is closed during the deployment - in this
# case because the connection goes over a 'reverse ssh' tunnel service
# that has changes that are being deployed.

# This is not seamless (the deployer doesn't get to see the logs after
# the disconnect), but is a lot better than the old behaviour, where
# the switch was aborted and the connection never restored.

{
  name = "nixos-rebuild-target-host-interrupted";

  # TODO: remove overlay from  nixos/modules/profiles/installation-device.nix
  #        make it a _small package instead, then remove pkgsReadOnly = false;.
  node.pkgsReadOnly = false;

  nodes = {
    deployer =
      {
        nodes,
        lib,
        pkgs,
        ...
      }:
      let
        inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
      in
      {
        imports = [
          ../modules/profiles/installation-device.nix
        ];

        nix.settings = {
          substituters = lib.mkForce [ ];
          hashed-mirrors = null;
          connect-timeout = 1;
        };

        system.includeBuildDependencies = true;

        virtualisation = {
          cores = 2;
          memorySize = 3072;
        };

        services.openssh.enable = true;
        users.users.root.openssh.authorizedKeys.keys = [ nodes.target.system.build.publicKey ];
        system.extraDependencies = [
          # so that it doesn't need to be built inside the test
          pkgs.nixVersions.latest
        ];

        system.build.privateKey = snakeOilPrivateKey;
        system.build.publicKey = snakeOilPublicKey;
        system.switch.enable = true;

        services.getty.autologinUser = lib.mkForce "root";
      };

    target =
      {
        nodes,
        lib,
        pkgs,
        ...
      }:
      let
        inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
        targetConfig = {
          documentation.enable = false;
          services.openssh.enable = true;
          system.build.privateKey = snakeOilPrivateKey;
          system.build.publicKey = snakeOilPublicKey;

          users.users.root.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ];
          users.users.alice.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ];
          users.users.bob.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ];

          users.users.alice.extraGroups = [ "wheel" ];
          users.users.bob.extraGroups = [ "wheel" ];

          # Disable sudo for root to ensure sudo isn't called without `--sudo`
          security.sudo.extraRules = lib.mkForce [
            {
              groups = [ "wheel" ];
              commands = [ { command = "ALL"; } ];
            }
            {
              users = [ "alice" ];
              commands = [
                {
                  command = "ALL";
                  options = [ "NOPASSWD" ];
                }
              ];
            }
          ];

          nix.settings.trusted-users = [ "@wheel" ];

          systemd.services."autossh-ng" = {
            after = [ "network.target" ];
            wantedBy = [ "multi-user.target" ];
            serviceConfig = {
              User = "root";
              Restart = "always";
              RestartSec = "10s";
              ExecStart = "${pkgs.openssh}/bin/ssh -o \"ServerAliveInterval 30\" -o \"ServerAliveCountMax 3\" -o ExitOnForwardFailure=yes -N -R2222:localhost:22 deployer";
            };
          };

        };
      in
      {
        imports = [ ./common/user-account.nix ];

        config = lib.mkMerge [
          targetConfig
          {
            system.build = {
              inherit targetConfig;
            };
            system.switch.enable = true;

            networking.hostName = "target";
          }
        ];
      };
  };

  testScript =
    { nodes, ... }:
    let
      sshConfig = builtins.toFile "ssh.conf" ''
        UserKnownHostsFile=/dev/null
        StrictHostKeyChecking=no
      '';

      targetConfigJSON = hostPkgs.writeText "target-configuration.json" (
        builtins.toJSON nodes.target.system.build.targetConfig
      );

      targetNetworkJSON = hostPkgs.writeText "target-network.json" (
        builtins.toJSON nodes.target.system.build.networkConfig
      );

      configFile =
        hostname:
        hostPkgs.writeText "configuration.nix" # nix
          ''
            { lib, pkgs, modulesPath, ... }: {
              imports = [
                (modulesPath + "/virtualisation/qemu-vm.nix")
                (modulesPath + "/testing/test-instrumentation.nix")
                (modulesPath + "/../tests/common/user-account.nix")
                (lib.modules.importJSON ./target-configuration.json)
                (lib.modules.importJSON ./target-network.json)
                ./hardware-configuration.nix
              ];

              boot.loader.grub = {
                enable = true;
                device = "/dev/vda";
                forceInstall = true;
              };

              # needed to make NIX_SSHOPTS work for nix-copy-closure
              nix.package = pkgs.nixVersions.latest;

              # We're changing the '-E' parameter to the new hostname here,
              # not because we care about the logs, but because we want to
              # force the scenario where the connection is broken during the
              # deployment (because the autossh-ng service is stopped and
              # started):
              systemd.services."autossh-ng".serviceConfig.ExecStart =
                lib.mkForce "''${pkgs.openssh}/bin/ssh -o \"ServerAliveInterval 30\" -o \"ServerAliveCountMax 3\" -o ExitOnForwardFailure=yes -N -R2222:localhost:22 -E ${hostname} deployer";

              # this will be asserted to validate the switch happened:
              networking.hostName = "${hostname}";
            }
          '';
    in
    # python
    ''
      start_all()
      target.wait_for_open_port(22)

      deployer.wait_until_succeeds("ping -c1 target")
      deployer.succeed("install -Dm 600 ${nodes.deployer.system.build.privateKey} ~root/.ssh/id_ecdsa")
      deployer.succeed("install ${sshConfig} ~root/.ssh/config")

      target.succeed("nixos-generate-config")
      target.succeed("install -Dm 600 ${nodes.target.system.build.privateKey} ~root/.ssh/id_ecdsa")
      target.succeed("install ${sshConfig} ~root/.ssh/config")
      deployer.succeed("scp alice@target:/etc/nixos/hardware-configuration.nix /root/hardware-configuration.nix")
      target.wait_for_unit("autossh-ng.service")

      deployer.copy_from_host("${configFile "config-1-deployed"}", "/root/configuration-1.nix")
      deployer.copy_from_host("${configFile "config-2-deployed"}", "/root/configuration-2.nix")
      deployer.copy_from_host("${targetNetworkJSON}", "/root/target-network.json")
      deployer.copy_from_host("${targetConfigJSON}", "/root/target-configuration.json")

      with subtest("Deploy to alice@target via reverse ssh"):
        deployer.wait_for_unit("multi-user.target")
        # Uses TTY/send_chars instead of deployer.succeed to set NIX_SSHOPTS
        deployer.send_chars("NIX_SSHOPTS=\"-p 2222\" nixos-rebuild switch -I nixos-config=/root/configuration-1.nix --target-host alice@localhost --sudo\n")

        # the connection breaks, but the 'switch' should now continue in the background:
        deployer.wait_until_tty_matches("1", "error: while running command with remote sudo")

        def deployed(last_try: bool) -> bool:
            target_hostname = deployer.succeed("ssh alice@target cat /etc/hostname", timeout=20).rstrip()
            if last_try:
                print(f"Still seeing hostname {target_hostname}")
            return target_hostname == "config-1-deployed"
        retry(deployed)

      with subtest("Deploy to bob@target via reverse ssh with password-based sudo"):
        deployer.wait_for_unit("multi-user.target")
        # Uses TTY/send_chars instead of deployer.succeed to set NIX_SSHOPTS and for ask-sudo-password
        deployer.send_chars("NIX_SSHOPTS=\"-p 2222\" nixos-rebuild switch -I nixos-config=/root/configuration-2.nix --target-host bob@localhost --ask-sudo-password\n")
        deployer.wait_until_tty_matches("1", "password for bob")
        deployer.send_chars("${nodes.target.users.users.bob.password}\n")

        # the connection breaks, but the 'switch' should now continue in the background:
        deployer.wait_until_tty_matches("1", "error: while running command with remote sudo")

        def deployed(last_try: bool) -> bool:
            target_hostname = deployer.succeed("ssh alice@target cat /etc/hostname", timeout=20).rstrip()
            if last_try:
                print(f"Still seeing hostname {target_hostname}")
            return target_hostname == "config-2-deployed"
        retry(deployed)
    '';
}
+34 −0
Original line number Diff line number Diff line
{
  lib,
  stdenv,
  fetchFromGitHub,
  rustPlatform,
  pkg-config,
  openssl,
  testers,
  mdbook-linkcheck,
  mdbook-linkcheck2,
}:

rustPlatform.buildRustPackage (finalAttrs: {
  pname = "mdbook-linkcheck";
  version = "0.7.7";
  pname = "mdbook-linkcheck2";
  version = "0.12.0";

  src = fetchFromGitHub {
    owner = "Michael-F-Bryan";
    repo = "mdbook-linkcheck";
    rev = "v${finalAttrs.version}";
    sha256 = "sha256-ZbraChBHuKAcUA62EVHZ1RygIotNEEGv24nhSPAEj00=";
    owner = "marxin";
    repo = "mdbook-linkcheck2";
    tag = "v${finalAttrs.version}";
    sha256 = "sha256-SvheBEIWiL1zdYeMQalbBeAQC86DycqV1/PTA+0S7Gg=";
  };

  cargoHash = "sha256-Tt7ljjWv2CMtP/ELZNgSH/ifmBk/42+E0r9ZXQEJNP8=";

  buildInputs = lib.optionals (!stdenv.hostPlatform.isDarwin) [ openssl ];

  nativeBuildInputs = lib.optionals (!stdenv.hostPlatform.isDarwin) [ pkg-config ];

  env.OPENSSL_NO_VENDOR = 1;
  cargoHash = "sha256-s4nvVHl/bViIxZfqc4SxSnCCYIY/hxy0C7f2/9ztqts=";

  doCheck = false; # tries to access network to test broken web link functionality

  passthru.tests.version = testers.testVersion { package = mdbook-linkcheck; };
  passthru.tests.version = testers.testVersion { package = mdbook-linkcheck2; };

  meta = {
    description = "Backend for `mdbook` which will check your links for you";
    mainProgram = "mdbook-linkcheck";
    homepage = "https://github.com/Michael-F-Bryan/mdbook-linkcheck";
    description = "Backend for mdbook which will check your links for you";
    mainProgram = "mdbook-linkcheck2";
    homepage = "https://github.com/marxin/mdbook-linkcheck2";
    license = lib.licenses.mit;
    maintainers = with lib.maintainers; [
      zhaofengli
      matthiasbeyer
      scandiravian
    ];
  };
})
Loading