{ config, pkgs, lib, ... }: with lib; let cfg = config.services.naxos.apps.immich; in { options.services.naxos.apps.immich = { enable = mkEnableOption "Immich Self-Hosted Photo & Video Hub"; runtime = mkOption { type = types.enum [ "systemd" "docker" ]; default = "systemd"; description = "Runtime to execute Immich (systemd for native bare-metal speed with NixOS package, docker for containerized)."; }; port = mkOption { type = types.port; default = 2283; description = "Web interface and API port."; }; host = mkOption { type = types.str; default = "0.0.0.0"; description = "Listen host."; }; mediaLocation = mkOption { type = types.str; default = "/tank/media/photos"; description = "ZFS dataset or path where uploaded photos and videos are stored."; }; accelerationDevices = mkOption { type = types.listOf types.str; default = [ "/dev/dri/renderD128" ]; description = "DRM render devices for hardware-accelerated transcoding."; }; machineLearningCPUQuota = mkOption { type = types.str; default = "200%"; description = "CPU quota for machine learning service (200% = 2 full cores)."; }; openFirewall = mkOption { type = types.bool; default = true; description = "Open port in firewall."; }; }; config = mkIf cfg.enable { # Systemd / Native NixOS Deployment services.immich = mkIf (cfg.runtime == "systemd") { enable = true; host = cfg.host; port = cfg.port; mediaLocation = cfg.mediaLocation; openFirewall = cfg.openFirewall; accelerationDevices = cfg.accelerationDevices; }; services.redis.servers.immich = mkIf (cfg.runtime == "systemd") { logLevel = "warning"; }; systemd.services.immich-machine-learning = mkIf (cfg.runtime == "systemd") { serviceConfig = { CPUQuota = cfg.machineLearningCPUQuota; Nice = 19; }; }; users.users.immich = mkIf (cfg.runtime == "systemd") { extraGroups = [ "video" "render" ]; }; systemd.tmpfiles.rules = [ "d ${cfg.mediaLocation} 0750 immich immich -" ]; }; }