Merge pull request #271030 from symphorien/nixseparatedebuginfod

nixseparatedebuginfod: init at 0.3.0, plus module and nixos test

authored by Guillaume Girol and committed by GitHub db0f76e8 883d1360

+236
+1
nixos/modules/module-list.nix
··· 497 497 ./services/development/jupyterhub/default.nix 498 498 ./services/development/livebook.nix 499 499 ./services/development/lorri.nix 500 + ./services/development/nixseparatedebuginfod.nix 500 501 ./services/development/rstudio-server/default.nix 501 502 ./services/development/zammad.nix 502 503 ./services/display-managers/greetd.nix
+105
nixos/modules/services/development/nixseparatedebuginfod.nix
··· 1 + { pkgs, lib, config, ... }: 2 + let 3 + cfg = config.services.nixseparatedebuginfod; 4 + url = "127.0.0.1:${toString cfg.port}"; 5 + in 6 + { 7 + options = { 8 + services.nixseparatedebuginfod = { 9 + enable = lib.mkEnableOption "separatedebuginfod, a debuginfod server providing source and debuginfo for nix packages"; 10 + port = lib.mkOption { 11 + description = "port to listen"; 12 + default = 1949; 13 + type = lib.types.port; 14 + }; 15 + nixPackage = lib.mkOption { 16 + type = lib.types.package; 17 + default = pkgs.nix; 18 + defaultText = lib.literalExpression "pkgs.nix"; 19 + description = '' 20 + 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. 21 + ''; 22 + }; 23 + allowOldNix = lib.mkOption { 24 + type = lib.types.bool; 25 + default = false; 26 + description = '' 27 + Do not fail evaluation when {option}`services.nixseparatedebuginfod.nixPackage` is older than nix 2.18. 28 + ''; 29 + }; 30 + }; 31 + }; 32 + config = lib.mkIf cfg.enable { 33 + assertions = [ { 34 + assertion = cfg.allowOldNix || (lib.versionAtLeast cfg.nixPackage.version "2.18"); 35 + 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."; 36 + } ]; 37 + 38 + systemd.services.nixseparatedebuginfod = { 39 + wantedBy = [ "multi-user.target" ]; 40 + wants = [ "nix-daemon.service" ]; 41 + after = [ "nix-daemon.service" ]; 42 + path = [ cfg.nixPackage ]; 43 + serviceConfig = { 44 + ExecStart = [ "${pkgs.nixseparatedebuginfod}/bin/nixseparatedebuginfod -l ${url}" ]; 45 + Restart = "on-failure"; 46 + CacheDirectory = "nixseparatedebuginfod"; 47 + # nix does not like DynamicUsers in allowed-users 48 + User = "nixseparatedebuginfod"; 49 + Group = "nixseparatedebuginfod"; 50 + 51 + # hardening 52 + # Filesystem stuff 53 + ProtectSystem = "strict"; # Prevent writing to most of / 54 + ProtectHome = true; # Prevent accessing /home and /root 55 + PrivateTmp = true; # Give an own directory under /tmp 56 + PrivateDevices = true; # Deny access to most of /dev 57 + ProtectKernelTunables = true; # Protect some parts of /sys 58 + ProtectControlGroups = true; # Remount cgroups read-only 59 + RestrictSUIDSGID = true; # Prevent creating SETUID/SETGID files 60 + PrivateMounts = true; # Give an own mount namespace 61 + RemoveIPC = true; 62 + UMask = "0077"; 63 + 64 + # Capabilities 65 + CapabilityBoundingSet = ""; # Allow no capabilities at all 66 + NoNewPrivileges = true; # Disallow getting more capabilities. This is also implied by other options. 67 + 68 + # Kernel stuff 69 + ProtectKernelModules = true; # Prevent loading of kernel modules 70 + SystemCallArchitectures = "native"; # Usually no need to disable this 71 + ProtectKernelLogs = true; # Prevent access to kernel logs 72 + ProtectClock = true; # Prevent setting the RTC 73 + 74 + # Networking 75 + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; 76 + 77 + # Misc 78 + LockPersonality = true; # Prevent change of the personality 79 + ProtectHostname = true; # Give an own UTS namespace 80 + RestrictRealtime = true; # Prevent switching to RT scheduling 81 + MemoryDenyWriteExecute = true; # Maybe disable this for interpreters like python 82 + RestrictNamespaces = true; 83 + }; 84 + }; 85 + 86 + users.users.nixseparatedebuginfod = { 87 + isSystemUser = true; 88 + group = "nixseparatedebuginfod"; 89 + }; 90 + 91 + users.groups.nixseparatedebuginfod = { }; 92 + 93 + nix.settings.extra-allowed-users = [ "nixseparatedebuginfod" ]; 94 + 95 + environment.variables.DEBUGINFOD_URLS = "http://${url}"; 96 + 97 + environment.systemPackages = [ 98 + # valgrind support requires debuginfod-find on PATH 99 + (lib.getBin pkgs.elfutils) 100 + ]; 101 + 102 + environment.etc."gdb/gdbinit.d/nixseparatedebuginfod.gdb".text = "set debuginfod enabled on"; 103 + 104 + }; 105 + }
+1
nixos/tests/all-tests.nix
··· 605 605 nixos-rebuild-install-bootloader = handleTestOn ["x86_64-linux"] ./nixos-rebuild-install-bootloader.nix {}; 606 606 nixos-rebuild-specialisations = handleTestOn ["x86_64-linux"] ./nixos-rebuild-specialisations.nix {}; 607 607 nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; }; 608 + nixseparatedebuginfod = handleTest ./nixseparatedebuginfod.nix {}; 608 609 node-red = handleTest ./node-red.nix {}; 609 610 nomad = handleTest ./nomad.nix {}; 610 611 non-default-filesystems = handleTest ./non-default-filesystems.nix {};
+80
nixos/tests/nixseparatedebuginfod.nix
··· 1 + import ./make-test-python.nix ({ pkgs, lib, ... }: 2 + let 3 + secret-key = "key-name:/COlMSRbehSh6YSruJWjL+R0JXQUKuPEn96fIb+pLokEJUjcK/2Gv8Ai96D7JGay5gDeUTx5wdpPgNvum9YtwA=="; 4 + public-key = "key-name:BCVI3Cv9hr/AIveg+yRmsuYA3lE8ecHaT4Db7pvWLcA="; 5 + in 6 + { 7 + name = "nixseparatedebuginfod"; 8 + /* A binary cache with debug info and source for nix */ 9 + nodes.cache = { pkgs, ... }: { 10 + services.nix-serve = { 11 + enable = true; 12 + secretKeyFile = builtins.toFile "secret-key" secret-key; 13 + openFirewall = true; 14 + }; 15 + system.extraDependencies = [ 16 + pkgs.nix.debug 17 + pkgs.nix.src 18 + pkgs.sl 19 + ]; 20 + }; 21 + /* the machine where we need the debuginfo */ 22 + nodes.machine = { 23 + imports = [ 24 + ../modules/installer/cd-dvd/channel.nix 25 + ]; 26 + services.nixseparatedebuginfod.enable = true; 27 + nix.settings = { 28 + substituters = lib.mkForce [ "http://cache:5000" ]; 29 + trusted-public-keys = [ public-key ]; 30 + }; 31 + environment.systemPackages = [ 32 + pkgs.valgrind 33 + pkgs.gdb 34 + (pkgs.writeShellScriptBin "wait_for_indexation" '' 35 + set -x 36 + while debuginfod-find debuginfo /run/current-system/sw/bin/nix |& grep 'File too large'; do 37 + sleep 1; 38 + done 39 + '') 40 + ]; 41 + }; 42 + testScript = '' 43 + start_all() 44 + cache.wait_for_unit("nix-serve.service") 45 + cache.wait_for_open_port(5000) 46 + machine.wait_for_unit("nixseparatedebuginfod.service") 47 + machine.wait_for_open_port(1949) 48 + 49 + with subtest("show the config to debug the test"): 50 + machine.succeed("nix --extra-experimental-features nix-command show-config |& logger") 51 + machine.succeed("cat /etc/nix/nix.conf |& logger") 52 + with subtest("check that the binary cache works"): 53 + machine.succeed("nix-store -r ${pkgs.sl}") 54 + 55 + # nixseparatedebuginfod needs .drv to associate executable -> source 56 + # on regular systems this would be provided by nixos-rebuild 57 + machine.succeed("nix-instantiate '<nixpkgs>' -A nix") 58 + 59 + machine.succeed("timeout 600 wait_for_indexation") 60 + 61 + # test debuginfod-find 62 + machine.succeed("debuginfod-find debuginfo /run/current-system/sw/bin/nix") 63 + 64 + # test that gdb can fetch source 65 + out = machine.succeed("gdb /run/current-system/sw/bin/nix --batch -x ${builtins.toFile "commands" '' 66 + start 67 + l 68 + ''}") 69 + print(out) 70 + assert 'int main(' in out 71 + 72 + # test that valgrind can display location information 73 + # this relies on the fact that valgrind complains about nix 74 + # libgc helps in this regard, and we also ask valgrind to show leak kinds 75 + # which are usually false positives. 76 + out = machine.succeed("valgrind --leak-check=full --show-leak-kinds=all nix-env --version 2>&1") 77 + print(out) 78 + assert 'main.cc' in out 79 + ''; 80 + })
+49
pkgs/by-name/ni/nixseparatedebuginfod/package.nix
··· 1 + { lib 2 + , fetchFromGitHub 3 + , rustPlatform 4 + , libarchive 5 + , openssl 6 + , sqlite 7 + , pkg-config 8 + , nixosTests 9 + }: 10 + 11 + rustPlatform.buildRustPackage rec { 12 + pname = "nixseparatedebuginfod"; 13 + version = "0.3.2"; 14 + 15 + src = fetchFromGitHub { 16 + owner = "symphorien"; 17 + repo = "nixseparatedebuginfod"; 18 + rev = "v${version}"; 19 + hash = "sha256-XSEHNoc3h21foVeR28KgfiBTRHyUh+GJ52LMD2xFHfA="; 20 + }; 21 + 22 + cargoHash = "sha256-t6W6siHuga/T9kmanA735zH2i9eCOT7vD6v7E5LIp9k="; 23 + 24 + # tests need a working nix install with access to the internet 25 + doCheck = false; 26 + 27 + buildInputs = [ 28 + libarchive 29 + openssl 30 + sqlite 31 + ]; 32 + 33 + nativeBuildInputs = [ pkg-config ]; 34 + 35 + passthru = { 36 + tests = { 37 + inherit (nixosTests) nixseparatedebuginfod; 38 + }; 39 + }; 40 + 41 + meta = with lib; { 42 + description = "Downloads and provides debug symbols and source code for nix derivations to gdb and other debuginfod-capable debuggers as needed"; 43 + homepage = "https://github.com/symphorien/nixseparatedebuginfod"; 44 + license = licenses.gpl3Only; 45 + maintainers = [ maintainers.symphorien ]; 46 + platforms = platforms.linux; 47 + mainProgram = "nixseparatedebuginfod"; 48 + }; 49 + }