1{
2 pkgs,
3 lib,
4 config,
5 ...
6}:
7let
8 cfg = config.services.nixseparatedebuginfod;
9 url = "127.0.0.1:${toString cfg.port}";
10in
11{
12 options = {
13 services.nixseparatedebuginfod = {
14 enable = lib.mkEnableOption "separatedebuginfod, a debuginfod server providing source and debuginfo for nix packages";
15 port = lib.mkOption {
16 description = "port to listen";
17 default = 1949;
18 type = lib.types.port;
19 };
20 nixPackage = lib.mkOption {
21 type = lib.types.package;
22 default = pkgs.nix;
23 defaultText = lib.literalExpression "pkgs.nix";
24 description = ''
25 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.
26 '';
27 };
28 allowOldNix = lib.mkOption {
29 type = lib.types.bool;
30 default = false;
31 description = ''
32 Do not fail evaluation when {option}`services.nixseparatedebuginfod.nixPackage` is older than nix 2.18.
33 '';
34 };
35 };
36 };
37 config = lib.mkIf cfg.enable {
38 assertions = [
39 {
40 assertion = cfg.allowOldNix || (lib.versionAtLeast cfg.nixPackage.version "2.18");
41 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.";
42 }
43 ];
44
45 systemd.services.nixseparatedebuginfod = {
46 wantedBy = [ "multi-user.target" ];
47 wants = [ "nix-daemon.service" ];
48 after = [ "nix-daemon.service" ];
49 path = [ cfg.nixPackage ];
50 serviceConfig = {
51 ExecStart = [ "${pkgs.nixseparatedebuginfod}/bin/nixseparatedebuginfod -l ${url}" ];
52 Restart = "on-failure";
53 CacheDirectory = "nixseparatedebuginfod";
54 # nix does not like DynamicUsers in allowed-users
55 User = "nixseparatedebuginfod";
56 Group = "nixseparatedebuginfod";
57
58 # hardening
59 # Filesystem stuff
60 ProtectSystem = "strict"; # Prevent writing to most of /
61 ProtectHome = true; # Prevent accessing /home and /root
62 PrivateTmp = true; # Give an own directory under /tmp
63 PrivateDevices = true; # Deny access to most of /dev
64 ProtectKernelTunables = true; # Protect some parts of /sys
65 ProtectControlGroups = true; # Remount cgroups read-only
66 RestrictSUIDSGID = true; # Prevent creating SETUID/SETGID files
67 PrivateMounts = true; # Give an own mount namespace
68 RemoveIPC = true;
69 UMask = "0077";
70
71 # Capabilities
72 CapabilityBoundingSet = ""; # Allow no capabilities at all
73 NoNewPrivileges = true; # Disallow getting more capabilities. This is also implied by other options.
74
75 # Kernel stuff
76 ProtectKernelModules = true; # Prevent loading of kernel modules
77 SystemCallArchitectures = "native"; # Usually no need to disable this
78 ProtectKernelLogs = true; # Prevent access to kernel logs
79 ProtectClock = true; # Prevent setting the RTC
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 users.users.nixseparatedebuginfod = {
94 isSystemUser = true;
95 group = "nixseparatedebuginfod";
96 };
97
98 users.groups.nixseparatedebuginfod = { };
99
100 nix.settings = lib.optionalAttrs (lib.versionAtLeast config.nix.package.version "2.4") {
101 extra-allowed-users = [ "nixseparatedebuginfod" ];
102 };
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
113 };
114}