{ config, lib, pkgs, ... }: let cfg = config.mailserver; hasMailDiscoveryConfig = cfg.enable && cfg.fqdn != null && cfg.domains != [ ]; in lib.mkIf hasMailDiscoveryConfig ( let domain = builtins.head cfg.domains; mobileconfigHost = "autoconfig.${domain}"; radicaleHost = "cal.${domain}"; mobileconfigPort = 8426; safeLegacyPath = email: builtins.replaceStrings [ "@" "+" ] [ "_" "-" ] email; accountEntries = lib.filter (entry: entry.domain == domain) ( lib.mapAttrsToList ( email: _: let parts = lib.splitString "@" email; username = builtins.head parts; domainPart = lib.last parts; in { inherit email username; domain = domainPart; legacyPath = safeLegacyPath email; } ) cfg.loginAccounts ); usernames = map (entry: entry.username) accountEntries; defaultUsername = if lib.length accountEntries == 1 then (builtins.head accountEntries).username else null; generatorScript = ./mobileconfig-generator.py; accountArgs = lib.concatMapStrings (entry: " --account ${entry.username}:${entry.email}:${entry.legacyPath}" ) accountEntries; defaultUsernameArg = if defaultUsername != null then " --default-username ${defaultUsername}" else ""; in { assertions = [ { assertion = lib.length usernames == lib.length (lib.unique usernames); message = "Mail mobileconfig usernames must be unique within ${domain}."; } ]; systemd.services.mobileconfig-generator = { description = "Apple mobileconfig generator"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { DynamicUser = true; ExecStart = "${pkgs.python3}/bin/python3 ${generatorScript} --domain ${domain} --mail-host ${cfg.fqdn} --radicale-host ${radicaleHost} --port ${toString mobileconfigPort}${defaultUsernameArg}${accountArgs}"; NoNewPrivileges = true; PrivateTmp = true; ProtectHome = true; ProtectSystem = "strict"; Restart = "always"; }; }; services.nginx.virtualHosts.${mobileconfigHost}.locations = { "= /mobileconfig".return = "308 /mobileconfig/$is_args$args"; "/mobileconfig/" = { proxyPass = "http://127.0.0.1:${toString mobileconfigPort}"; extraConfig = '' proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; ''; }; }; } )