diff --git a/kubenix-modules/all.nix b/kubenix-modules/all.nix index 196271e..eb470c4 100644 --- a/kubenix-modules/all.nix +++ b/kubenix-modules/all.nix @@ -18,6 +18,7 @@ let ./blog.nix ./attic.nix ./atuin.nix + ./immich.nix # ./argo.nix # ./minecraft.nix ]; diff --git a/kubenix-modules/base.nix b/kubenix-modules/base.nix index 9cab73f..018f126 100644 --- a/kubenix-modules/base.nix +++ b/kubenix-modules/base.nix @@ -57,16 +57,6 @@ }; }; }; - - immich = { - chart = nixhelm.chartsDerivations.${system}.immich.immich; - includeCRDs = true; - values = { - immich.persistence.library.existingClaim = "immich-test"; - redis.enabled = true; - postgresql.enabled = true; - }; - }; }; resources.nodes = @@ -79,15 +69,5 @@ }) machinesWithKubernetesLabels; }; - - lab.ingresses.immich-test = { - host = "immich.kun.is"; - entrypoint = "localsecure"; - - service = { - name = "immich-server"; - portName = "http"; - }; - }; }; } diff --git a/kubenix-modules/immich.nix b/kubenix-modules/immich.nix new file mode 100644 index 0000000..c344197 --- /dev/null +++ b/kubenix-modules/immich.nix @@ -0,0 +1,246 @@ +{ + kubernetes.resources = { + deployments = { + immich-server = { + metadata.labels = { + app = "immich"; + component = "server"; + }; + + spec = { + selector.matchLabels = { + app = "immich"; + component = "server"; + }; + + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { + app = "immich"; + component = "server"; + }; + + spec = { + volumes.data.persistentVolumeClaim.claimName = "immich"; + + containers.immich = { + image = "ghcr.io/immich-app/immich-server:v1.106.4"; + imagePullPolicy = "Always"; + ports.web.containerPort = 3001; + + env = { + TZ.value = "Europe/Amsterdam"; + UPLOAD_LOCATION.value = "/library"; + # IMMICH_CONFIG_FILE.value = "?"; + REDIS_HOSTNAME.value = "immich-redis.default.svc.cluster.local"; + DB_HOSTNAME.value = "immich-postgres.default.svc.cluster.local"; + DB_USERNAME.value = "postgres"; + DB_PASSWORD.value = "ref+sops://secrets/kubernetes.yaml#/immich/databasePassword"; + DB_DATABASE_NAME.value = "immich"; + IMMICH_MACHINE_LEARNING_URL.value = "http://immich-ml.default.svc.cluster.local"; + }; + + volumeMounts = [{ + name = "data"; + mountPath = "/library"; + }]; + }; + }; + }; + }; + }; + + immich-ml = { + metadata.labels = { + app = "immich"; + component = "machine-learning"; + }; + + spec = { + selector.matchLabels = { + app = "immich"; + component = "machine-learning"; + }; + + template = { + metadata.labels = { + app = "immich"; + component = "machine-learning"; + }; + + spec = { + containers.machine-learning = { + image = "ghcr.io/immich-app/immich-machine-learning:v1.106.4"; + imagePullPolicy = "Always"; + ports.ml.containerPort = 3003; + }; + }; + }; + }; + }; + + immich-redis = { + metadata.labels = { + app = "immich"; + component = "redis"; + }; + + spec = { + selector.matchLabels = { + app = "immich"; + component = "redis"; + }; + + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { + app = "immich"; + component = "redis"; + }; + + spec = { + containers.redis = { + image = "docker.io/redis:6.2-alpine@sha256:d6c2911ac51b289db208767581a5d154544f2b2fe4914ea5056443f62dc6e900"; + ports.redis.containerPort = 6379; + imagePullPolicy = "Always"; + }; + }; + }; + }; + }; + + immich-database = { + metadata.labels = { + app = "immich"; + component = "database"; + }; + + spec = { + selector.matchLabels = { + app = "immich"; + component = "database"; + }; + + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { + app = "immich"; + component = "database"; + }; + + spec = { + volumes.data.persistentVolumeClaim.claimName = "immich-db"; + # securityContext.fsGroup = 0700; + + containers.postgres = { + image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0"; + imagePullPolicy = "Always"; + command = [ "postgres" ]; + args = [ "-c" "shared_preload_libraries=vectors.so" "-c" "search_path=\"$$user\", public, vectors" "-c" "logging_collector=on" "-c" "max_wal_size=2GB" "-c" "shared_buffers=512MB" "-c" "wal_compression=on" ]; + ports.postgres.containerPort = 5432; + securityContext.runAsUser = 999; + securityContext.runAsGroup = 999; + + env = { + POSTGRES_PASSWORD.value = "ref+sops://secrets/kubernetes.yaml#/immich/databasePassword"; + POSTGRES_USER.value = "postgres"; + POSTGRES_DB.value = "immich"; + POSTGRES_INITDB_ARGS.value = "--data-checksums"; + PGDATA.value = "/pgdata/data"; + }; + + volumeMounts = [{ + name = "data"; + mountPath = "/pgdata"; + }]; + }; + }; + }; + }; + }; + }; + + services = { + immich-server.spec = { + selector = { + app = "immich"; + component = "server"; + }; + + ports.web = { + port = 80; + targetPort = "web"; + }; + }; + + immich-redis.spec = { + selector = { + app = "immich"; + component = "redis"; + }; + + ports.redis = { + port = 6379; + targetPort = "redis"; + }; + }; + + immich-ml.spec = { + selector = { + app = "immich"; + component = "machine-learning"; + }; + + ports.machine-learning = { + port = 80; + targetPort = "ml"; + }; + }; + + immich-postgres.spec = { + selector = { + app = "immich"; + component = "database"; + }; + + ports.postgres = { + port = 5432; + targetPort = "postgres"; + }; + }; + }; + }; + + lab.ingresses.immich-test = { + host = "immich.kun.is"; + + service = { + name = "immich-server"; + portName = "web"; + }; + }; +} diff --git a/kubenix-modules/volumes.nix b/kubenix-modules/volumes.nix index 9231b7c..7ea3e15 100644 --- a/kubenix-modules/volumes.nix +++ b/kubenix-modules/volumes.nix @@ -25,9 +25,10 @@ bazarr.storage = "25Mi"; attic.storage = "15Gi"; attic-db.storage = "150Mi"; - immich-test.storage = "10Gi"; atuin.storage = "600Mi"; atuin-db.storage = "100Mi"; + immich.storage = "50Gi"; + immich-db.storage = "1Gi"; }; nfsVolumes = { diff --git a/nixos-modules/monitoring/gatus-endpoints.nix b/nixos-modules/monitoring/gatus-endpoints.nix deleted file mode 100644 index b5893cd..0000000 --- a/nixos-modules/monitoring/gatus-endpoints.nix +++ /dev/null @@ -1,230 +0,0 @@ -{ lib, config, machines, ... }: -let - cfg = config.lab.monitoring; - - status = code: "[STATUS] == ${toString code}"; - bodyContains = text: "[BODY] == pat(*${text}*)"; - maxResponseTime = ms: "[RESPONSE_TIME] < ${toString ms}"; - - machineEndpoints = lib.attrsets.mapAttrsToList - (name: machine: { - name = "Host ${name}"; - url = "icmp://${name}.dmz"; - conditions = [ "[RESPONSE_TIME] < 10" ]; - }) - machines; - - otherEndpoints = [ - { - name = "Forgejo"; - url = "https://git.kun.is"; - conditions = [ - (status 200) - (bodyContains "Forgejo: Beyond coding. We forge.") - (maxResponseTime 750) - ]; - } - { - name = "Nextcloud"; - url = "https://cloud.kun.is/status.php"; - conditions = [ - (status 200) - "[BODY].installed == true" - "[BODY].maintenance == false" - "[BODY].needsDbUpgrade == false" - (maxResponseTime 2000) - ]; - } - { - name = "Paperless-ngx"; - url = "https://paperless.kun.is/accounts/login/"; - conditions = [ - (status 200) - (bodyContains "Please sign in.") - (maxResponseTime 750) - ]; - } - { - name = "Radicale"; - url = "https://dav.kun.is/.web/"; - conditions = [ - (status 200) - (bodyContains "Login") - (maxResponseTime 750) - ]; - } - { - name = "FreshRSS"; - url = "https://rss.kun.is/i/"; - conditions = [ - (status 200) - (bodyContains "Login") - (maxResponseTime 750) - ]; - } - { - name = "KitchenOwl"; - url = "https://boodschappen.kun.is/signin"; - conditions = [ - (status 200) - (bodyContains "