From bd812ddae0f164659018cbfebc12bc6d4c9fb0bb Mon Sep 17 00:00:00 2001 From: mjallen18 Date: Fri, 20 Sep 2024 20:44:16 -0500 Subject: [PATCH] immich --- hosts/desktop/home.nix | 1 + hosts/nas/apps.nix | 2 + hosts/nas/sops.nix | 19 +++ modules/apps/immich/default.nix | 210 ++++++++++++++++++++++++++++++++ modules/apps/immich/options.nix | 7 ++ modules/default.nix | 1 + secrets/secrets.yaml | 11 +- 7 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 modules/apps/immich/default.nix create mode 100644 modules/apps/immich/options.nix diff --git a/hosts/desktop/home.nix b/hosts/desktop/home.nix index 00c9c7e..d0877e4 100644 --- a/hosts/desktop/home.nix +++ b/hosts/desktop/home.nix @@ -63,6 +63,7 @@ in age bottles chromium + compose2nix deadnix discord fastfetch diff --git a/hosts/nas/apps.nix b/hosts/nas/apps.nix index f0e87bb..e1d3e4f 100644 --- a/hosts/nas/apps.nix +++ b/hosts/nas/apps.nix @@ -18,6 +18,8 @@ free-games-claimer.enable = true; + immich.enable = true; + jackett.enable = true; jellyfin.enable = true; diff --git a/hosts/nas/sops.nix b/hosts/nas/sops.nix index 8d01ac9..737b9f6 100644 --- a/hosts/nas/sops.nix +++ b/hosts/nas/sops.nix @@ -41,6 +41,25 @@ "${config.sops.placeholder."jallen-nas/nextcloud/smtppassword"}" ''; + sops.secrets."jallen-nas/immich/db-password" = { + restartUnits = [ "podman-immich-postgres.service" ]; + }; + sops.secrets."jallen-nas/immich/db-name" = { + restartUnits = [ "podman-immich-postgres.service" ]; + }; + sops.secrets."jallen-nas/immich/db-user" = { + restartUnits = [ "podman-immich-postgres.service" ]; + }; + sops.secrets."jallen-nas/immich/server-db-password" = { + restartUnits = [ "podman-immich-server.service" ]; + }; + sops.secrets."jallen-nas/immich/server-db-name" = { + restartUnits = [ "podman-immich-server.service" ]; + }; + sops.secrets."jallen-nas/immich/server-db-user" = { + restartUnits = [ "podman-immich-server.service" ]; + }; + # Permission modes are in octal representation (same as chmod), # the digits represent: user|group|others # 7 - full (rwx) diff --git a/modules/apps/immich/default.nix b/modules/apps/immich/default.nix new file mode 100644 index 0000000..e01b033 --- /dev/null +++ b/modules/apps/immich/default.nix @@ -0,0 +1,210 @@ +{ lib, config, pkgs, ... }: +with lib; +let + cfg = config.nas-apps.immich; +in +{ + imports = [ ./options.nix ]; + + config = mkIf cfg.enable { + + virtualisation.oci-containers.containers."immich-machine-learning" = { + image = "ghcr.io/immich-app/immich-machine-learning:pr-12826-cuda"; + volumes = [ + "/media/nas/ssd/nix-app-data/immich/model-cache:/cache:rw" + ]; + log-driver = "journald"; + extraOptions = [ + "--network-alias=immich-machine-learning" + "--network=immich_default" + "--device=nvidia.com/gpu=0" + ]; + ports = [ + "3003:3003" + ]; + environment = { + PUID = "911"; + PGID = "1000"; + }; + }; + + systemd.services."podman-immich-machine-learning" = { + serviceConfig = { + Restart = lib.mkOverride 500 "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" + ]; + }; + + virtualisation.oci-containers.containers."immich-postgres" = { + image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0"; + environment = { + "POSTGRES_INITDB_ARGS" = "--data-checksums"; + PUID = "911"; + PGID = "1000"; + }; + environmentFiles = [ + config.sops.secrets."jallen-nas/immich/db-password".path + config.sops.secrets."jallen-nas/immich/db-name".path + config.sops.secrets."jallen-nas/immich/db-user".path + ]; + volumes = [ + "/media/nas/ssd/nix-app-data/immich/postgres:/var/lib/postgresql/data:rw" + ]; + ports = [ + "5433:5432" + ]; + cmd = [ "postgres" "-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" ]; + log-driver = "journald"; + extraOptions = [ + "--health-cmd=pg_isready --dbname=$DB_DATABASE_NAME --username=$DB_USERNAME || exit 1; Chksum=\"$(psql --dbname=$DB_DATABASE_NAME --username=$DB_USERNAME --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')\"; echo \"checksum failure count is $Chksum\"; [ \"$Chksum\" = '0' ] || exit 1" + "--health-interval=5m0s" + "--health-start-period=5m0s" + "--network-alias=database" + "--network=immich_default" + ]; + }; + + systemd.services."podman-immich-postgres" = { + serviceConfig = { + Restart = lib.mkOverride 500 "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" + ]; + }; + + virtualisation.oci-containers.containers."immich-redis" = { + image = "docker.io/redis:6.2-alpine@sha256:2d1463258f2764328496376f5d965f20c6a67f66ea2b06dc42af351f75248792"; + log-driver = "journald"; + extraOptions = [ + "--health-cmd=redis-cli ping || exit 1" + "--network-alias=redis" + "--network=immich_default" + ]; + ports = [ + "6381:6379" + ]; + environment = { + PUID = "911"; + PGID = "1000"; + }; + }; + + systemd.services."podman-immich-redis" = { + serviceConfig = { + Restart = lib.mkOverride 500 "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" + ]; + }; + + virtualisation.oci-containers.containers."immich-server" = { + image = "ghcr.io/imagegenius/immich:latest"; + volumes = [ + "/media/nas/ssd/nix-app-data/immich/upload:/usr/src/app/upload:rw" + "/media/nas/ssd/nix-app-data/immich/config:/config" + "/media/nas/main/photos:/photos" + "/media/nas/ssd/nix-app-data/immich/libraries:/libraries" + "/etc/localtime:/etc/localtime:ro" + ]; + ports = [ + "5555:8080/tcp" + ]; + dependsOn = [ + "immich-postgres" + "immich-redis" + ]; + log-driver = "journald"; + extraOptions = [ + "--network-alias=immich-server" + "--network=immich_default" + "--device=nvidia.com/gpu=0" + ]; + environment = { + PUID = "911"; + PGID = "1000"; + DB_HOSTNAME = "10.0.1.18"; + DB_PORT = "5433"; + REDIS_HOSTNAME = "10.0.1.18"; + REDIS_PORT = "6381"; + }; + environmentFiles = [ + config.sops.secrets."jallen-nas/immich/server-db-password".path + config.sops.secrets."jallen-nas/immich/server-db-name".path + config.sops.secrets."jallen-nas/immich/server-db-user".path + ]; + }; + + systemd.services."podman-immich-server" = { + serviceConfig = { + Restart = lib.mkOverride 500 "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" + ]; + }; + + systemd.services."podman-network-immich_default" = { + path = [ pkgs.podman ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "podman network rm -f immich_default"; + }; + script = '' + podman network inspect immich_default || podman network create immich_default + ''; + 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" ]; + }; + }; +} diff --git a/modules/apps/immich/options.nix b/modules/apps/immich/options.nix new file mode 100644 index 0000000..83ac168 --- /dev/null +++ b/modules/apps/immich/options.nix @@ -0,0 +1,7 @@ +{ lib, ... }: +with lib; +{ + options.nas-apps.immich = { + enable = mkEnableOption "immich docker service"; + }; +} diff --git a/modules/default.nix b/modules/default.nix index e4360e3..e2f54fa 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -8,6 +8,7 @@ ./apps/deluge ./apps/discover-wrapped ./apps/free-games-claimer + ./apps/immich ./apps/jackett ./apps/jellyfin ./apps/jellyseerr diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 261f734..d1ac708 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -14,6 +14,13 @@ jallen-nas: smtppassword: ENC[AES256_GCM,data:AIn3HJ3oX90nzcmSLSIeizqL1w==,iv:EyIgk3mxJ1Pn9Gff6ia6c2ekreSFGUWDbLrtC/meMyI=,tag:LvkT98sSOVDV+mxMyJKnbQ==,type:str] manyfold: secretkeybase: ENC[AES256_GCM,data:b+fgTrtnZcp34DOQ0dtKc6bX6/dm9j0o3QJr,iv:e4hOwgTFCXVokGqhwKsYHt5IQgtaKcMmEqvDoMly5aI=,tag:E8gFiOuozA4T1mmcgXfbDg==,type:str] + immich: + db-password: ENC[AES256_GCM,data:QOCPlkJX3o6hjJviYmu/HCwTchLVkP9Y5QWVjXs=,iv:JauPXpgvQcxUeBzDZ/dtc0fOScOmxo58uPNNWAF+e+Y=,tag:Oc+xUcD25P6lAOnoeNtxQA==,type:str] + db-name: ENC[AES256_GCM,data:UNJGb5TJ4G4ov0wUPdYLLsIx,iv:70RBulQkrPixRbOf1owSDq9pjxZGh91VW5WorUZ0ta4=,tag:hY2kUXTEXA0rjxbMGo82AQ==,type:str] + db-user: ENC[AES256_GCM,data:0hFTUW7tKfjEFDLqrrv20GMsQHFfNotp,iv:5SUb36awCbvQ2U2K8pNUIDIbTnoA4pcy1Y128sSpmMk=,tag:lQ5sYcBCicyvsaXrWk7v4Q==,type:str] + server-db-password: ENC[AES256_GCM,data:NtNMYemg+Se0CKT7yF7Yqso+33gCZn4=,iv:9lp0GoQY+I+2u/O/PFEu97H++HXDWgL1bxlOYqWfzyY=,tag:kILw1T9Ne7nSoIET4SSrOA==,type:str] + server-db-name: ENC[AES256_GCM,data:bMXo9Jds5l0p9eYEPmquHQ8wwxbM+c0=,iv:fkb0P9uD9oMTOl5OuK7QDOxgJVfquKLaMfoPhRTwsAk=,tag:2Kat49n3odcVhn34c7+rig==,type:str] + server-db-user: ENC[AES256_GCM,data:od8C91VJVK/cWCl824gCRqnOAC7mGA==,iv:mHJnrpKoD3c0z/XuUwFMHm8pDrOHoVzIloOS2U4IHzg=,tag:xE44Svdg/RWTe1i9Q43QQQ==,type:str] desktop: matt_password: ENC[AES256_GCM,data:z/Jjzr+/PREpNEQsAVl4soeKAwW3sdteIqjhZT2txQDiR0FvGvEBoE/aYCM9NS7XSCgTeTuOqgBGfq4xDLc5/ZBAl7KoGHmKIQ==,iv:qVONkw8PDI2ydqybqGIU2XFq4+qC1BeXnfwxbxbWBww=,tag:eYOD2EoBn9XMiYOaBDFlRw==,type:str] hass_token: ENC[AES256_GCM,data:un4uyUPcr6g8IIWlXvTCpQ5hXms9FZxaVQz+fk1HMNRdfToTI7OLv8XyYOZ4NOZk5OJcLUUcu2S6zDKL0nc6PUqKD/8X8Rc4wVxEPoAZHiH3EBwuj3LSQac9m2Qlgs17vdfRGkpCt52h5ayPwItop1eb222MXHnQWPsslWT7RIN+kuzQ8prj7MU3ag6lqH8dDZjYQutskF1VkXWolQZkAG8gGZPK+C0BXB5Kxlpx4nYD/pQs2eKr,iv:qR5Jn4QcDISEcLzwmPa7hj9+u5JcQuzdB0qLxlYeK8s=,tag:tSN0CaQz6WsFSw+0fVrDYA==,type:str] @@ -50,8 +57,8 @@ sops: UGhsN2N0Mjl3UEJvUVlGRlJiN05WaUkKW37lU4G4CLTo6JoHC2OyhKsG/FuO+BiN pzlVJwzRnmAqwklRbc6RMbQLl2EQrp6KQcgYsUxCMH9OQ/9WJ98dxQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-09-04T16:52:28Z" - mac: ENC[AES256_GCM,data:cyM8+Y6p83pd/S3t+/EhA7LZPeMtzCjnD8NUL5wXLnu1AVWraAg8Sx+P3wKj/iy0pTkKZ5d54xUrZeN7mevOvU4LZ9xJXDRIFf0jVUic/XSS5r56w9mG1Z2pCMDdR2wCq36Vx7w4lgMHUcjLc7ca8w256Ky42jLnBY6s1pr38Vs=,iv:4oj8PQA/0wSXmWqTrru+GHF2W6UUfHXHib7Zo/7xNCw=,tag:y7V30iBNuhjEj2jURdCHIg==,type:str] + lastmodified: "2024-09-21T01:05:24Z" + mac: ENC[AES256_GCM,data:pXhGu8BXKulc4wqmQY6JFUhM5X3rm8W4/jR/DQ33+7E8Yuf9zIfDXOdZ/aIwKkOeF/lxKG4ca8knwZBxpuApH8NKzjVW3cMESM0vK+N2EsoNjv08HhDtnlc9vcGKAeBXLqZDxcbHNnd0P8mCDgJM3Ybl4pCH310mqtsSvoEtByE=,iv:tzFlOp/5775lj2yKfPjEan/G98H5FO0vqENoVK1qDdQ=,tag:2tIl8WGH/3NCeP85y/4lUA==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.0