From e3ff293c0c66e26f2572de163e4a1a86658677a3 Mon Sep 17 00:00:00 2001 From: Pim Kunis Date: Tue, 1 Oct 2024 18:46:15 +0200 Subject: [PATCH] Use NixNG for Attic container --- flake.lock | 19 +-- flake.nix | 2 +- globals.nix | 1 - modules/attic-image.nix | 59 +++++++++ modules/attic.nix | 267 ++++++++++++++++++---------------------- 5 files changed, 191 insertions(+), 157 deletions(-) create mode 100644 modules/attic-image.nix diff --git a/flake.lock b/flake.lock index 47c7d7f..df8fbf8 100644 --- a/flake.lock +++ b/flake.lock @@ -471,15 +471,16 @@ ] }, "locked": { - "lastModified": 1727033240, - "narHash": "sha256-LEug48WOL+mmFYtKM57e/oudgjBk2Km5zIP3p27hF8I=", - "owner": "nix-community", + "lastModified": 1727766416, + "narHash": "sha256-gxizo/V/Ut60MRtCB+jJJoDxNfsfApxH0mIkNFI2cVY=", + "owner": "pizzapim", "repo": "NixNG", - "rev": "c7e38ecb6a655d39d9a9d275ec330e3e3f73fda8", + "rev": "bf6eb29623cff5e70d79d233b7bd18643c555ab3", "type": "github" }, "original": { - "owner": "nix-community", + "owner": "pizzapim", + "ref": "attic", "repo": "NixNG", "type": "github" } @@ -640,11 +641,11 @@ "sops-nix": "sops-nix" }, "locked": { - "lastModified": 1727038016, - "narHash": "sha256-sL2CL8xgubM0hUz7npS+nei0rxWDBgqMZr7q9lpH9so=", + "lastModified": 1727210707, + "narHash": "sha256-3pw0xNT2QGCI62X18UZYZln/TdaTVxjU+BTRyE3o5vQ=", "ref": "refs/heads/master", - "rev": "3d456b1a4383d2f40cceb691182c4364333fe934", - "revCount": 475, + "rev": "fcc2848523f2350167e6894620d63740526c186f", + "revCount": 476, "type": "git", "url": "https://git.kun.is/home/nixos-servers" }, diff --git a/flake.nix b/flake.nix index 334c94d..b9c0bbb 100644 --- a/flake.nix +++ b/flake.nix @@ -35,7 +35,7 @@ }; nixng = { - url = "github:nix-community/NixNG"; + url = "github:pizzapim/NixNG/attic"; inputs.nixpkgs.follows = "nixpkgs"; }; }; diff --git a/globals.nix b/globals.nix index 16f92ab..e52575a 100644 --- a/globals.nix +++ b/globals.nix @@ -30,7 +30,6 @@ let cyberchef = "mpepping/cyberchef:latest"; freshrss = "freshrss/freshrss:1.24.3"; bind9 = "ubuntu/bind9:9.18-22.04_beta"; - attic = "git.kun.is/home/atticd:fd910d91c2143295e959d2c903e9ea25cf94ba27"; hedgedoc = "quay.io/hedgedoc/hedgedoc:1.9.9"; minecraft = "itzg/minecraft-server:latest"; }; diff --git a/modules/attic-image.nix b/modules/attic-image.nix new file mode 100644 index 0000000..ee8a0aa --- /dev/null +++ b/modules/attic-image.nix @@ -0,0 +1,59 @@ +{ nixpkgs, nglib, ... }: +nglib.makeSystem { + inherit nixpkgs; + system = "x86_64-linux"; + name = "nixng-attic"; + + config = { ... }: { + dumb-init = { + enable = true; + type.services = { }; + }; + + init.services.attic = { + shutdownOnExit = true; + }; + + services.attic = { + enable = true; + + settings = { + # The '+" is to explicitly denote the end of the Vals expression. + # This is done because we quote the template for the toml file. + # See: https://github.com/helmfile/vals?tab=readme-ov-file#expression-syntax + # database.url = "ref+sops://secrets.yml#attic/databaseURL+"; + database = { }; + + storage = { + type = "local"; + path = "/var/lib/atticd/storage"; + }; + + listen = "[::]:8080"; + + # 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 + # + # If 0, 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 + }; + }; + }; + }; +} diff --git a/modules/attic.nix b/modules/attic.nix index 79d14fb..8770375 100644 --- a/modules/attic.nix +++ b/modules/attic.nix @@ -1,184 +1,159 @@ -{ pkgs, lib, config, globals, ... }: { +{ nixpkgs, pkgs, lib, nixng, config, globals, ... }: +let + + atticStream = (import ./attic-image.nix { + inherit nixpkgs nixng globals; + inherit (nixng) nglib; + }).config.system.build.ociImage.stream; + + atticImage = pkgs.stdenv.mkDerivation { + name = "attic.tar"; + src = atticStream; + dontUnpack = true; + buildPhase = '' + $src > $out + ''; + }; +in +{ options.attic.enable = lib.mkEnableOption "attic"; config = lib.mkIf config.attic.enable { - kubernetes.resources = - let - atticSettings = { - # The '+" is to explicitly denote the end of the Vals expression. - # This is done because we quote the template for the INI file. - # See: https://github.com/helmfile/vals?tab=readme-ov-file#expression-syntax - database.url = "ref+sops://secrets.yml#attic/databaseURL+"; - - storage = { - type = "local"; - path = "/var/lib/atticd/storage"; - }; - - listen = "[::]:8080"; - - # 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 - # - # If 0, 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 - }; + kubernetes.resources = { + secrets = { + server.stringData.token = "ref+sops://secrets.yml#attic/jwtToken"; + database.stringData = { + password = "ref+sops://secrets.yml#/attic/databasePassword"; + url = "ref+sops://secrets.yml#/attic/databaseURL+"; }; - generatedConfig = (pkgs.formats.toml { }).generate "attic.toml" atticSettings; - in - { - secrets = { - server.stringData = { - token = "ref+sops://secrets.yml#attic/jwtToken"; - config = builtins.readFile generatedConfig; + }; + + deployments = { + attic.spec = { + selector.matchLabels = { + app = "attic"; + component = "website"; }; - database.stringData.password = "ref+sops://secrets.yml#/attic/databasePassword"; - }; + strategy = { + type = "RollingUpdate"; - deployments = { - attic.spec = { - selector.matchLabels = { + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "attic"; component = "website"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.attic = { + image = "nix:0${atticImage}"; + ports.web.containerPort = 8080; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; - - template = { - metadata.labels = { - app = "attic"; - component = "website"; - }; - - spec = { - containers.attic = { - image = globals.images.attic; - ports.web.containerPort = 8080; - args = [ "-f" "/etc/atticd/config.toml" ]; - - env.ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64.valueFrom.secretKeyRef = { + env = { + ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64.valueFrom.secretKeyRef = { name = "server"; key = "token"; }; - volumeMounts = [ - { - name = "data"; - mountPath = "/var/lib/atticd/storage"; - } - { - name = "config"; - mountPath = "/etc/atticd/config.toml"; - subPath = "config"; - } - ]; - }; - - volumes = { - data.persistentVolumeClaim.claimName = "data"; - config.secret.secretName = "server"; - }; - - securityContext = { - fsGroup = 0; - fsGroupChangePolicy = "OnRootMismatch"; - }; - }; - }; - }; - - attic-db.spec = { - selector.matchLabels = { - app = "attic"; - component = "database"; - }; - - template = { - metadata.labels = { - app = "attic"; - component = "database"; - }; - - spec = { - containers.postgres = { - image = globals.images.postgres15; - imagePullPolicy = "IfNotPresent"; - ports.postgres.containerPort = 5432; - - env = { - POSTGRES_DB.value = "attic"; - POSTGRES_USER.value = "attic"; - PGDATA.value = "/pgdata/data"; - - POSTGRES_PASSWORD.valueFrom.secretKeyRef = { - name = "database"; - key = "password"; - }; + ATTIC_SERVER_DATABASE_URL.valueFrom.secretKeyRef = { + name = "database"; + key = "url"; }; - - volumeMounts = [{ - name = "data"; - mountPath = "/pgdata"; - }]; }; - volumes.data.persistentVolumeClaim.claimName = "database"; + volumeMounts = [{ + name = "data"; + mountPath = "/var/lib/atticd/storage"; + }]; + }; + + volumes = { + data.persistentVolumeClaim.claimName = "data"; + server.secret.secretName = "server"; + }; + + securityContext = { + fsGroup = 0; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - services = { - attic.spec = { - selector = { - app = "attic"; - component = "website"; - }; - - ports.web = { - port = 80; - targetPort = "web"; - }; + attic-db.spec = { + selector.matchLabels = { + app = "attic"; + component = "database"; }; - database.spec = { - selector = { + template = { + metadata.labels = { app = "attic"; component = "database"; }; - ports.postgres = { - port = 5432; - targetPort = "postgres"; + spec = { + containers.postgres = { + image = globals.images.postgres15; + imagePullPolicy = "IfNotPresent"; + ports.postgres.containerPort = 5432; + + env = { + POSTGRES_DB.value = "attic"; + POSTGRES_USER.value = "attic"; + PGDATA.value = "/pgdata/data"; + + POSTGRES_PASSWORD.valueFrom.secretKeyRef = { + name = "database"; + key = "password"; + }; + }; + + volumeMounts = [{ + name = "data"; + mountPath = "/pgdata"; + }]; + }; + + volumes.data.persistentVolumeClaim.claimName = "database"; }; }; }; }; + services = { + attic.spec = { + selector = { + app = "attic"; + component = "website"; + }; + + ports.web = { + port = 80; + targetPort = "web"; + }; + }; + + database.spec = { + selector = { + app = "attic"; + component = "database"; + }; + + ports.postgres = { + port = 5432; + targetPort = "postgres"; + }; + }; + }; + }; + lab = { ingresses.attic = { host = "attic.kun.is";