1{ config, pkgs, lib, ... }:
2let
3 cfg = config.services.harmonia;
4 format = pkgs.formats.toml { };
5in
6{
7 options = {
8 services.harmonia = {
9 enable = lib.mkEnableOption "Harmonia: Nix binary cache written in Rust";
10
11 signKeyPath = lib.mkOption {
12 type = lib.types.nullOr lib.types.path;
13 default = null;
14 description = "Path to the signing key that will be used for signing the cache";
15 };
16
17 package = lib.mkPackageOption pkgs "harmonia" { };
18
19 settings = lib.mkOption {
20 inherit (format) type;
21 default = { };
22 description = ''
23 Settings to merge with the default configuration.
24 For the list of the default configuration, see <https://github.com/nix-community/harmonia/tree/master#configuration>.
25 '';
26 };
27 };
28 };
29
30 config = lib.mkIf cfg.enable {
31 nix.settings.extra-allowed-users = [ "harmonia" ];
32 users.users.harmonia = {
33 isSystemUser = true;
34 group = "harmonia";
35 };
36 users.groups.harmonia = { };
37
38 systemd.services.harmonia = {
39 description = "harmonia binary cache service";
40
41 requires = [ "nix-daemon.socket" ];
42 after = [ "network.target" ];
43 wantedBy = [ "multi-user.target" ];
44
45 environment = {
46 CONFIG_FILE = format.generate "harmonia.toml" cfg.settings;
47 SIGN_KEY_PATH = lib.mkIf (cfg.signKeyPath != null) "%d/sign-key";
48 # Note: it's important to set this for nix-store, because it wants to use
49 # $HOME in order to use a temporary cache dir. bizarre failures will occur
50 # otherwise
51 HOME = "/run/harmonia";
52 };
53
54 serviceConfig = {
55 ExecStart = lib.getExe cfg.package;
56 User = "harmonia";
57 Group = "harmonia";
58 Restart = "on-failure";
59 PrivateUsers = true;
60 DeviceAllow = [ "" ];
61 UMask = "0066";
62 RuntimeDirectory = "harmonia";
63 LoadCredential = lib.mkIf (cfg.signKeyPath != null) [ "sign-key:${cfg.signKeyPath}" ];
64 SystemCallFilter = [
65 "@system-service"
66 "~@privileged"
67 "~@resources"
68 ];
69 CapabilityBoundingSet = "";
70 ProtectKernelModules = true;
71 ProtectKernelTunables = true;
72 ProtectControlGroups = true;
73 ProtectKernelLogs = true;
74 ProtectHostname = true;
75 ProtectClock = true;
76 RestrictRealtime = true;
77 MemoryDenyWriteExecute = true;
78 ProcSubset = "pid";
79 ProtectProc = "invisible";
80 RestrictNamespaces = true;
81 SystemCallArchitectures = "native";
82 PrivateNetwork = false;
83 PrivateTmp = true;
84 PrivateDevices = true;
85 PrivateMounts = true;
86 NoNewPrivileges = true;
87 ProtectSystem = "strict";
88 ProtectHome = true;
89 LockPersonality = true;
90 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
91 LimitNOFILE = 65536;
92 };
93 };
94 };
95}