Make permanent Immich deployment

This commit is contained in:
Pim Kunis 2024-06-16 16:46:08 +02:00
parent 726beabb9c
commit 2efe24dac9
6 changed files with 253 additions and 253 deletions

View file

@ -18,6 +18,7 @@ let
./blog.nix ./blog.nix
./attic.nix ./attic.nix
./atuin.nix ./atuin.nix
./immich.nix
# ./argo.nix # ./argo.nix
# ./minecraft.nix # ./minecraft.nix
]; ];

View file

@ -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 = resources.nodes =
@ -79,15 +69,5 @@
}) })
machinesWithKubernetesLabels; machinesWithKubernetesLabels;
}; };
lab.ingresses.immich-test = {
host = "immich.kun.is";
entrypoint = "localsecure";
service = {
name = "immich-server";
portName = "http";
};
};
}; };
} }

246
kubenix-modules/immich.nix Normal file
View file

@ -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";
};
};
}

View file

@ -25,9 +25,10 @@
bazarr.storage = "25Mi"; bazarr.storage = "25Mi";
attic.storage = "15Gi"; attic.storage = "15Gi";
attic-db.storage = "150Mi"; attic-db.storage = "150Mi";
immich-test.storage = "10Gi";
atuin.storage = "600Mi"; atuin.storage = "600Mi";
atuin-db.storage = "100Mi"; atuin-db.storage = "100Mi";
immich.storage = "50Gi";
immich-db.storage = "1Gi";
}; };
nfsVolumes = { nfsVolumes = {

View file

@ -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 "<title>KitchenOwl</title>")
(maxResponseTime 750)
];
}
{
name = "HedgeDoc";
url = "https://md.kun.is/";
conditions = [
(status 200)
(bodyContains "The best platform to write and share markdown.")
(maxResponseTime 750)
];
}
{
name = "Cyberchef";
url = "https://cyberchef.kun.is/";
conditions = [
(status 200)
(bodyContains "CyberChef - The Cyber Swiss Army Knife")
(maxResponseTime 750)
];
}
{
name = "Pi-hole";
url = "https://pihole.kun.is:444/admin/login.php";
conditions = [
(status 200)
(bodyContains "Log in")
(maxResponseTime 750)
];
}
{
name = "Inbucket";
url = "https://inbucket.kun.is:444/";
conditions = [
(status 200)
(bodyContains "<title>Inbucket</title>")
(maxResponseTime 750)
];
}
{
name = "kms";
url = "tcp://kms.kun.is:1688";
conditions = [
"[CONNECTED] == true"
];
}
{
name = "Bazarr";
url = "https://bazarr.kun.is:444/system/status";
conditions = [
(status 200)
(bodyContains "<title>Bazarr</title>")
(maxResponseTime 750)
];
}
{
name = "Sonarr";
url = "https://sonarr.kun.is:444/system/status";
conditions = [
(status 200)
(bodyContains "<title>Sonarr</title>")
(maxResponseTime 750)
];
}
{
name = "Radarr";
url = "https://radarr.kun.is:444/system/status";
conditions = [
(status 200)
(bodyContains "<title>Radarr</title>")
(maxResponseTime 750)
];
}
{
name = "Jellyfin";
url = "https://media.kun.is/web/index.html#!/login.html?";
conditions = [
(status 200)
(bodyContains "<title>Jellyfin</title>")
(maxResponseTime 750)
];
}
{
name = "Jellyseerr";
url = "https://jellyseerr.kun.is:444/login";
conditions = [
(status 200)
(bodyContains "Sign in to continue")
(maxResponseTime 750)
];
}
{
name = "Prowlarr";
url = "https://prowlarr.kun.is:444/system/status";
conditions = [
(status 200)
(bodyContains "<title>Prowlarr</title>")
(maxResponseTime 750)
];
}
{
name = "Transmission";
url = "https://transmission.kun.is:444/transmission/web/";
conditions = [
(status 200)
(bodyContains "Transmission Web Interface")
(maxResponseTime 750)
];
}
{
name = "Syncthing";
url = "https://sync.kun.is:444/";
conditions = [
(status 401)
(maxResponseTime 750)
];
}
{
name = "Traefik";
url = "https://traefik.kun.is:444/dashboard/#/";
conditions = [
(status 200)
(bodyContains "<title>Traefik</title>")
(maxResponseTime 750)
];
}
{
name = "BIND";
url = "192.168.30.7";
dns = {
query-type = "SOA";
query-name = "kun.is";
};
conditions = [
"[DNS_RCODE] == NOERROR"
];
}
{
name = "Pi-hole DNS";
url = "192.168.30.8";
dns = {
query-type = "SOA";
query-name = "kun.is";
};
conditions = [
"[DNS_RCODE] == NOERROR"
];
}
];
in
{
config = lib.mkIf cfg.server.enable {
services.gatus.settings.endpoints = map
(endpoint: endpoint // {
interval = "5m";
alerts = [{ type = "email"; }];
})
(machineEndpoints ++ otherEndpoints);
};
}

