1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 cfg = config.services.cachix-watch-store;
9in
10{
11 meta.maintainers = [
12 lib.maintainers.jfroche
13 lib.maintainers.domenkozar
14 ];
15
16 options.services.cachix-watch-store = {
17 enable = lib.mkEnableOption "Cachix Watch Store: https://docs.cachix.org";
18
19 cacheName = lib.mkOption {
20 type = lib.types.str;
21 description = "Cachix binary cache name";
22 };
23
24 cachixTokenFile = lib.mkOption {
25 type = lib.types.path;
26 description = ''
27 Required file that needs to contain the cachix auth token.
28 '';
29 };
30
31 signingKeyFile = lib.mkOption {
32 type = lib.types.nullOr lib.types.path;
33 description = ''
34 Optional file containing a self-managed signing key to sign uploaded store paths.
35 '';
36 default = null;
37 };
38
39 compressionLevel = lib.mkOption {
40 type = lib.types.nullOr lib.types.int;
41 description = "The compression level for ZSTD compression (between 0 and 16)";
42 default = null;
43 };
44
45 jobs = lib.mkOption {
46 type = lib.types.nullOr lib.types.int;
47 description = "Number of threads used for pushing store paths";
48 default = null;
49 };
50
51 host = lib.mkOption {
52 type = lib.types.nullOr lib.types.str;
53 default = null;
54 description = "Cachix host to connect to";
55 };
56
57 verbose = lib.mkOption {
58 type = lib.types.bool;
59 description = "Enable verbose output";
60 default = false;
61 };
62
63 package = lib.mkPackageOption pkgs "cachix" { };
64 };
65
66 config = lib.mkIf cfg.enable {
67 systemd.services.cachix-watch-store-agent = {
68 description = "Cachix watch store Agent";
69 wants = [ "network-online.target" ];
70 after = [ "network-online.target" ];
71 path = [ config.nix.package ];
72 wantedBy = [ "multi-user.target" ];
73 unitConfig = {
74 # allow to restart indefinitely
75 StartLimitIntervalSec = 0;
76 };
77 serviceConfig = {
78 # don't put too much stress on the machine when restarting
79 RestartSec = 1;
80 # we don't want to kill children processes as those are deployments
81 KillMode = "process";
82 Restart = "on-failure";
83 DynamicUser = true;
84 LoadCredential = [
85 "cachix-token:${toString cfg.cachixTokenFile}"
86 ] ++ lib.optional (cfg.signingKeyFile != null) "signing-key:${toString cfg.signingKeyFile}";
87 };
88 script =
89 let
90 command =
91 [ "${cfg.package}/bin/cachix" ]
92 ++ (lib.optional cfg.verbose "--verbose")
93 ++ (lib.optionals (cfg.host != null) [
94 "--host"
95 cfg.host
96 ])
97 ++ [ "watch-store" ]
98 ++ (lib.optionals (cfg.compressionLevel != null) [
99 "--compression-level"
100 (toString cfg.compressionLevel)
101 ])
102 ++ (lib.optionals (cfg.jobs != null) [
103 "--jobs"
104 (toString cfg.jobs)
105 ])
106 ++ [ cfg.cacheName ];
107 in
108 ''
109 export CACHIX_AUTH_TOKEN="$(<"$CREDENTIALS_DIRECTORY/cachix-token")"
110 ${lib.optionalString (
111 cfg.signingKeyFile != null
112 ) ''export CACHIX_SIGNING_KEY="$(<"$CREDENTIALS_DIRECTORY/signing-key")"''}
113 ${lib.escapeShellArgs command}
114 '';
115 };
116 };
117}