{ pkgs, lib, config, ... }: let cfg = config.services.tvix-binary-cache; systemdHardening = { PrivateDevices = true; PrivateTmp = true; ProtectControlGroups = true; ProtectKernelTunables = true; RestrictSUIDSGID = true; ProtectSystem = "strict"; ProtectKernelLogs = true; ProtectProc = "invisible"; PrivateUsers = true; ProtectHome = true; UMask = "0077"; RuntimeDirectoryMode = "0750"; StateDirectoryMode = "0750"; }; in { options = { services.tvix-binary-cache = { enable = lib.mkEnableOption "BinaryCache using tvix ca-store"; blob-service-addr = lib.mkOption { type = lib.types.str; default = "objectstore+file://%S/tvix-castore/blobs.object-store"; description = '' `blob-service-addr` option for the castore (please read tvix source/docs to learn more). ''; }; directory-service-addr = lib.mkOption { type = lib.types.str; default = "sled://%S/tvix-castore/directories.sled"; description = '' `directory-service-addr` option for the castore (please read tvix source/docs to learn more). ''; }; caches = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule ( { name, ... }: { options = { port = lib.mkOption { type = lib.types.port; default = 9000; }; name = lib.mkOption { type = lib.types.str; description = "Name of the cache"; default = name; defaultText = lib.literalMD "Defaults to attribute name in services.tvix-binary-cache.caches"; }; }; } ) ); }; }; }; config = lib.mkIf cfg.enable { systemd.services = lib.mkMerge ( (lib.singleton { tvix-castore = { wants = [ "tvix-castore.service" ]; after = [ "tvix-castore.service" ]; environment = { BLOB_SERVICE_ADDR = cfg.blob-service-addr; DIRECTORY_SERVICE_ADDR = cfg.directory-service-addr; PATH_INFO_SERVICE_ADDR = "sled://%S/tvix-castore/pathinfo.sled"; # Unused but probably needed }; serviceConfig = { ExecStart = "${pkgs.tvix-store}/bin/tvix-store --otlp=false daemon --listen-address=\"%t/tvix-castore/socket\""; DynamicUser = true; User = "tvix-binary-cache"; StateDirectory = "tvix-castore"; RuntimeDirectory = "tvix-castore"; } // systemdHardening; }; }) ++ (lib.mapAttrsToList ( name: cfg: let stateDir = "tvix-binary-cache-${cfg.name}"; in { "nar-bridge-${cfg.name}" = { wants = [ "tvix-store-${cfg.name}.service" ]; wantedBy = [ "multi-user.target" ]; after = [ "tvix-store-${cfg.name}.service" ]; serviceConfig = rec { ExecStart = "${lib.getExe pkgs.nar-bridge-go} --otlp=false --listen-addr=\"[::1]:${builtins.toString cfg.port}\" --store-addr=\"unix://%t/${stateDir}/socket\""; DynamicUser = true; User = "tvix-binary-cache"; } // systemdHardening; }; "tvix-store-${cfg.name}" = { wants = [ "tvix-castore.service" ]; after = [ "tvix-castore.service" ]; environment = { BLOB_SERVICE_ADDR = "grpc+unix://%t/tvix-castore/socket"; DIRECTORY_SERVICE_ADDR = "grpc+unix://%t/tvix-castore/socket"; PATH_INFO_SERVICE_ADDR = "sled://%S/${stateDir}/pathinfo.sled"; }; serviceConfig = { ExecStart = "${pkgs.tvix-store}/bin/tvix-store --otlp=false daemon --listen-address=\"%t/${stateDir}/socket\""; DynamicUser = true; User = "tvix-binary-cache"; StateDirectory = stateDir; RuntimeDirectory = stateDir; } // systemdHardening; }; } ) cfg.caches) ); }; }