about summary refs log tree commit diff
path: root/modules/services
diff options
context:
space:
mode:
authorsefidel <contact@sefidel.net>2024-02-10 19:57:01 +0900
committersefidel <contact@sefidel.net>2024-02-10 19:57:01 +0900
commitea8153a1d7273cafdc5444094ec7c43d688c9288 (patch)
tree577ccabef268a178338825d8d0a3bf6a4118b960 /modules/services
parent48d9a41ca267664062e872ae3ee3be158e30ebce (diff)
downloadnixrc-ea8153a1d7273cafdc5444094ec7c43d688c9288.tar.gz
nixrc-ea8153a1d7273cafdc5444094ec7c43d688c9288.zip
feat(modules): add atticd
Diffstat (limited to 'modules/services')
-rw-r--r--modules/services/atticd.nix100
1 files changed, 100 insertions, 0 deletions
diff --git a/modules/services/atticd.nix b/modules/services/atticd.nix
new file mode 100644
index 0000000..444f6eb
--- /dev/null
+++ b/modules/services/atticd.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.modules.services.atticd;
+in
+{
+  options.modules.services.atticd = {
+    enable = mkEnableOption "Whether to enable atticd, a Multi-tenant Nix Binary Cache";
+
+    hosts = mkOption { type = types.listOf types.str; description = "List of FQDNs where attic is reachable at"; };
+    baseURL = mkOption { type = types.str; description = "URL to use as a API Endpoint"; };
+
+    storagePath = mkOption { type = types.path; description = "Path to the directory to store all files under"; };
+
+    watchStore = mkEnableOption "Whether to watch the Nix store for new paths";
+
+    secrets = {
+      attic-credentials = mkOption { type = types.path; description = "Path to the acme environment file"; };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.atticd = {
+      enable = true;
+      credentialsFile = cfg.secrets.attic-credentials;
+
+      settings = {
+        listen = "[::]:4005";
+        allowed-hosts = cfg.hosts;
+        api-endpoint = cfg.baseURL;
+
+        database.url = "postgres://atticd?host=/run/postgresql";
+
+        require-proof-of-possession = false;
+
+        # Data chunking
+        #
+        # Warning: If you change any of the values here, it will be
+        # difficult to reuse existing chunks for newly-uploaded NARs
+        # since the cutpoints will be different. As a result, the
+        # deduplication ratio will suffer for a while after the change.
+        chunking = {
+          # The minimum NAR size to trigger chunking
+          #
+          # IUUU, chunking is disabled entirely for newly-uploaded NARs.
+          # If 1, all NARs are chunked.
+          nar-size-threshold = 64 * 1024; # 64 KiB
+
+          # The preferred minimum size of a chunk, in bytes
+          min-size = 16 * 1024; # 16 KiB
+
+          # The preferred average size of a chunk, in bytes
+          avg-size = 64 * 1024; # 64 KiB
+
+          # The preferred maximum size of a chunk, in bytes
+          max-size = 256 * 1024; # 256 KiB
+        };
+        storage = {
+          type = "local";
+          path = cfg.storagePath;
+        };
+        compression = {
+          type = "zstd";
+          level = 9;
+        };
+        garbage-collection = {
+          interval = "12 hours";
+          default-retention-period = "4 weeks";
+        };
+      };
+    };
+
+    services.postgresql.ensureDatabases = [ "atticd" ];
+    services.postgresql.ensureUsers = [
+      {
+        name = "atticd";
+        ensureDBOwnership = true;
+      }
+    ];
+
+    systemd.services.atticd-watch-store = mkIf cfg.watchStore {
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "network-online.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.attic}/bin/attic watch-store hydra";
+        Restart = "on-failure";
+        RestartSec = "5s";
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
+        RestrictNamespaces = true;
+        RestrictSUIDSGID = true;
+      };
+    };
+  };
+}