Loading nixos/modules/services/web-apps/immich.nix +44 −2 Original line number Diff line number Diff line Loading @@ -10,6 +10,10 @@ let isPostgresUnixSocket = lib.hasPrefix "/" cfg.database.host; isRedisUnixSocket = lib.hasPrefix "/" cfg.redis.host; # convert a Nix attribute path to jq object identifier-index: # https://jqlang.org/manual/#object-identifier-index attrPathToIndex = attrPath: "." + lib.concatStringsSep "." attrPath; commonServiceConfig = { Type = "simple"; Restart = "on-failure"; Loading Loading @@ -147,6 +151,27 @@ in ); }; secretSettings = mkOption { default = { }; description = '' Secrets to to be added to the JSON file generated from {option}`settings`, read from files. ''; example = lib.literalExpression '' { notifications.smtp.transport.password = "/path/to/secret"; oauth.clientSecret = "/path/to/other/secret"; } ''; type = let inherit (types) attrsOf either path; recursiveType = either (attrsOf recursiveType) path // { description = "nested " + (attrsOf path).description; }; in recursiveType; }; machine-learning = { enable = mkEnableOption "immich's machine-learning functionality to detect faces and search for objects" Loading Loading @@ -352,8 +377,8 @@ in IMMICH_MEDIA_LOCATION = cfg.mediaLocation; IMMICH_MACHINE_LEARNING_URL = "http://localhost:3003"; } // lib.optionalAttrs (cfg.settings != null) { IMMICH_CONFIG_FILE = "${format.generate "immich.json" cfg.settings}"; // lib.optionalAttrs (cfg.settings != null || cfg.settingsFile != null) { IMMICH_CONFIG_FILE = "/run/immich/config.json"; }; services.immich.machine-learning.environment = { Loading Loading @@ -382,7 +407,24 @@ in postgresqlPackage ]; preStart = mkIf (cfg.settings != null) ( '' cat '${format.generate "immich-config.json" cfg.settings}' > /run/immich/config.json '' + lib.concatStrings ( lib.mapAttrsToListRecursive (attrPath: _: '' tmp="$(mktemp)" ${lib.getExe pkgs.jq} --rawfile secret "$CREDENTIALS_DIRECTORY/${attrPathToIndex attrPath}" \ '${attrPathToIndex attrPath} = $secret' /run/immich/config.json > "$tmp" mv "$tmp" /run/immich/config.json '') cfg.secretSettings ) ); serviceConfig = commonServiceConfig // { LoadCredential = lib.mapAttrsToListRecursive ( attrPath: file: "${attrPathToIndex attrPath}:${file}" ) cfg.secretSettings; ExecStart = lib.getExe cfg.package; EnvironmentFile = mkIf (cfg.secretsFile != null) cfg.secretsFile; Slice = "system-immich.slice"; Loading nixos/tests/web-apps/immich.nix +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,15 @@ services.immich = { enable = true; environment.IMMICH_LOG_LEVEL = "verbose"; settings.backup.database = { enabled = true; cronExpression = "invalid"; }; secretSettings = { backup.database.cronExpression = "${pkgs.writeText "cron" "0 02 * * *"}"; # thanks to LoadCredential files only readable by root should work notifications.smtp.transport.password = "/etc/shadow"; }; }; }; Loading @@ -25,6 +34,8 @@ machine.wait_for_unit("immich-server.service") machine.succeed("stat -L -c '%a %U %G' /run/immich/config.json | grep '600 immich immich'") machine.wait_for_open_port(2283) # Server machine.wait_for_open_port(3003) # Machine learning machine.succeed("curl --fail http://localhost:2283/") Loading Loading
nixos/modules/services/web-apps/immich.nix +44 −2 Original line number Diff line number Diff line Loading @@ -10,6 +10,10 @@ let isPostgresUnixSocket = lib.hasPrefix "/" cfg.database.host; isRedisUnixSocket = lib.hasPrefix "/" cfg.redis.host; # convert a Nix attribute path to jq object identifier-index: # https://jqlang.org/manual/#object-identifier-index attrPathToIndex = attrPath: "." + lib.concatStringsSep "." attrPath; commonServiceConfig = { Type = "simple"; Restart = "on-failure"; Loading Loading @@ -147,6 +151,27 @@ in ); }; secretSettings = mkOption { default = { }; description = '' Secrets to to be added to the JSON file generated from {option}`settings`, read from files. ''; example = lib.literalExpression '' { notifications.smtp.transport.password = "/path/to/secret"; oauth.clientSecret = "/path/to/other/secret"; } ''; type = let inherit (types) attrsOf either path; recursiveType = either (attrsOf recursiveType) path // { description = "nested " + (attrsOf path).description; }; in recursiveType; }; machine-learning = { enable = mkEnableOption "immich's machine-learning functionality to detect faces and search for objects" Loading Loading @@ -352,8 +377,8 @@ in IMMICH_MEDIA_LOCATION = cfg.mediaLocation; IMMICH_MACHINE_LEARNING_URL = "http://localhost:3003"; } // lib.optionalAttrs (cfg.settings != null) { IMMICH_CONFIG_FILE = "${format.generate "immich.json" cfg.settings}"; // lib.optionalAttrs (cfg.settings != null || cfg.settingsFile != null) { IMMICH_CONFIG_FILE = "/run/immich/config.json"; }; services.immich.machine-learning.environment = { Loading Loading @@ -382,7 +407,24 @@ in postgresqlPackage ]; preStart = mkIf (cfg.settings != null) ( '' cat '${format.generate "immich-config.json" cfg.settings}' > /run/immich/config.json '' + lib.concatStrings ( lib.mapAttrsToListRecursive (attrPath: _: '' tmp="$(mktemp)" ${lib.getExe pkgs.jq} --rawfile secret "$CREDENTIALS_DIRECTORY/${attrPathToIndex attrPath}" \ '${attrPathToIndex attrPath} = $secret' /run/immich/config.json > "$tmp" mv "$tmp" /run/immich/config.json '') cfg.secretSettings ) ); serviceConfig = commonServiceConfig // { LoadCredential = lib.mapAttrsToListRecursive ( attrPath: file: "${attrPathToIndex attrPath}:${file}" ) cfg.secretSettings; ExecStart = lib.getExe cfg.package; EnvironmentFile = mkIf (cfg.secretsFile != null) cfg.secretsFile; Slice = "system-immich.slice"; Loading
nixos/tests/web-apps/immich.nix +11 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,15 @@ services.immich = { enable = true; environment.IMMICH_LOG_LEVEL = "verbose"; settings.backup.database = { enabled = true; cronExpression = "invalid"; }; secretSettings = { backup.database.cronExpression = "${pkgs.writeText "cron" "0 02 * * *"}"; # thanks to LoadCredential files only readable by root should work notifications.smtp.transport.password = "/etc/shadow"; }; }; }; Loading @@ -25,6 +34,8 @@ machine.wait_for_unit("immich-server.service") machine.succeed("stat -L -c '%a %U %G' /run/immich/config.json | grep '600 immich immich'") machine.wait_for_open_port(2283) # Server machine.wait_for_open_port(3003) # Machine learning machine.succeed("curl --fail http://localhost:2283/") Loading