View file

@ -23,6 +23,8 @@ attic:
atuin: atuin:
databaseURL: ENC[AES256_GCM,data:IBmND/J2Pzz+CDCeNBRtErxSQIi8PeUuLGN4rIXKSLwZ6TGJKcNmbuxQDvWkCnI1crx3oak=,iv:wc3G/00oIuaiGF4mA2vIm35wFGxT0a3Ox3k1C9YBAx4=,tag:MQPcsR+vrD85DttYYi6jUw==,type:str] databaseURL: ENC[AES256_GCM,data:IBmND/J2Pzz+CDCeNBRtErxSQIi8PeUuLGN4rIXKSLwZ6TGJKcNmbuxQDvWkCnI1crx3oak=,iv:wc3G/00oIuaiGF4mA2vIm35wFGxT0a3Ox3k1C9YBAx4=,tag:MQPcsR+vrD85DttYYi6jUw==,type:str]
databasePassword: ENC[AES256_GCM,data:qfWOmFfBOuguOfb1Z51F527ic3o=,iv:4Yx5rpzZHzRlfvZydcBNFRStEO0P4uIcjDqxgRgQmHE=,tag:pbJXcUdvul7nCrXQ9ylAdQ==,type:str] databasePassword: ENC[AES256_GCM,data:qfWOmFfBOuguOfb1Z51F527ic3o=,iv:4Yx5rpzZHzRlfvZydcBNFRStEO0P4uIcjDqxgRgQmHE=,tag:pbJXcUdvul7nCrXQ9ylAdQ==,type:str]
immich:
databasePassword: ENC[AES256_GCM,data:fZtGYiHOhYjdzBxaSdnstjlOAJE=,iv:YV+o4upajDHtwWSU6Z9h3Ncl9fXbo65KT6YMqlh2evY=,tag:BWLRc3bdnS9M70jC3SZXlA==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -47,8 +49,8 @@ sops:
aHpYZ2VtdVBVTkxZbGFOYzRpbGltZHMKJs4E+CsthuzQZqA0Yip4G/1XK4SuoiRP aHpYZ2VtdVBVTkxZbGFOYzRpbGltZHMKJs4E+CsthuzQZqA0Yip4G/1XK4SuoiRP
Lo65L33lfNibdSOeIygqnyo6GBwjD52TcNQpvzkVbr3M3hWlJs8wCA== Lo65L33lfNibdSOeIygqnyo6GBwjD52TcNQpvzkVbr3M3hWlJs8wCA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-06-15T18:55:03Z" lastmodified: "2024-06-16T14:30:15Z"
mac: ENC[AES256_GCM,data:THDaTY91n6nTZoDFzSOL+6m0gi+jthNJsjr8sqDO9dRyuezuMj2cJcmfZQZrhxsXIeyr+yHkCxNuqvhpVkH1k/rfQQXbOLXAfdioJepTqr/6zjMy7lr/AoBgzNlcwicE8YVevO34BNE83QqfN3GfPdDfNlE0sku9k2Eda3W61SU=,iv:VI+7Kvf3p6J3l+XAFaadplNWl6t0Xqxoy5q/1zbvp0A=,tag:JeVv8d1GXxPKfdJZ4nbGRQ==,type:str] mac: ENC[AES256_GCM,data:dGFqNLSfoWvQ88l9ZEchJkRGmKyE0Ullactg+45t6gT9qzS9Y6crV1VOZEkfv6CabDrXWsq8cgadW9bD1z+vmpnRGdnsFIzYycw36y+ibiJ7ItCkT5KO86W8EsalzSxdy+Ac89Jp3Fv1xWzWcxKAO6jz0zluv6CrUl3kk5wTfBI=,iv:tdWY4pjE6ux5rbsYG5qTqnRDjspsIXAuWXqEnR6j4qI=,tag:Sw6fdDVKB8L1Me6Sa67O6Q==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.8.1 version: 3.8.1