nixseparatedebuginfod2: init package and module (#428845)

authored by

Martin Weinelt and committed by
GitHub
63c4ed7e 99386fe3

+272 -29
+35 -8
nixos/modules/config/debug-info.nix
··· 1 - { config, lib, ... }: 1 + { 2 + config, 3 + lib, 4 + pkgs, 5 + ... 6 + }: 2 7 { 3 8 4 9 options = { ··· 23 28 ''; 24 29 }; 25 30 31 + environment.debuginfodServers = lib.mkOption { 32 + type = lib.types.listOf lib.types.str; 33 + default = [ ]; 34 + description = '' 35 + List of urls of debuginfod servers for tools like {command}`gdb` and {command}`valgrind` to use. 36 + 37 + Unrelated to {option}`environment.enableDebugInfo`. 38 + ''; 39 + }; 40 + 26 41 }; 27 42 28 - config = lib.mkIf config.environment.enableDebugInfo { 43 + config = lib.mkMerge [ 44 + (lib.mkIf config.environment.enableDebugInfo { 45 + 46 + # FIXME: currently disabled because /lib is already in 47 + # environment.pathsToLink, and we can't have both. 48 + #environment.pathsToLink = [ "/lib/debug/.build-id" ]; 29 49 30 - # FIXME: currently disabled because /lib is already in 31 - # environment.pathsToLink, and we can't have both. 32 - #environment.pathsToLink = [ "/lib/debug/.build-id" ]; 50 + environment.extraOutputsToInstall = [ "debug" ]; 51 + 52 + environment.variables.NIX_DEBUG_INFO_DIRS = [ "/run/current-system/sw/lib/debug" ]; 33 53 34 - environment.extraOutputsToInstall = [ "debug" ]; 54 + }) 55 + (lib.mkIf (config.environment.debuginfodServers != [ ]) { 56 + environment.variables.DEBUGINFOD_URLS = lib.strings.concatStringsSep " " config.environment.debuginfodServers; 35 57 36 - environment.variables.NIX_DEBUG_INFO_DIRS = [ "/run/current-system/sw/lib/debug" ]; 58 + environment.systemPackages = [ 59 + # valgrind support requires debuginfod-find on PATH 60 + (lib.getBin pkgs.elfutils) 61 + ]; 37 62 38 - }; 63 + environment.etc."gdb/gdbinit.d/nixseparatedebuginfod2.gdb".text = "set debuginfod enabled on"; 64 + }) 65 + ]; 39 66 40 67 }
+1
nixos/modules/module-list.nix
··· 591 591 ./services/development/jupyterhub/default.nix 592 592 ./services/development/livebook.nix 593 593 ./services/development/lorri.nix 594 + ./services/development/nixseparatedebuginfod2.nix 594 595 ./services/development/nixseparatedebuginfod.nix 595 596 ./services/development/rstudio-server/default.nix 596 597 ./services/development/vsmartcard-vpcd.nix
+1 -9
nixos/modules/services/development/nixseparatedebuginfod.nix
··· 101 101 extra-allowed-users = [ "nixseparatedebuginfod" ]; 102 102 }; 103 103 104 - environment.variables.DEBUGINFOD_URLS = "http://${url}"; 105 - 106 - environment.systemPackages = [ 107 - # valgrind support requires debuginfod-find on PATH 108 - (lib.getBin pkgs.elfutils) 109 - ]; 110 - 111 - environment.etc."gdb/gdbinit.d/nixseparatedebuginfod.gdb".text = "set debuginfod enabled on"; 112 - 104 + environment.debuginfodServers = [ "http://${url}" ]; 113 105 }; 114 106 }
+97
nixos/modules/services/development/nixseparatedebuginfod2.nix
··· 1 + { 2 + pkgs, 3 + lib, 4 + config, 5 + utils, 6 + ... 7 + }: 8 + let 9 + cfg = config.services.nixseparatedebuginfod2; 10 + url = "127.0.0.1:${toString cfg.port}"; 11 + in 12 + { 13 + options = { 14 + services.nixseparatedebuginfod2 = { 15 + enable = lib.mkEnableOption "nixseparatedebuginfod2, a debuginfod server providing source and debuginfo for nix packages"; 16 + port = lib.mkOption { 17 + description = "port to listen"; 18 + default = 1950; 19 + type = lib.types.port; 20 + }; 21 + package = lib.mkPackageOption pkgs "nixseparatedebuginfod2" { }; 22 + substituter = lib.mkOption { 23 + description = "nix substituter to fetch debuginfo from. Either http/https substituters, or `local:` to use debuginfo present in the local store."; 24 + default = "https://cache.nixos.org"; 25 + example = "local:"; 26 + type = lib.types.str; 27 + }; 28 + cacheExpirationDelay = lib.mkOption { 29 + description = "keep unused cache entries for this long. A number followed by a unit"; 30 + default = "1d"; 31 + type = lib.types.str; 32 + }; 33 + }; 34 + }; 35 + config = lib.mkIf cfg.enable { 36 + systemd.services.nixseparatedebuginfod2 = { 37 + wantedBy = [ "multi-user.target" ]; 38 + path = [ config.nix.package ]; 39 + serviceConfig = { 40 + ExecStart = [ 41 + (utils.escapeSystemdExecArgs [ 42 + (lib.getExe cfg.package) 43 + "--listen-address" 44 + url 45 + "--substituter" 46 + cfg.substituter 47 + "--expiration" 48 + cfg.cacheExpirationDelay 49 + ]) 50 + ]; 51 + Restart = "on-failure"; 52 + CacheDirectory = "nixseparatedebuginfod2"; 53 + DynamicUser = true; 54 + 55 + # hardening 56 + # Filesystem stuff 57 + ProtectSystem = "strict"; # Prevent writing to most of / 58 + ProtectHome = true; # Prevent accessing /home and /root 59 + PrivateTmp = true; # Give an own directory under /tmp 60 + PrivateDevices = true; # Deny access to most of /dev 61 + ProtectKernelTunables = true; # Protect some parts of /sys 62 + ProtectControlGroups = true; # Remount cgroups read-only 63 + RestrictSUIDSGID = true; # Prevent creating SETUID/SETGID files 64 + PrivateMounts = true; # Give an own mount namespace 65 + RemoveIPC = true; 66 + UMask = "0077"; 67 + 68 + # Capabilities 69 + CapabilityBoundingSet = ""; # Allow no capabilities at all 70 + NoNewPrivileges = true; # Disallow getting more capabilities. This is also implied by other options. 71 + 72 + # Kernel stuff 73 + ProtectKernelModules = true; # Prevent loading of kernel modules 74 + SystemCallArchitectures = "native"; # Usually no need to disable this 75 + SystemCallFilter = "@system-service"; 76 + ProtectKernelLogs = true; # Prevent access to kernel logs 77 + ProtectClock = true; # Prevent setting the RTC 78 + ProtectProc = "noaccess"; 79 + ProcSubset = "pid"; 80 + 81 + # Networking 82 + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; 83 + 84 + # Misc 85 + LockPersonality = true; # Prevent change of the personality 86 + ProtectHostname = true; # Give an own UTS namespace 87 + RestrictRealtime = true; # Prevent switching to RT scheduling 88 + MemoryDenyWriteExecute = true; # Maybe disable this for interpreters like python 89 + RestrictNamespaces = true; 90 + 91 + }; 92 + }; 93 + 94 + environment.debuginfodServers = [ "http://${url}" ]; 95 + 96 + }; 97 + }
+1
nixos/tests/all-tests.nix
··· 1059 1059 }; 1060 1060 nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; }; 1061 1061 nixseparatedebuginfod = runTest ./nixseparatedebuginfod.nix; 1062 + nixseparatedebuginfod2 = runTest ./nixseparatedebuginfod2.nix; 1062 1063 node-red = runTest ./node-red.nix; 1063 1064 nomad = runTest ./nomad.nix; 1064 1065 nominatim = runTest ./nominatim.nix;
+13 -12
nixos/tests/nixseparatedebuginfod.nix
··· 5 5 in 6 6 { 7 7 name = "nixseparatedebuginfod"; 8 - # A binary cache with debug info and source for nix 8 + # A binary cache with debug info and source for gnumake 9 9 nodes.cache = 10 10 { pkgs, ... }: 11 11 { ··· 15 15 openFirewall = true; 16 16 }; 17 17 system.extraDependencies = [ 18 - pkgs.nix.debug 19 - pkgs.nix.src 18 + pkgs.gnumake.debug 19 + pkgs.gnumake.src 20 20 pkgs.sl 21 21 ]; 22 22 }; ··· 33 33 environment.systemPackages = [ 34 34 pkgs.valgrind 35 35 pkgs.gdb 36 + pkgs.gnumake 36 37 (pkgs.writeShellScriptBin "wait_for_indexation" '' 37 38 set -x 38 - while debuginfod-find debuginfo /run/current-system/sw/bin/nix |& grep 'File too large'; do 39 + while debuginfod-find debuginfo /run/current-system/sw/bin/make |& grep 'File too large'; do 39 40 sleep 1; 40 41 done 41 42 '') ··· 56 57 57 58 # nixseparatedebuginfod needs .drv to associate executable -> source 58 59 # on regular systems this would be provided by nixos-rebuild 59 - machine.succeed("nix-instantiate '<nixpkgs>' -A nix") 60 + machine.succeed("nix-instantiate '<nixpkgs>' -A gnumake") 60 61 61 62 machine.succeed("timeout 600 wait_for_indexation") 62 63 63 64 # test debuginfod-find 64 - machine.succeed("debuginfod-find debuginfo /run/current-system/sw/bin/nix") 65 + machine.succeed("debuginfod-find debuginfo /run/current-system/sw/bin/make") 65 66 66 67 # test that gdb can fetch source 67 - out = machine.succeed("gdb /run/current-system/sw/bin/nix --batch -x ${builtins.toFile "commands" '' 68 + out = machine.succeed("gdb /run/current-system/sw/bin/make --batch -x ${builtins.toFile "commands" '' 68 69 start 69 70 l 70 71 ''}") 71 72 print(out) 72 - assert 'int main(' in out 73 + assert 'main (int argc, char **argv, char **envp)' in out 73 74 74 75 # test that valgrind can display location information 75 - # this relies on the fact that valgrind complains about nix 76 - # libgc helps in this regard, and we also ask valgrind to show leak kinds 76 + # this relies on the fact that valgrind complains about gnumake 77 + # because we also ask valgrind to show leak kinds 77 78 # which are usually false positives. 78 - out = machine.succeed("valgrind --leak-check=full --show-leak-kinds=all nix-env --version 2>&1") 79 + out = machine.succeed("valgrind --leak-check=full --show-leak-kinds=all make --version 2>&1") 79 80 print(out) 80 - assert 'main.cc' in out 81 + assert 'main.c' in out 81 82 ''; 82 83 }
+72
nixos/tests/nixseparatedebuginfod2.nix
··· 1 + { pkgs, lib, ... }: 2 + { 3 + name = "nixseparatedebuginfod2"; 4 + # A binary cache with debug info and source for gnumake 5 + nodes.cache = 6 + { pkgs, ... }: 7 + { 8 + services.nginx = { 9 + enable = true; 10 + virtualHosts.default = { 11 + default = true; 12 + addSSL = false; 13 + root = "/var/lib/thebinarycache"; 14 + }; 15 + }; 16 + networking.firewall.allowedTCPPorts = [ 80 ]; 17 + systemd.services.buildthebinarycache = { 18 + before = [ "nginx.service" ]; 19 + wantedBy = [ "nginx.service" ]; 20 + script = '' 21 + ${pkgs.nix}/bin/nix --extra-experimental-features nix-command copy --to file:///var/lib/thebinarycache?index-debug-info=true ${pkgs.gnumake.debug} ${pkgs.gnumake} ${pkgs.gnumake.src} ${pkgs.sl} 22 + ''; 23 + serviceConfig = { 24 + User = "nginx"; 25 + Group = "nginx"; 26 + StateDirectory = "thebinarycache"; 27 + Type = "oneshot"; 28 + }; 29 + }; 30 + }; 31 + # the machine where we need the debuginfo 32 + nodes.machine = { 33 + services.nixseparatedebuginfod2 = { 34 + enable = true; 35 + substituter = "http://cache"; 36 + }; 37 + environment.systemPackages = [ 38 + pkgs.valgrind 39 + pkgs.gdb 40 + pkgs.gnumake 41 + ]; 42 + }; 43 + testScript = '' 44 + start_all() 45 + cache.wait_for_unit("nginx.service") 46 + cache.wait_for_open_port(80) 47 + machine.wait_for_unit("nixseparatedebuginfod2.service") 48 + machine.wait_for_open_port(1950) 49 + 50 + with subtest("check that the binary cache works"): 51 + machine.succeed("nix-store --extra-substituters http://cache --option require-sigs false -r ${pkgs.sl}") 52 + 53 + # test debuginfod-find 54 + machine.succeed("debuginfod-find debuginfo /run/current-system/sw/bin/make") 55 + 56 + # test that gdb can fetch source 57 + out = machine.succeed("gdb /run/current-system/sw/bin/make --batch -x ${builtins.toFile "commands" '' 58 + start 59 + l 60 + ''}") 61 + print(out) 62 + assert 'main (int argc, char **argv, char **envp)' in out 63 + 64 + # test that valgrind can display location information 65 + # this relies on the fact that valgrind complains about gnumake 66 + # because we also ask valgrind to show leak kinds 67 + # which are usually false positives. 68 + out = machine.succeed("valgrind --leak-check=full --show-leak-kinds=all make --version 2>&1") 69 + print(out) 70 + assert 'main.c' in out 71 + ''; 72 + }
+52
pkgs/by-name/ni/nixseparatedebuginfod2/package.nix
··· 1 + { 2 + lib, 3 + fetchFromGitHub, 4 + rustPlatform, 5 + libarchive, 6 + openssl, 7 + pkg-config, 8 + bubblewrap, 9 + elfutils, 10 + nix, 11 + nixosTests, 12 + }: 13 + 14 + rustPlatform.buildRustPackage rec { 15 + pname = "nixseparatedebuginfod2"; 16 + version = "0.1.0"; 17 + 18 + src = fetchFromGitHub { 19 + owner = "symphorien"; 20 + repo = "nixseparatedebuginfod2"; 21 + tag = "v${version}"; 22 + hash = "sha256-bk+l/oWAPuWV6mnh9Pr/mru3BZjos08IfzEGUEFSW1E="; 23 + }; 24 + 25 + cargoHash = "sha256-HmtFso6uF2GsjIA0FPVL4S3S+lwQUrg7N576UaekXpU="; 26 + 27 + buildInputs = [ 28 + libarchive 29 + openssl 30 + ]; 31 + 32 + nativeBuildInputs = [ pkg-config ]; 33 + 34 + nativeCheckInputs = [ 35 + bubblewrap 36 + elfutils 37 + nix 38 + ]; 39 + 40 + env.OPENSSL_NO_VENDOR = "1"; 41 + 42 + passthru.tests = { inherit (nixosTests) nixseparatedebuginfod2; }; 43 + 44 + meta = { 45 + description = "Downloads and provides debug symbols and source code for nix derivations to gdb and other debuginfod-capable debuggers as needed"; 46 + homepage = "https://github.com/symphorien/nixseparatedebuginfod2"; 47 + license = lib.licenses.gpl3Only; 48 + maintainers = [ lib.maintainers.symphorien ]; 49 + platforms = lib.platforms.linux; 50 + mainProgram = "nixseparatedebuginfod2"; 51 + }; 52 + }