Unverified Commit db0f76e8 authored by Guillaume Girol's avatar Guillaume Girol Committed by GitHub
Browse files

Merge pull request #271030 from symphorien/nixseparatedebuginfod

nixseparatedebuginfod: init at 0.3.0, plus module and nixos test
parents 883d1360 dece7254
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -497,6 +497,7 @@
  ./services/development/jupyterhub/default.nix
  ./services/development/livebook.nix
  ./services/development/lorri.nix
  ./services/development/nixseparatedebuginfod.nix
  ./services/development/rstudio-server/default.nix
  ./services/development/zammad.nix
  ./services/display-managers/greetd.nix
+105 −0
Original line number Diff line number Diff line
{ pkgs, lib, config, ... }:
let
  cfg = config.services.nixseparatedebuginfod;
  url = "127.0.0.1:${toString cfg.port}";
in
{
  options = {
    services.nixseparatedebuginfod = {
      enable = lib.mkEnableOption "separatedebuginfod, a debuginfod server providing source and debuginfo for nix packages";
      port = lib.mkOption {
        description = "port to listen";
        default = 1949;
        type = lib.types.port;
      };
      nixPackage = lib.mkOption {
        type = lib.types.package;
        default = pkgs.nix;
        defaultText = lib.literalExpression "pkgs.nix";
        description = ''
          The version of nix that nixseparatedebuginfod should use as client for the nix daemon. It is strongly advised to use nix version >= 2.18, otherwise some debug info may go missing.
        '';
      };
      allowOldNix = lib.mkOption {
        type = lib.types.bool;
        default = false;
        description = ''
          Do not fail evaluation when {option}`services.nixseparatedebuginfod.nixPackage` is older than nix 2.18.
        '';
      };
    };
  };
  config = lib.mkIf cfg.enable {
    assertions = [ {
      assertion = cfg.allowOldNix || (lib.versionAtLeast cfg.nixPackage.version "2.18");
      message = "nixseparatedebuginfod works better when `services.nixseparatedebuginfod.nixPackage` is set to nix >= 2.18 (instead of ${cfg.nixPackage.name}). Set `services.nixseparatedebuginfod.allowOldNix` to bypass.";
    } ];

    systemd.services.nixseparatedebuginfod = {
      wantedBy = [ "multi-user.target" ];
      wants = [ "nix-daemon.service" ];
      after = [ "nix-daemon.service" ];
      path = [ cfg.nixPackage ];
      serviceConfig = {
        ExecStart = [ "${pkgs.nixseparatedebuginfod}/bin/nixseparatedebuginfod -l ${url}" ];
        Restart = "on-failure";
        CacheDirectory = "nixseparatedebuginfod";
        # nix does not like DynamicUsers in allowed-users
        User = "nixseparatedebuginfod";
        Group = "nixseparatedebuginfod";

        # hardening
        # Filesystem stuff
        ProtectSystem = "strict"; # Prevent writing to most of /
        ProtectHome = true; # Prevent accessing /home and /root
        PrivateTmp = true; # Give an own directory under /tmp
        PrivateDevices = true; # Deny access to most of /dev
        ProtectKernelTunables = true; # Protect some parts of /sys
        ProtectControlGroups = true; # Remount cgroups read-only
        RestrictSUIDSGID = true; # Prevent creating SETUID/SETGID files
        PrivateMounts = true; # Give an own mount namespace
        RemoveIPC = true;
        UMask = "0077";

        # Capabilities
        CapabilityBoundingSet = ""; # Allow no capabilities at all
        NoNewPrivileges = true; # Disallow getting more capabilities. This is also implied by other options.

        # Kernel stuff
        ProtectKernelModules = true; # Prevent loading of kernel modules
        SystemCallArchitectures = "native"; # Usually no need to disable this
        ProtectKernelLogs = true; # Prevent access to kernel logs
        ProtectClock = true; # Prevent setting the RTC

        # Networking
        RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";

        # Misc
        LockPersonality = true; # Prevent change of the personality
        ProtectHostname = true; # Give an own UTS namespace
        RestrictRealtime = true; # Prevent switching to RT scheduling
        MemoryDenyWriteExecute = true; # Maybe disable this for interpreters like python
        RestrictNamespaces = true;
      };
    };

    users.users.nixseparatedebuginfod = {
      isSystemUser = true;
      group = "nixseparatedebuginfod";
    };

    users.groups.nixseparatedebuginfod = { };

    nix.settings.extra-allowed-users = [ "nixseparatedebuginfod" ];

    environment.variables.DEBUGINFOD_URLS = "http://${url}";

    environment.systemPackages = [
      # valgrind support requires debuginfod-find on PATH
      (lib.getBin pkgs.elfutils)
    ];

    environment.etc."gdb/gdbinit.d/nixseparatedebuginfod.gdb".text = "set debuginfod enabled on";

  };
}
+1 −0
Original line number Diff line number Diff line
@@ -605,6 +605,7 @@ in {
  nixos-rebuild-install-bootloader = handleTestOn ["x86_64-linux"] ./nixos-rebuild-install-bootloader.nix {};
  nixos-rebuild-specialisations = handleTestOn ["x86_64-linux"] ./nixos-rebuild-specialisations.nix {};
  nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; };
  nixseparatedebuginfod = handleTest ./nixseparatedebuginfod.nix {};
  node-red = handleTest ./node-red.nix {};
  nomad = handleTest ./nomad.nix {};
  non-default-filesystems = handleTest ./non-default-filesystems.nix {};
