1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 23:00:39 +02:00

feat: reenable immich with native module, prepare nixos-extra-modules update

This commit is contained in:
oddlama 2025-09-13 20:18:54 +02:00
parent ef2f2a9b77
commit 157c303f38
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
25 changed files with 1521 additions and 184 deletions

View file

@ -42,7 +42,13 @@
"usb_storage"
"sd_mod"
];
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
boot.binfmt.emulatedSystems = [
"aarch64-linux"
"i686-linux"
"x86_64-windows"
"riscv32-linux"
"riscv64-linux"
];
}
// lib.optionalAttrs (!minimal) {
# TODO goodbye once -sk keys.

View file

@ -19,7 +19,7 @@ let
"photos.${globals.domains.me}"
"s3.photos.${globals.domains.me}"
globals.services.mealie.domain
# globals.services.immich.domain
globals.services.immich.domain
globals.services.influxdb.domain
globals.services.loki.domain
globals.services.paperless.domain

View file

@ -145,9 +145,9 @@
// mkMicrovm "paperless" {
enablePaperlessDataset = true;
}
# // mkMicrovm "immich" {
# enableStorageDataset = true;
# }
// mkMicrovm "immich" {
enableStorageDataset = true;
}
// mkMicrovm "ai" { }
// mkMicrovm "minecraft" { }
// mkMicrovm "ente" {

View file

