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" {
|
// mkMicrovm "paperless" {
|
||||||
enablePaperlessDataset = true;
|
enablePaperlessDataset = true;
|
||||||
}
|
}
|
||||||
|
// mkMicrovm "immich" {
|
||||||
|
enableStorageDataset = true;
|
||||||
|
}
|
||||||
#// mkMicrovm "minecraft"
|
#// mkMicrovm "minecraft"
|
||||||
#// mkMicrovm "immich"
|
|
||||||
#// mkMicrovm "firefly"
|
#// mkMicrovm "firefly"
|
||||||
#// mkMicrovm "fasten-health"
|
#// mkMicrovm "fasten-health"
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,19 +1,54 @@
|
||||||
{
|
{
|
||||||
|
pkgs,
|
||||||
config,
|
config,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
sentinelCfg = nodes.sentinel.config;
|
sentinelCfg = nodes.sentinel.config;
|
||||||
immichDomain = "immich.${sentinelCfg.repo.secrets.local.personalDomain}";
|
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 {
|
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 = {
|
nodes.sentinel = {
|
||||||
networking.providedDomains.immich = immichDomain;
|
networking.providedDomains.immich = immichDomain;
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
upstreams.immich = {
|
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 = ''
|
extraConfig = ''
|
||||||
zone immich 64k;
|
zone immich 64k;
|
||||||
keepalive 2;
|
keepalive 2;
|
||||||
|
@ -32,9 +67,156 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.immich = {
|
systemd.tmpfiles.settings = {
|
||||||
enable = true;
|
"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"];
|
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 = [
|
environment.persistence."/state".directories = [
|
||||||
{
|
{
|
||||||
directory = paperlessBackupDir;
|
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 = {};
|
||||||
groups."web-sentinel.adguardhome" = {};
|
groups."web-sentinel.adguardhome" = {};
|
||||||
groups."web-sentinel.influxdb" = {};
|
groups."web-sentinel.influxdb" = {};
|
||||||
|
groups."web-sentinel.immich" = {};
|
||||||
systems.oauth2.web-sentinel = {
|
systems.oauth2.web-sentinel = {
|
||||||
displayName = "Web Sentinel";
|
displayName = "Web Sentinel";
|
||||||
originUrl = "https://oauth2.${personalDomain}";
|
originUrl = "https://oauth2.${personalDomain}";
|
||||||
|
@ -156,6 +157,7 @@ in {
|
||||||
supplementaryScopeMaps = {
|
supplementaryScopeMaps = {
|
||||||
"web-sentinel.adguardhome" = ["access_adguardhome"];
|
"web-sentinel.adguardhome" = ["access_adguardhome"];
|
||||||
"web-sentinel.influxdb" = ["access_influxdb"];
|
"web-sentinel.influxdb" = ["access_influxdb"];
|
||||||
|
"web-sentinel.immich" = ["access_immich"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,6 +84,8 @@ in {
|
||||||
RestartSec = "600"; # Retry every 10 minutes
|
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 = [
|
environment.persistence."/state".directories = [
|
||||||
{
|
{
|
||||||
directory = config.services.vaultwarden.backupDir;
|
directory = config.services.vaultwarden.backupDir;
|
||||||
|
|
|
@ -29,5 +29,6 @@
|
||||||
msr = uidGid 980;
|
msr = uidGid 980;
|
||||||
fwupd-refresh = uidGid 979;
|
fwupd-refresh = uidGid 979;
|
||||||
radicale = uidGid 978;
|
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