{ lib, config, pkgs, ... }: let mediaLocation = "/var/lib/immich"; in { options.host.immich = { enable = lib.mkEnableOption "should immich be enabled on this computer"; subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that immich will be hosted at"; default = "immich"; }; }; config = lib.mkIf config.host.immich.enable (lib.mkMerge [ { host = { reverse_proxy.subdomains.${config.host.immich.subdomain} = { target = "http://localhost:${toString config.services.immich.port}"; websockets.enable = true; forwardHeaders.enable = true; extraConfig = '' # allow large file uploads client_max_body_size 50000M; # set timeout proxy_read_timeout 600s; proxy_send_timeout 600s; send_timeout 600s; proxy_redirect off; ''; }; postgres = { enable = true; extraUsers = { ${config.services.immich.database.user} = { isClient = true; }; }; }; }; services.immich = { enable = true; port = 2283; # redis.enable = false; }; networking.firewall.interfaces.${config.services.tailscale.interfaceName} = { allowedUDPPorts = [ config.services.immich.port ]; allowedTCPPorts = [ config.services.immich.port ]; }; } (lib.mkIf config.services.fail2ban.enable { environment.etc = { "fail2ban/filter.d/immich.local".text = lib.mkIf config.services.immich.enable ( pkgs.lib.mkDefault (pkgs.lib.mkAfter '' [Definition] failregex = immich-server.*Failed login attempt for user.+from ip address\s? journalmatch = CONTAINER_TAG=immich-server '') ); }; services.fail2ban = { jails = { immich-iptables.settings = lib.mkIf config.services.immich.enable { enabled = true; filter = "immich"; backend = "systemd"; }; }; }; }) (lib.mkIf config.host.impermanence.enable { assertions = [ { assertion = config.services.immich.mediaLocation == mediaLocation; message = "immich media location does not match persistence"; } ]; environment.persistence."/persist/system/root" = { enable = true; hideMounts = true; directories = [ { directory = mediaLocation; user = "immich"; group = "immich"; } ]; }; }) ]); }