@ -0,0 +1,288 @@
{
config,
globals,
lib,
nodes,
...
}:
let
immichDomain = "immich.${globals.domains.me}";
in
{
microvm.mem = 1024 * 12;
microvm.vcpu = 16;
# Mirror the original oauth2 secret
age.secrets.immich-oauth2-client-secret = {
inherit (nodes.ward-kanidm.config.age.secrets.kanidm-oauth2-immich) rekeyFile;
mode = "440";
group = "immich";
};
wireguard.proxy-sentinel = {
client.via = "sentinel";
firewallRuleForNode.sentinel.allowedTCPPorts = [ 2283 ];
};
wireguard.proxy-home = {
client.via = "ward";
firewallRuleForNode.ward-web-proxy.allowedTCPPorts = [ 2283 ];
};
globals.services.immich.domain = immichDomain;
globals.monitoring.http.immich = {
url = "https://${immichDomain}";
expectedBodyRegex = "immutable.entry.app";
network = "internet";
};
environment.persistence."/persist".directories = [
{
directory = "/var/cache/immich";
user = "immich";
group = "immich";
mode = "0750";
}
];
environment.persistence."/storage".directories = [
{
directory = "/var/lib/immich";
user = "immich";
group = "immich";
mode = "0750";
}
];
services.immich = {
enable = true;
# We use VectorChord from the beginning
database.enableVectors = false;
environment = {
IMMICH_LOG_LEVEL = "verbose";
IMMICH_TRUSTED_PROXIES = lib.concatStringsSep "," [
];
};
settings = {
backup.database = {
cronExpression = "0 02 * * *";
enabled = true;
keepLastAmount = 14;
};
ffmpeg = {
accel = "disabled";
accelDecode = false;
acceptedAudioCodecs = [
"aac"
"mp3"
"libopus"
"pcm_s16le"
];
acceptedContainers = [
"mov"
"ogg"
"webm"
];
acceptedVideoCodecs = [ "h264" ];
bframes = -1;
cqMode = "auto";
crf = 23;
gopSize = 0;
maxBitrate = "0";
preferredHwDevice = "auto";
preset = "ultrafast";
refs = 0;
targetAudioCodec = "aac";
targetResolution = "720";
targetVideoCodec = "h264";
temporalAQ = false;
threads = 0;
tonemap = "hable";
transcode = "required";
twoPass = false;
};
image = {
colorspace = "p3";
extractEmbedded = false;
preview = {
format = "jpeg";
quality = 80;
size = 1440;
};
thumbnail = {
format = "webp";
quality = 80;
size = 250;
};
};
job = {
backgroundTask.concurrency = 5;
faceDetection.concurrency = 2;
library.concurrency = 5;
metadataExtraction.concurrency = 5;
migration.concurrency = 5;
notifications.concurrency = 5;
search.concurrency = 5;
sidecar.concurrency = 5;
smartSearch.concurrency = 2;
thumbnailGeneration.concurrency = 3;
videoConversion.concurrency = 1;
};
library = {
scan = {
cronExpression = "0 0 * * *";
enabled = true;
};
watch.enabled = false;
};
logging = {
enabled = true;
level = "log";
};
machineLearning = {
clip = {
enabled = true;
modelName = "ViT-B-32__openai";
};
duplicateDetection = {
enabled = true;
maxDistance = 0.01;
};
enabled = true;
facialRecognition = {
enabled = true;
maxDistance = 0.5;
minFaces = 2;
minScore = 0.65;
modelName = "buffalo_l";
};
urls = [ "http://localhost:3003" ];
};
map = {
darkStyle = "https://tiles.immich.cloud/v1/style/dark.json";
enabled = true;
lightStyle = "https://tiles.immich.cloud/v1/style/light.json";
};
metadata.faces.import = false;
newVersionCheck.enabled = true;
notifications = {
smtp = {
enabled = false;
from = "";
replyTo = "";
transport = {
host = "";
ignoreCert = false;
password = "";
port = 587;
username = "";
};
};
};
oauth = rec {
autoLaunch = false;
autoRegister = true;
buttonText = "Login with Kanidm";
clientId = "immich";
clientSecret._secret = config.age.secrets.immich-oauth2-client-secret.path;
defaultStorageQuota = null;
enabled = true;
issuerUrl = "https://${globals.services.kanidm.domain}/oauth2/openid/${clientId}";
mobileOverrideEnabled = true;
mobileRedirectUri = "https://${immichDomain}/api/oauth/mobile-redirect";
profileSigningAlgorithm = "none";
scope = "openid email profile";
signingAlgorithm = "ES256";
storageLabelClaim = "preferred_username";
storageQuotaClaim = "immich_quota";
};
passwordLogin.enabled = true;
reverseGeocoding.enabled = true;
server = {
externalDomain = "https://${immichDomain}";
loginPageMessage = "Besser im Stuhl einschlafen als im Schlaf einstuhlen.";
};
storageTemplate = {
enabled = true;
hashVerificationEnabled = true;
template = "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}";
};
theme.customCss = "";
trash = {
days = 30;
enabled = true;
};
user.deleteDelay = 7;
};
};
nodes.sentinel = {
services.nginx = {
upstreams.immich = {
servers."${config.wireguard.proxy-sentinel.ipv4}:2283" = { };
extraConfig = ''
zone immich 64k;
keepalive 2;
'';
monitoring = {
enable = true;
expectedBodyRegex = "immutable.entry.app";
};
};
virtualHosts.${immichDomain} = {
forceSSL = true;
useACMEWildcardHost = true;
locations."/" = {
proxyPass = "http://immich";
proxyWebsockets = true;
};
extraConfig = ''
client_max_body_size 50G;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
'';
};
};
};
nodes.ward-web-proxy = {
services.nginx = {
upstreams.immich = {
servers."${config.wireguard.proxy-home.ipv4}:2283" = { };
extraConfig = ''
zone immich 64k;
keepalive 2;
'';
monitoring = {
enable = true;
expectedBodyRegex = "immutable.entry.app";
};
};
virtualHosts.${immichDomain} = {
forceSSL = true;
useACMEWildcardHost = true;
locations."/" = {
proxyPass = "http://immich";
proxyWebsockets = true;
extraConfig = '''';
};
extraConfig = ''
client_max_body_size 50G;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
allow ${globals.net.home-lan.vlans.home.cidrv4};
allow ${globals.net.home-lan.vlans.home.cidrv6};
# Firezone traffic
allow ${globals.net.home-lan.vlans.services.hosts.ward.ipv4};
allow ${globals.net.home-lan.vlans.services.hosts.ward.ipv6};
deny all;
'';
};
};
};
}

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKE+geXK2RVVNwZVoYOuX7pW+6mbgCa9SIghJCdHmbSB

View file

@ -21,7 +21,7 @@ let
"photos.${globals.domains.me}"
"s3.photos.${globals.domains.me}"
globals.services.mealie.domain
# globals.services.immich.domain
globals.services.immich.domain
globals.services.influxdb.domain
globals.services.loki.domain
globals.services.paperless.domain

View file

@ -118,7 +118,7 @@ in
"photos.${globals.domains.me}"
"s3.photos.${globals.domains.me}"
globals.services.mealie.domain
# globals.services.immich.domain
globals.services.immich.domain
globals.services.influxdb.domain
globals.services.loki.domain
globals.services.paperless.domain

View file

@ -37,7 +37,7 @@ in
age.secrets.kanidm-oauth2-forgejo = mkRandomSecret;
age.secrets.kanidm-oauth2-grafana = mkRandomSecret;
# age.secrets.kanidm-oauth2-immich = mkRandomSecret;
age.secrets.kanidm-oauth2-immich = mkRandomSecret;
age.secrets.kanidm-oauth2-firezone = mkRandomSecret;
age.secrets.kanidm-oauth2-mealie = mkRandomSecret;
age.secrets.kanidm-oauth2-paperless = mkRandomSecret;
@ -115,27 +115,23 @@ in
inherit (globals.kanidm) persons;
# # Immich
# groups."immich.access" = { };
# systems.oauth2.immich = {
# displayName = "Immich";
# originUrl = [
# "https://${globals.services.immich.domain}/auth/login"
# "https://${globals.services.immich.domain}/api/oauth/mobile-redirect"
# ];
# originLanding = "https://${globals.services.immich.domain}/";
# basicSecretFile = config.age.secrets.kanidm-oauth2-immich.path;
# preferShortUsername = true;
# # XXX: PKCE is currently not supported by immich
# allowInsecureClientDisablePkce = true;
# # XXX: RS256 is used instead of ES256 so additionally we need legacy crypto
# enableLegacyCrypto = true;
# scopeMaps."immich.access" = [
# "openid"
# "email"
# "profile"
# ];
# };
# Immich
groups."immich.access" = { };
systems.oauth2.immich = {
displayName = "Immich";
originUrl = [
"https://${globals.services.immich.domain}/auth/login"
"https://${globals.services.immich.domain}/api/oauth/mobile-redirect"
];
originLanding = "https://${globals.services.immich.domain}/";
basicSecretFile = config.age.secrets.kanidm-oauth2-immich.path;
preferShortUsername = true;
scopeMaps."immich.access" = [
"openid"
"email"
"profile"
];
};
# Firezone
groups."firezone.access" = { };