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:
parent
d77fcaa826
commit
364073c197
15 changed files with 239 additions and 6 deletions
|
@ -129,8 +129,10 @@
|
|||
// mkMicrovm "paperless" {
|
||||
enablePaperlessDataset = true;
|
||||
}
|
||||
// mkMicrovm "immich" {
|
||||
enableStorageDataset = true;
|
||||
}
|
||||
#// mkMicrovm "minecraft"
|
||||
#// mkMicrovm "immich"
|
||||
#// mkMicrovm "firefly"
|
||||
#// mkMicrovm "fasten-health"
|
||||
);
|
||||
|
|
|
@ -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"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
1
hosts/sire/secrets/immich/host.pub
Normal file
1
hosts/sire/secrets/immich/host.pub
Normal file
|
@ -0,0 +1 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKE+geXK2RVVNwZVoYOuX7pW+6mbgCa9SIghJCdHmbSB
|
|
@ -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"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -29,5 +29,6 @@
|
|||
msr = uidGid 980;
|
||||
fwupd-refresh = uidGid 979;
|
||||
radicale = uidGid 978;
|
||||
podman = uidGid 977;
|
||||
};
|
||||
}
|
||||
|
|
Binary file not shown.
9
secrets/generated/sire-immich/postgres_password.age
Normal file
9
secrets/generated/sire-immich/postgres_password.age
Normal 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
|
|
@ -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×à™¾ë©?Á¹
|
11
secrets/generated/sire-immich/telegraf-influxdb-token.age
Normal file
11
secrets/generated/sire-immich/telegraf-influxdb-token.age
Normal 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ˆW9lPé’õFg. T² FS!à€Ú5×Û¤ÂTËo ÷LvΦ¯ž¿,Ú2îåTH7aº!lÕj*GG
|
Binary file not shown.
BIN
secrets/wireguard/proxy-sentinel/keys/sire-immich.age
Normal file
BIN
secrets/wireguard/proxy-sentinel/keys/sire-immich.age
Normal file
Binary file not shown.
1
secrets/wireguard/proxy-sentinel/keys/sire-immich.pub
Normal file
1
secrets/wireguard/proxy-sentinel/keys/sire-immich.pub
Normal file
|
@ -0,0 +1 @@
|
|||
slaNaddkDDEeC9Y69VTKqAhYJcjc2u0UbbwxNzaZNR4=
|
|
@ -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êjgJü =�pà6C?©¨è¸Öè¿¯Žø
|
Loading…
Add table
Add a link
Reference in a new issue