+80 −0
Original line number Diff line number Diff line
import ./make-test-python.nix ({ pkgs, lib, ... }:
let
  secret-key = "key-name:/COlMSRbehSh6YSruJWjL+R0JXQUKuPEn96fIb+pLokEJUjcK/2Gv8Ai96D7JGay5gDeUTx5wdpPgNvum9YtwA==";
  public-key = "key-name:BCVI3Cv9hr/AIveg+yRmsuYA3lE8ecHaT4Db7pvWLcA=";
in
{
  name = "nixseparatedebuginfod";
  /* A binary cache with debug info and source for nix */
  nodes.cache = { pkgs, ... }: {
    services.nix-serve = {
      enable = true;
      secretKeyFile = builtins.toFile "secret-key" secret-key;
      openFirewall = true;
    };
    system.extraDependencies = [
      pkgs.nix.debug
      pkgs.nix.src
      pkgs.sl
    ];
  };
  /* the machine where we need the debuginfo */
  nodes.machine = {
    imports = [
      ../modules/installer/cd-dvd/channel.nix
    ];
    services.nixseparatedebuginfod.enable = true;
    nix.settings = {
      substituters = lib.mkForce [ "http://cache:5000" ];
      trusted-public-keys = [ public-key ];
    };
    environment.systemPackages = [
      pkgs.valgrind
      pkgs.gdb
      (pkgs.writeShellScriptBin "wait_for_indexation" ''
        set -x
        while debuginfod-find debuginfo /run/current-system/sw/bin/nix |& grep 'File too large'; do
          sleep 1;
        done
      '')
    ];
  };
  testScript = ''
    start_all()
    cache.wait_for_unit("nix-serve.service")
    cache.wait_for_open_port(5000)
    machine.wait_for_unit("nixseparatedebuginfod.service")
    machine.wait_for_open_port(1949)

    with subtest("show the config to debug the test"):
      machine.succeed("nix --extra-experimental-features nix-command show-config |& logger")
      machine.succeed("cat /etc/nix/nix.conf |& logger")
    with subtest("check that the binary cache works"):
      machine.succeed("nix-store -r ${pkgs.sl}")

    # nixseparatedebuginfod needs .drv to associate executable -> source
    # on regular systems this would be provided by nixos-rebuild
    machine.succeed("nix-instantiate '<nixpkgs>' -A nix")

    machine.succeed("timeout 600 wait_for_indexation")

    # test debuginfod-find
    machine.succeed("debuginfod-find debuginfo /run/current-system/sw/bin/nix")

    # test that gdb can fetch source
    out = machine.succeed("gdb /run/current-system/sw/bin/nix --batch -x ${builtins.toFile "commands" ''
    start
    l
    ''}")
    print(out)
    assert 'int main(' in out

    # test that valgrind can display location information
    # this relies on the fact that valgrind complains about nix
    # libgc helps in this regard, and we also ask valgrind to show leak kinds
    # which are usually false positives.
    out = machine.succeed("valgrind --leak-check=full --show-leak-kinds=all nix-env --version 2>&1")
    print(out)
    assert 'main.cc' in out
  '';
})
+49 −0
Original line number Diff line number Diff line
{ lib
, fetchFromGitHub
, rustPlatform
, libarchive
, openssl
, sqlite
, pkg-config
, nixosTests
}:

rustPlatform.buildRustPackage rec {
  pname = "nixseparatedebuginfod";
  version = "0.3.2";

  src = fetchFromGitHub {
    owner = "symphorien";
    repo = "nixseparatedebuginfod";
    rev = "v${version}";
    hash = "sha256-XSEHNoc3h21foVeR28KgfiBTRHyUh+GJ52LMD2xFHfA=";
  };

  cargoHash = "sha256-t6W6siHuga/T9kmanA735zH2i9eCOT7vD6v7E5LIp9k=";

  # tests need a working nix install with access to the internet
  doCheck = false;

  buildInputs = [
    libarchive
    openssl
    sqlite
  ];

  nativeBuildInputs = [ pkg-config ];

  passthru = {
    tests = {
      inherit (nixosTests) nixseparatedebuginfod;
    };
  };

  meta = with lib; {
    description = "Downloads and provides debug symbols and source code for nix derivations to gdb and other debuginfod-capable debuggers as needed";
    homepage = "https://github.com/symphorien/nixseparatedebuginfod";
    license = licenses.gpl3Only;
    maintainers = [ maintainers.symphorien ];
    platforms = platforms.linux;
    mainProgram = "nixseparatedebuginfod";
  };
}