From ba27b0b51f5fb8bc10d67f4df701b677eff8dbfc Mon Sep 17 00:00:00 2001 From: Felix Buehler Date: Wed, 25 Dec 2024 23:32:02 +0100 Subject: [PATCH] service/photos: migrate to immich from photoprism --- machines/newton/secrets.yaml | 10 +- machines/newton/services.nix | 11 +-- modules/services/default.nix | 2 +- modules/services/photoprism/default.nix | 82 ---------------- modules/services/photos/default.nix | 119 ++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 96 deletions(-) delete mode 100644 modules/services/photoprism/default.nix create mode 100644 modules/services/photos/default.nix diff --git a/machines/newton/secrets.yaml b/machines/newton/secrets.yaml index 01ad005..108552f 100644 --- a/machines/newton/secrets.yaml +++ b/machines/newton/secrets.yaml @@ -15,8 +15,8 @@ nextcloud: password: ENC[AES256_GCM,data:uE507Ij34zJVYnd2YkNCGj8hpFpEM5w=,iv:x8BNCUaAas0poQ/Lo0izZApF6l52xal8DDrClIzWjvk=,tag:sA08dmcVQbKswX9hF/txag==,type:str] nextcloud-exporter: password: ENC[AES256_GCM,data:ziQ/rVJx9NELSQA6/BeniH7joJPnc6Q=,iv:LtZ2Inm0V4ZRv0blRUNfXJOyFY85NkZo+5r31fs0oXM=,tag:5maJ5fkJU+JnbpLGf/MhOg==,type:str] -photoprism: - password: ENC[AES256_GCM,data:FMf/JBsmn4G/EpZQGyEiYivUqw+13Lk=,iv:VEvbbei0Cc8j0J9OH/9cLXNIxvlLF7JsbLRzNVHEAug=,tag:MNHr6TpBsufXc5uGhCIZiw==,type:str] +photos: + secrets: ENC[AES256_GCM,data:eUlyoAx9odHPjuSSL63WFJJntRm77FvcxSzf8+6r6qNGtlnx,iv:IEq+NpZx4JIQ/hDCcNEHh+I2B7tD9BbbB7Y1XyW4yW0=,tag:+Ar83rwchWdaMvTYGHAoDQ==,type:str] grafana: password: ENC[AES256_GCM,data:OaAJs/asyZWIdKLaY7OlXPzoDeL4jaA=,iv:J7NwPmqjDj3d4LEB7DGEGDsPML+EXhvwWy3j6MyueNA=,tag:mPGOT7pi1lH+5Q6Mx+yAGQ==,type:str] sso: @@ -52,8 +52,8 @@ sops: NmNwT3N5UEVabFdLTDhseFRjeVZaWFkKL3HGFqfttU1tXY4OhnIr1ABFsHB0R0CX s6wxb0ilut32ijjtnGXMIIa9y6XsMTpYskTb9FdRP9VnQQGVrMfdew== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-11-13T22:35:33Z" - mac: ENC[AES256_GCM,data:xeI7hSFT/DwZmwuh0as0y6A2vEdf8nXWg+QxEiCR73g0o4TXmOa5+VJG+b1H677WijU3fDTgt+SUU2ZjyaqP+qMzC7hz86gMGdU5Zr9DGp0A+aYTZr5l+bNDB6MHCkLq0hEmdij7qrKZh++PJwtAEFo7/z96PH+t1bi9D2MnhJ8=,iv:6EbbzvOCn50MoHjwRexJj/yJdSXccCJE4b1e12A1KjY=,tag:JJ1o2K8a492uvfV9xnfHTg==,type:str] + lastmodified: "2024-12-17T21:17:38Z" + mac: ENC[AES256_GCM,data:pPuvSlWqiCsNFjAoQOH6/0D5lb9Z7giKCHpz0/kWvbug5K730bpeYSfqvEc01VLb+RV6JugvblwF/SXhMEhe1KmvvGOmWPPCufhw4LEhnLotegKkZ5h1bcKLREEqy3nhSDmqbfELNPWxLOxO/fzJjhBTpuNuWZ0nLIAQP+MidWY=,iv:uQaMI9MJ3SZB7h7W7SRBOC6Ig6yoiATGP4eU/kjoO+Q=,tag:YUvl0Og8ckVIBOlW/Zi/hQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.9.2 diff --git a/machines/newton/services.nix b/machines/newton/services.nix index 090d061..2576535 100644 --- a/machines/newton/services.nix +++ b/machines/newton/services.nix @@ -21,7 +21,7 @@ in "freshrss/password" = { owner = config.users.users.freshrss.name; }; - "photoprism/password" = { }; + "photos/secrets" = { }; "grafana/password" = { owner = config.users.users.grafana.name; }; @@ -98,14 +98,9 @@ in enable = true; }; # self-hosted photo gallery - photoprism = { + photos = { enable = true; - passwordFile = secrets."photoprism/password".path; - originalsPath = "/data/photos"; - settings = { - PHOTOPRISM_ADMIN_USER = "felix"; - PHOTOPRISM_SPONSOR = "true"; - }; + secretsFile = secrets."photos/secrets".path; }; ssh-server = { enable = true; diff --git a/modules/services/default.nix b/modules/services/default.nix index 48f0da1..c127919 100644 --- a/modules/services/default.nix +++ b/modules/services/default.nix @@ -31,7 +31,7 @@ ./octoprint ./paperless ./passworts - ./photoprism + ./photos ./prometheus ./promtail ./prowlarr diff --git a/modules/services/photoprism/default.nix b/modules/services/photoprism/default.nix deleted file mode 100644 index 6ba5718..0000000 --- a/modules/services/photoprism/default.nix +++ /dev/null @@ -1,82 +0,0 @@ -# self-hosted photo gallery -{ config, lib, ... }: -let - cfg = config.my.services.photoprism; - inherit (config.networking) domain; -in -{ - options.my.services.photoprism = { - enable = lib.mkEnableOption (lib.mdDoc "Photoprism web server"); - - passwordFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = lib.mdDoc '' - Admin password file. - ''; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 2342; - description = lib.mdDoc '' - Web interface port. - ''; - }; - - originalsPath = lib.mkOption { - type = lib.types.path; - default = null; - example = "/data/photos"; - description = lib.mdDoc '' - Storage path of your original media files (photos and videos) - ''; - }; - - settings = lib.mkOption { - type = lib.types.attrsOf lib.types.str; - default = { }; - description = lib.mdDoc '' - Extra photoprism config options. See [the getting-started guide](https://docs.photoprism.app/getting-started/config-options/) for available options. - ''; - example = { - PHOTOPRISM_DEFAULT_LOCALE = "de"; - PHOTOPRISM_ADMIN_USER = "root"; - }; - }; - }; - - config = lib.mkIf cfg.enable { - services.photoprism = { - enable = true; - inherit (cfg) - passwordFile - port - originalsPath - settings - ; - }; - - my.services.nginx.virtualHosts = [ - { - subdomain = "photos"; - inherit (cfg) port; - extraConfig = { - locations."/" = { - proxyWebsockets = true; - }; - }; - } - ]; - - webapps.apps.photoprism = { - dashboard = { - name = "Photos"; - category = "media"; - icon = "image"; - url = "https://photos.${domain}/library/login"; - method = "get"; - }; - }; - }; -} diff --git a/modules/services/photos/default.nix b/modules/services/photos/default.nix new file mode 100644 index 0000000..1842ce4 --- /dev/null +++ b/modules/services/photos/default.nix @@ -0,0 +1,119 @@ +# self-hosted photo gallery +{ config, lib, ... }: +let + cfg = config.my.services.photos; + inherit (config.networking) domain; +in +{ + options.my.services.photos = { + enable = lib.mkEnableOption (lib.mdDoc "Photos gallery"); + + secretsFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = lib.mdDoc '' + pass secrets + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 2283; + description = lib.mdDoc '' + Web interface port. + ''; + }; + + settings = lib.mkOption { + type = lib.types.anything; + default = { }; + description = '' + see . + ''; + }; + + path = lib.mkOption { + type = lib.types.path; + default = null; + example = "/data/photos"; + description = lib.mdDoc '' + Storage path of your original media files (photos and videos) + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.immich = { + enable = true; + # mediaLocation = path; + inherit (cfg) + secretsFile + port + ; + settings = { + ffmpeg.transcode = "disabled"; + server.externalDomain = "https://photos.${domain}"; + } // cfg.settings; + environment = { + IMMICH_TELEMETRY_INCLUDE = "all"; + IMMICH_API_METRICS_PORT = toString (cfg.port + 1); + IMMICH_MICROSERVICES_METRICS_PORT = toString (cfg.port + 2); + }; + }; + + services.prometheus = { + scrapeConfigs = [ + { + job_name = "immich"; + static_configs = [ + { + targets = [ "127.0.0.1:${toString (cfg.port + 1)}" ]; + labels = { + instance = config.networking.hostName; + service = "api"; + }; + } + { + targets = [ "127.0.0.1:${toString (cfg.port + 2)}" ]; + labels = { + instance = config.networking.hostName; + service = "server"; + }; + } + ]; + } + ]; + }; + + my.services.nginx.virtualHosts = [ + { + subdomain = "photos"; + inherit (cfg) port; + extraConfig = { + locations."/" = { + proxyWebsockets = true; + extraConfig = '' + # Allow large file uploads + client_max_body_size 1G; + + # Configure timeout + proxy_read_timeout 600s; + proxy_send_timeout 600s; + send_timeout 600s; + ''; + }; + }; + } + ]; + + webapps.apps.photos = { + dashboard = { + name = "Photos"; + category = "media"; + icon = "image"; + url = "https://photos.${domain}"; + method = "get"; + }; + }; + }; +}