feat: add immich module to yumeami tsuki host
All checks were successful
ci / treefmt (push) Successful in 2m10s
All checks were successful
ci / treefmt (push) Successful in 2m10s
This commit is contained in:
parent
72efc82c2a
commit
6a0b61a502
6 changed files with 106 additions and 12 deletions
|
|
@ -88,6 +88,7 @@ in {
|
||||||
"forgejo"
|
"forgejo"
|
||||||
"grafana"
|
"grafana"
|
||||||
"asciinema"
|
"asciinema"
|
||||||
|
"immich"
|
||||||
"ntfy"
|
"ntfy"
|
||||||
"terraform"
|
"terraform"
|
||||||
"vaultwarden"
|
"vaultwarden"
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,14 @@ in {
|
||||||
port = 5125;
|
port = 5125;
|
||||||
internal = true;
|
internal = true;
|
||||||
};
|
};
|
||||||
|
immich = {
|
||||||
|
port = 2283;
|
||||||
|
internal = true;
|
||||||
|
websocket = {
|
||||||
|
enable = true;
|
||||||
|
path = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
jellyfin = {
|
jellyfin = {
|
||||||
port = 8096;
|
port = 8096;
|
||||||
internal = true;
|
internal = true;
|
||||||
|
|
|
||||||
58
modules/nixos/services/apps/immich/default.nix
Normal file
58
modules/nixos/services/apps/immich/default.nix
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP hostHasService resolveServicePort;
|
||||||
|
inherit (config.networking) hostName;
|
||||||
|
|
||||||
|
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
|
||||||
|
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
|
||||||
|
|
||||||
|
isEnabled = hostHasService networkCfg.network-services hostName "immich";
|
||||||
|
port = resolveServicePort networkCfg.network-services "immich" 2283;
|
||||||
|
in {
|
||||||
|
config = mkIf isEnabled {
|
||||||
|
services.immich = {
|
||||||
|
enable = true;
|
||||||
|
host = "0.0.0.0";
|
||||||
|
port = port;
|
||||||
|
openFirewall = true;
|
||||||
|
|
||||||
|
database = {
|
||||||
|
enable = false;
|
||||||
|
host = resolveDatabaseIP networkCfg.devices pgCfg.databases "immich";
|
||||||
|
port = 5600;
|
||||||
|
name = "immich";
|
||||||
|
user = "immich";
|
||||||
|
};
|
||||||
|
|
||||||
|
secretsFile = config.sops.secrets."environment-file/immich".path;
|
||||||
|
|
||||||
|
settings.server.externalDomain = "https://photos.yumeami.sh";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.immich-server = let
|
||||||
|
dbHost = resolveDatabaseHost pgCfg.databases "immich";
|
||||||
|
in
|
||||||
|
mkIf (dbHost == hostName) {
|
||||||
|
after = ["postgresql.service" "pgbouncer.service"];
|
||||||
|
requires = ["postgresql.service" "pgbouncer.service"];
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."environment-file/immich" = {};
|
||||||
|
|
||||||
|
${namespace}.services.storage.impermanence.folders = let
|
||||||
|
immichUser = config.users.users.immichUser;
|
||||||
|
in [
|
||||||
|
{
|
||||||
|
directory = "/var/lib/immich";
|
||||||
|
user = immichUser.name;
|
||||||
|
group = immichUser.group;
|
||||||
|
mode = "700";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
} @ args: let
|
} @ args: let
|
||||||
inherit (lib) types mkIf concatStringsSep hasAttr getAttr filter;
|
inherit (lib) types mkIf mkMerge concatStringsSep hasAttr getAttr filter optionalString head splitString;
|
||||||
inherit (lib.${namespace}) getAttrByNamespace mkOptionsWithNamespace readJsonOrEmpty getIn mkOptAttrset;
|
inherit (lib.${namespace}) getAttrByNamespace mkOptionsWithNamespace readJsonOrEmpty getIn mkOptAttrset;
|
||||||
inherit (config.networking) hostName;
|
inherit (config.networking) hostName;
|
||||||
base = "${namespace}.services.storage.postgresql";
|
base = "${namespace}.services.storage.postgresql";
|
||||||
|
|
@ -26,7 +26,7 @@ in {
|
||||||
config = mkIf (hasAttr hostName cfg.databases) (let
|
config = mkIf (hasAttr hostName cfg.databases) (let
|
||||||
hostDatabases = getAttr hostName cfg.databases;
|
hostDatabases = getAttr hostName cfg.databases;
|
||||||
mainServices = filter (db: !(lib.hasSuffix "-log" db)) hostDatabases;
|
mainServices = filter (db: !(lib.hasSuffix "-log" db)) hostDatabases;
|
||||||
logDatabases = filter (lib.hasSuffix "-log") hostDatabases;
|
auxDbs = filter (lib.hasSuffix "-log") hostDatabases;
|
||||||
in {
|
in {
|
||||||
services = {
|
services = {
|
||||||
postgresql = {
|
postgresql = {
|
||||||
|
|
@ -34,9 +34,21 @@ in {
|
||||||
enableTCPIP = true;
|
enableTCPIP = true;
|
||||||
package = pkgs.postgresql_17;
|
package = pkgs.postgresql_17;
|
||||||
|
|
||||||
settings = {
|
settings = mkMerge [
|
||||||
port = port;
|
{
|
||||||
};
|
port = port;
|
||||||
|
}
|
||||||
|
(mkIf (builtins.elem "immich" mainServices) {
|
||||||
|
shared_preload_libraries = ["vchord.so"];
|
||||||
|
search_path = "\"$user\", public, vectors";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
extensions = mkIf (builtins.elem "immich" mainServices) (ps:
|
||||||
|
with ps; [
|
||||||
|
pgvector
|
||||||
|
vectorchord
|
||||||
|
]);
|
||||||
|
|
||||||
authentication = let
|
authentication = let
|
||||||
permissionEntries =
|
permissionEntries =
|
||||||
|
|
@ -105,14 +117,28 @@ in {
|
||||||
ALTER FUNCTION public.pgbouncer_lookup(text) SET search_path = pg_catalog;
|
ALTER FUNCTION public.pgbouncer_lookup(text) SET search_path = pg_catalog;
|
||||||
GRANT EXECUTE ON FUNCTION public.pgbouncer_lookup(text) TO pgbouncer_auth;
|
GRANT EXECUTE ON FUNCTION public.pgbouncer_lookup(text) TO pgbouncer_auth;
|
||||||
|
|
||||||
${concatStringsSep "\n" (map (logDb: let
|
${
|
||||||
mainUser = lib.removeSuffix "-log" logDb;
|
auxDbs
|
||||||
|
|> map (db: let
|
||||||
|
user = head (splitString "-" db);
|
||||||
in ''
|
in ''
|
||||||
GRANT ALL PRIVILEGES ON DATABASE "${logDb}" TO "${mainUser}";
|
GRANT ALL PRIVILEGES ON DATABASE "${db}" TO "${user}";
|
||||||
ALTER DATABASE "${logDb}" OWNER TO "${mainUser}";
|
ALTER DATABASE "${db}" OWNER TO "${user}";
|
||||||
'')
|
'')
|
||||||
logDatabases)}
|
|> concatStringsSep "\n"
|
||||||
|
}
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
|
${
|
||||||
|
optionalString (builtins.elem "immich" mainServices) ''
|
||||||
|
${
|
||||||
|
["unaccent" "uuid-ossp" "cube" "earthdistance" "pg_trgm" "vector" "vchord"]
|
||||||
|
|> map (ext: "psql -d immich -v ON_ERROR_STOP=1 -c 'CREATE EXTENSION IF NOT EXISTS \"${ext}\";'")
|
||||||
|
|> concatStringsSep "\n"
|
||||||
|
}
|
||||||
|
psql -d immich -v ON_ERROR_STOP=1 -c 'ALTER SCHEMA public OWNER TO immich;'
|
||||||
|
''
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -16,6 +16,7 @@ environment-file:
|
||||||
autobrr: ENC[AES256_GCM,data:EXuYnWKHk0cwFWdMUaU/aapaPlY4o0/WjwlBenIM9aqOQ9jZ8bqQEcSeP8iHg9XjDJFNpxwSTsDCp3sB6jXrqAbR6Q==,iv:rhRvRE5+1VfcGcWjm4rGrs8fPzttp5WgHGpjnwcgSV4=,tag:RNK3Xp+NGeUSOgWC9uUsCA==,type:str]
|
autobrr: ENC[AES256_GCM,data:EXuYnWKHk0cwFWdMUaU/aapaPlY4o0/WjwlBenIM9aqOQ9jZ8bqQEcSeP8iHg9XjDJFNpxwSTsDCp3sB6jXrqAbR6Q==,iv:rhRvRE5+1VfcGcWjm4rGrs8fPzttp5WgHGpjnwcgSV4=,tag:RNK3Xp+NGeUSOgWC9uUsCA==,type:str]
|
||||||
bazarr: ENC[AES256_GCM,data:vDTjMrKEoGdnx1ABTAuA0k3kogR2tV4z9jvXVj52B2YVDRa4MPN/CWRXtAR1u0jysf7rE3NJMsBv3nQgOpI=,iv:ahQlJt+aok0vkgVD85qdpIEX0rxE9qcUOQWH7abqa0w=,tag:DzogkL9XBDJNBsiUgBwHIw==,type:str]
|
bazarr: ENC[AES256_GCM,data:vDTjMrKEoGdnx1ABTAuA0k3kogR2tV4z9jvXVj52B2YVDRa4MPN/CWRXtAR1u0jysf7rE3NJMsBv3nQgOpI=,iv:ahQlJt+aok0vkgVD85qdpIEX0rxE9qcUOQWH7abqa0w=,tag:DzogkL9XBDJNBsiUgBwHIw==,type:str]
|
||||||
glance: ENC[AES256_GCM,data:/T/ItEwjzvLj1/p3ldFu+dorzOWUSDcxrljPiYJ1j/9PIJZMJkZ2BYIXIt8FwwnA1Omwl6QoJwN9H/GiT2we69ucVnic0i3SchDHuM3rXA9/xuvUB61rzXdx3fQ9T7LbJ6cA77oApCBCOA==,iv:LlsIVEhUot5YJpTzi6uvL/i2hrfAxnP3pZOOV9L8Xvs=,tag:/Fnh+WgtZXfSb9pWe1m1Mw==,type:str]
|
glance: ENC[AES256_GCM,data:/T/ItEwjzvLj1/p3ldFu+dorzOWUSDcxrljPiYJ1j/9PIJZMJkZ2BYIXIt8FwwnA1Omwl6QoJwN9H/GiT2we69ucVnic0i3SchDHuM3rXA9/xuvUB61rzXdx3fQ9T7LbJ6cA77oApCBCOA==,iv:LlsIVEhUot5YJpTzi6uvL/i2hrfAxnP3pZOOV9L8Xvs=,tag:/Fnh+WgtZXfSb9pWe1m1Mw==,type:str]
|
||||||
|
immich: ENC[AES256_GCM,data:ebaICuhFvHeJek8px2PLPYHY21rrfDe3QMj/WSwsnfCrzKnZ20eKxyU2InzSi0KN2hJ4xuhYeJI=,iv:wFMblYyr+ENXQxZwBhQLBvDA4ERmZPjkurn/pIuzYc4=,tag:0OZg/lGC/Lti2XtfAXZXUg==,type:str]
|
||||||
lidarr: ENC[AES256_GCM,data:F75i9YOqcFPVICggm+JHJB+jor2PNAAfyu/Zsj+zptqtJh0nJMMpfctuEYRyc1k0y/VGssPDu8FqEqH44kmgn4L1cmsLcAM=,iv:6JvmnIAG4GUebD7DoLrGt/G/tUrbAiZUDlGZUHxxmbY=,tag:U9wB+cKXM3kSnbADmfTmzw==,type:str]
|
lidarr: ENC[AES256_GCM,data:F75i9YOqcFPVICggm+JHJB+jor2PNAAfyu/Zsj+zptqtJh0nJMMpfctuEYRyc1k0y/VGssPDu8FqEqH44kmgn4L1cmsLcAM=,iv:6JvmnIAG4GUebD7DoLrGt/G/tUrbAiZUDlGZUHxxmbY=,tag:U9wB+cKXM3kSnbADmfTmzw==,type:str]
|
||||||
ntfy: ENC[AES256_GCM,data:JB+h4r+QXerD8PbT35RwM556RY63mTNvBN31rIZA7gVkqfa33tLco1fNkFyysA+qpTKaraKpGgmlC6yBgWi5dc7My2CzEHKqqEAV6CJ24Tj00F1aXOunw8BsEBCYuVeHpbIsEtikbkTQ6d0r5bAXdlrL8zyD,iv:/zLYKwDcaNWR3lBqH+IPuwsPnq59SQHaMGSEY+ADJ/w=,tag:+WMzRX+YPaW8dMvJsAAcVQ==,type:str]
|
ntfy: ENC[AES256_GCM,data:JB+h4r+QXerD8PbT35RwM556RY63mTNvBN31rIZA7gVkqfa33tLco1fNkFyysA+qpTKaraKpGgmlC6yBgWi5dc7My2CzEHKqqEAV6CJ24Tj00F1aXOunw8BsEBCYuVeHpbIsEtikbkTQ6d0r5bAXdlrL8zyD,iv:/zLYKwDcaNWR3lBqH+IPuwsPnq59SQHaMGSEY+ADJ/w=,tag:+WMzRX+YPaW8dMvJsAAcVQ==,type:str]
|
||||||
prowlarr: ENC[AES256_GCM,data:l1aDFg/alG7CDkkwufzMjQ2/6ZLnMvBO/GodS2txktvjRCeoc+qfL4Xf4T6JCltVHTHTl8P3Y0GlWoZ0VPbuP/L+UmV/jZKBvA==,iv:xnXc5TGd1zpDCvaN2IzdI2R/t8C0hTJaLVsP6u3fNsU=,tag:4ZkRyc1aCZoY59X9zIV5gw==,type:str]
|
prowlarr: ENC[AES256_GCM,data:l1aDFg/alG7CDkkwufzMjQ2/6ZLnMvBO/GodS2txktvjRCeoc+qfL4Xf4T6JCltVHTHTl8P3Y0GlWoZ0VPbuP/L+UmV/jZKBvA==,iv:xnXc5TGd1zpDCvaN2IzdI2R/t8C0hTJaLVsP6u3fNsU=,tag:4ZkRyc1aCZoY59X9zIV5gw==,type:str]
|
||||||
|
|
@ -168,7 +169,7 @@ sops:
|
||||||
yUtR1lCjpW5Hpi2vDoom4HDsodeXfazqS+RjpHuKOLeO39bb4KbAhg==
|
yUtR1lCjpW5Hpi2vDoom4HDsodeXfazqS+RjpHuKOLeO39bb4KbAhg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age1988jz0qfj6m9xfenhd292tkxwyxvzhv79gkgrhm0gep353kej3yqe6zp86
|
recipient: age1988jz0qfj6m9xfenhd292tkxwyxvzhv79gkgrhm0gep353kej3yqe6zp86
|
||||||
lastmodified: "2026-06-30T19:23:37Z"
|
lastmodified: "2026-07-01T03:01:47Z"
|
||||||
mac: ENC[AES256_GCM,data:FewAMhmopqxq6N6elvjIVmyR+LaQCh/ItQFVU0tSUInp6+qz6jPb1gKYqOI0pOU0C5euBV02K39afY8vrJBc8hM7AD+talKGXmgNULX3f4JWOnNrfOgFhgoqXTgWrU+kAEHmM5ZNlFICYeEow6i+/t6DAlVFuylrCpFokJLH0bU=,iv:7QnAu29thDRu/AamlvyjgZp4MwoiScELDByLSDWTjV0=,tag:y++WaY41XP/ifUo7IqKZZw==,type:str]
|
mac: ENC[AES256_GCM,data:YU7Bz3jfzZBcRS8988PEelyk0ILGDIMYMOm3dmX1CS2vEmPdYS4F90JS5msyniV8FEvygsZg9Es5UvijEvXCwLHFi8DCsisRREQkjng6Y0HlpYxZ3vkX1ayYqNz6HgtZyLh8SeMvxUJO9fI69NzhW9lw7xvgeSnnNz2DVu2kqqg=,iv:tys6hfzw6qUXXMNMtPx8cydGLJLbT6OEBxQaCAt8LwU=,tag:niCSLPegApsGkK02Xh4XSA==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.13.1
|
version: 3.13.1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue