1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 23:00:39 +02:00

feat: add immich via oci containers

This commit is contained in:
oddlama 2024-01-20 23:16:43 +01:00
parent d77fcaa826
commit 364073c197
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
15 changed files with 239 additions and 6 deletions

View file

@ -129,8 +129,10 @@
// mkMicrovm "paperless" {
enablePaperlessDataset = true;
}
// mkMicrovm "immich" {
enableStorageDataset = true;
}
#// mkMicrovm "minecraft"
#// mkMicrovm "immich"
#// mkMicrovm "firefly"
#// mkMicrovm "fasten-health"
);

View file

@ -1,19 +1,54 @@
{
pkgs,
config,
nodes,
...
}: let
sentinelCfg = nodes.sentinel.config;
immichDomain = "immich.${sentinelCfg.repo.secrets.local.personalDomain}";
ipImmichMachineLearning = "10.89.0.10";
ipImmichMicroservices = "10.89.0.11";
ipImmichPostgres = "10.89.0.12";
ipImmichRedis = "10.89.0.13";
ipImmichServer = "10.89.0.14";
version = "v1.93.3";
environment = {
DB_DATABASE_NAME = "immich";
DB_HOSTNAME = ipImmichPostgres;
DB_PASSWORD_FILE = config.age.secrets.postgres_password.path;
DB_USERNAME = "postgres";
IMMICH_VERSION = "${version}";
UPLOAD_LOCATION = upload_folder;
IMMICH_SERVER_URL = "http://${ipImmichServer}:3001/";
IMMICH_MACHINE_LEARNING_URL = "http://${ipImmichMachineLearning}:3003";
REDIS_HOSTNAME = ipImmichRedis;
};
upload_folder = "/storage/immich";
pgdata_folder = "/persist/immich/pgdata";
model_folder = "/state/immich/modeldata";
serviceConfig = {
serviceConfig.Restart = "always";
after = ["podman-network-immich-default.service"];
requires = ["podman-network-immich-default.service"];
partOf = ["podman-compose-immich-root.target"];
wantedBy = ["podman-compose-immich-root.target"];
};
in {
meta.wireguard-proxy.sentinel.allowedTCPPorts = [config.services.immich.web_port];
microvm.mem = 1024 * 8;
microvm.vcpu = 20;
meta.wireguard-proxy.sentinel.allowedTCPPorts = [2283];
nodes.sentinel = {
networking.providedDomains.immich = immichDomain;
services.nginx = {
upstreams.immich = {
servers."${config.meta.wireguard.proxy-sentinel.ipv4}:${toString config.services.immich.settings.bind_port}" = {};
servers."${config.meta.wireguard.proxy-sentinel.ipv4}:2283" = {};
extraConfig = ''
zone immich 64k;
keepalive 2;
@ -32,9 +67,156 @@ in {
};
};
services.immich = {
enable = true;
systemd.tmpfiles.settings = {
"10-immich" = {
${upload_folder}.d = {
mode = "0770";
};
${pgdata_folder}.d = {
mode = "0770";
};
${model_folder}.d = {
mode = "0770";
};
};
};
systemd.services.grafana.serviceConfig.RestartSec = "600"; # Retry every 10 minutes
age.secrets.postgres_password.generator.script = "alnum";
# Runtime
virtualisation.podman = {
enable = true;
autoPrune.enable = true;
dockerCompat = true;
};
virtualisation.oci-containers.backend = "podman";
# Containers
virtualisation.oci-containers.containers."immich_machine_learning" = {
image = "ghcr.io/immich-app/immich-machine-learning:${version}";
inherit environment;
volumes = [
"${model_folder}:/cache:rw"
];
log-driver = "journald";
extraOptions = [
"--network-alias=immich-machine-learning"
"--network=immich-default"
"--ip=${ipImmichMachineLearning}"
];
};
systemd.services."podman-immich_machine_learning" = serviceConfig;
virtualisation.oci-containers.containers."immich_microservices" = {
image = "ghcr.io/immich-app/immich-server:${version}";
inherit environment;
volumes = [
"${config.age.secrets.postgres_password.path}:${config.age.secrets.postgres_password.path}:ro"
"/etc/localtime:/etc/localtime:ro"
"${upload_folder}:/usr/src/app/upload:rw"
];
cmd = ["start.sh" "microservices"];
dependsOn = [
"immich_postgres"
"immich_redis"
];
log-driver = "journald";
extraOptions = [
"--network-alias=immich-microservices"
"--network=immich-default"
"--ip=${ipImmichMicroservices}"
];
};
systemd.services."podman-immich_microservices" =
serviceConfig
// {
unitConfig.UpheldBy = [
"podman-immich_postgres.service"
"podman-immich_redis.service"
];
};
virtualisation.oci-containers.containers."immich_postgres" = {
image = "tensorchord/pgvecto-rs:pg14-v0.1.11@sha256:0335a1a22f8c5dd1b697f14f079934f5152eaaa216c09b61e293be285491f8ee";
environment = {
POSTGRES_DB = environment.DB_DATABASE_NAME;
POSTGRES_PASSWORD_FILE = environment.DB_PASSWORD_FILE;
POSTGRES_USER = environment.DB_USERNAME;
};
volumes = [
"${config.age.secrets.postgres_password.path}:${config.age.secrets.postgres_password.path}:ro"
"${pgdata_folder}:/var/lib/postgresql/data:rw"
];
log-driver = "journald";
extraOptions = [
"--network-alias=immich_postgres"
"--network=immich-default"
"--ip=${ipImmichPostgres}"
];
};
systemd.services."podman-immich_postgres" = serviceConfig;
virtualisation.oci-containers.containers."immich_redis" = {
image = "redis:6.2-alpine@sha256:c5a607fb6e1bb15d32bbcf14db22787d19e428d59e31a5da67511b49bb0f1ccc";
log-driver = "journald";
extraOptions = [
"--network-alias=immich_redis"
"--network=immich-default"
"--ip=${ipImmichRedis}"
];
};
systemd.services."podman-immich_redis" = serviceConfig;
virtualisation.oci-containers.containers."immich_server" = {
image = "ghcr.io/immich-app/immich-server:${version}";
inherit environment;
volumes = [
"${config.age.secrets.postgres_password.path}:${config.age.secrets.postgres_password.path}:ro"
"/etc/localtime:/etc/localtime:ro"
"${upload_folder}:/usr/src/app/upload:rw"
];
ports = [
"2283:3001/tcp"
];
cmd = ["start.sh" "immich"];
dependsOn = [
"immich_postgres"
"immich_redis"
];
log-driver = "journald";
extraOptions = [
"--network-alias=immich-server"
"--network=immich-default"
"--ip=${ipImmichServer}"
];
};
systemd.services."podman-immich_server" =
serviceConfig
// {
unitConfig.UpheldBy = [
"podman-immich_postgres.service"
"podman-immich_redis.service"
];
};
# Networks
systemd.services."podman-network-immich-default" = {
path = [pkgs.podman];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "${pkgs.podman}/bin/podman network rm -f immich-default";
};
script = ''
podman network inspect immich-default || podman network create immich-default --opt isolate=true --subnet=10.89.0.0/24
'';
partOf = ["podman-compose-immich-root.target"];
wantedBy = ["podman-compose-immich-root.target"];
};
# Root service
# When started, this will automatically create all resources and start
# the containers. When stopped, this will teardown all resources.
systemd.targets."podman-compose-immich-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
wantedBy = ["multi-user.target"];
};
}

View file

@ -115,6 +115,8 @@ in {
before = ["restic-backups-storage-box-dusk.service"];
};
# Needed so we don't run out of tmpfs space for large backups.
# Technically this could be cleared each boot but whatever.
environment.persistence."/state".directories = [
{
directory = paperlessBackupDir;

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKE+geXK2RVVNwZVoYOuX7pW+6mbgCa9SIghJCdHmbSB

View file

@ -148,6 +148,7 @@ in {
groups.web-sentinel = {};
groups."web-sentinel.adguardhome" = {};
groups."web-sentinel.influxdb" = {};
groups."web-sentinel.immich" = {};
systems.oauth2.web-sentinel = {
displayName = "Web Sentinel";
originUrl = "https://oauth2.${personalDomain}";
@ -156,6 +157,7 @@ in {
supplementaryScopeMaps = {
"web-sentinel.adguardhome" = ["access_adguardhome"];
"web-sentinel.influxdb" = ["access_influxdb"];
"web-sentinel.immich" = ["access_immich"];
};
};
};

View file

@ -84,6 +84,8 @@ in {
RestartSec = "600"; # Retry every 10 minutes
};
# Needed so we don't run out of tmpfs space for large backups.
# Technically this could be cleared each boot but whatever.
environment.persistence."/state".directories = [
{
directory = config.services.vaultwarden.backupDir;

View file

@ -29,5 +29,6 @@
msr = uidGid 980;
fwupd-refresh = uidGid 979;
radicale = uidGid 978;
podman = uidGid 977;
};
}

View file

@ -0,0 +1,9 @@
age-encryption.org/v1
-> X25519 lxcs64hgn5qiaMjFfFKIdS7a4DYzsSIp2rYWu9Sxg1o
DWoXP55lOfYh26BQyMTWtJpZXD6RAYYT4ArCNy2RmPQ
-> piv-p256 xqSe8Q ApSmxT6ujEnuH3c0Avr7g/DGdbSf906OFhOiMvi9ONmt
UmLDT5AJkIc8GgLgaVgS6KWk7d0rf/P29V4l2JU1lgI
-> )-grease p4kI HFcVp
dPSUp6CWnLW6gpi6a2g+mWKIZ+OEYiRvTc6YcSLY
--- 7pImagsw0LryRQOHCqzwJxCQNyoESpJsrztMaUqrwPg
’›Nb­Ç¬øÿ Е7ç�æàÿ™ÔçM³NPþ‡r»û>+8÷zÿŠ��ŸJ×— Ä’o\LWÓs‘Ú³Þz0Þ;öi¼pRiKÛ.w�v¤—K

View file

@ -0,0 +1,10 @@
age-encryption.org/v1
-> X25519 ks4qXV3qPJeADOguclgvlOS/81Wd7fgcVKdlhg3FgzI
PLKauYQ+46t8RSPD73M18RUOL/z4SjikoNsDbL3X/cc
-> piv-p256 xqSe8Q A2xu0dbsgARRnDBak5Cd6YG3JF5zOuZlqzPdbg9lgP2x
+tbb9URbCrPqIWOp0O26ptbXRUh/6koKhdONNz5p494
-> Yy),Z@(\-grease %R <|> I]- G
1t94Jtghka4vBg2VMzDqPO2qwzpovhNT0W+fe0K82obdDaajCa3pfiFz4Nrfbm+7
hsJyVaViVGio7BVDPso
--- 8JU+s4Yn2DCmSHfRx4EPn8pa8RRWTn8BfEkCLhVn+DI
¶‚¤~£¦l¾àñoŒÿLµðÒNâu앵 êzωtÆ5‹Îžà¯c½W0g8,{5à•t²êKíñç>ˆmó’‡…›H×à™¾ë©?Á¹

View file

@ -0,0 +1,11 @@
age-encryption.org/v1
-> X25519 SQp3X/pCRAK0LDysYw/iO5XbD5DknZDqrfYVsF4Wryc
MToFiMkEqhq0uJlDE3peo/1r2eG8SGfYj6XZDcHJHsE
-> piv-p256 xqSe8Q AjwjDiFrzD8Zvc7Xx9fA7WcxG+nsF2mUgmMlFswinh/l
ONrzVVrUpWWfy4on9Vouz3D3VxSYu4Rb2+DnRSyBtWU
-> J)C?2Kps-grease ",
+w4vydh7txIfUxLLwNztvo6nDva4zEfkJJZn2Kbh1agtjfiaqVh9hznQyHjY+bKX
TTro7bJoHrdBOj7RX6CV1BO0w2ToeQ1XnkhZv/8GE2xm3aehsSEFt5AqU8f2ucrt
--- ISE4KQBHYV8vazUMaRG9y8BTag3zVtMN32n3lwiTp48
å† d”ѲT‚AvÈuˆW 9lPé’õFg. T² FS!à€Ú5×Û¤ÂTËo ÷LvΦ¯ž¿,Ú2îåTH7aº!lÕj*GG

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
slaNaddkDDEeC9Y69VTKqAhYJcjc2u0UbbwxNzaZNR4=

View file

@ -0,0 +1,10 @@
age-encryption.org/v1
-> X25519 YIhkI6nWo8Ud/fjZVBXO5g0NOmaXVbmLiFvSLJ/cdFg
4RZpFKtM40Q81tSAIq1xUjMy4GmGeIZ+335KiFf28M8
-> piv-p256 xqSe8Q AuTq/W1xNTEYrBAbLgffA95slATEeMRMUIwuMyicmwcA
QlR1jm1BC/MDfSF82oJibcS5huJx0lRtdbO/dHfIkKE
-> XNC"-grease ~K@0<!HN Di rk 3m~F,
8ORNYpBbKkp5zl6LfrxMk8xS6emyDpR0sUKzqtmXAVLt1Zcq3/FdYDW6c6oJFuNw
Sq1iqnpxXxGnsawE1CT3R+VBzJoe8/pKYB4Zua4
--- 0nVnlPHZ85iPTakrStBzIxuTiexocUWpv8FETdMmDiA
zG¼{ö„ýgžÉb>Àº†ãbKÉg{+¼/³½û0„:Ê\Ã�¤sß’-‚5êjg Jü =�pà6C?©¨è¸Öè¿¯Žø