mobileconfig
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
imports = [
|
||||
./autodiscover.nix
|
||||
./mail.nix
|
||||
./mobileconfig.nix
|
||||
./radicale.nix
|
||||
./roundcube.nix
|
||||
];
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
{
|
||||
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}";
|
||||
safeAccountName = email: builtins.replaceStrings [ "@" "+" ] [ "_" "-" ] email;
|
||||
|
||||
mkUuid = seed:
|
||||
let
|
||||
hash = builtins.hashString "sha256" seed;
|
||||
in
|
||||
"${lib.substring 0 8 hash}-${lib.substring 8 4 hash}-${lib.substring 12 4 hash}-${lib.substring 16 4 hash}-${lib.substring 20 12 hash}";
|
||||
|
||||
mkMobileconfig = email:
|
||||
let
|
||||
safeName = safeAccountName email;
|
||||
profileUuid = mkUuid "${email}-apple-profile";
|
||||
mailUuid = mkUuid "${email}-apple-mail";
|
||||
caldavUuid = mkUuid "${email}-apple-caldav";
|
||||
carddavUuid = mkUuid "${email}-apple-carddav";
|
||||
in
|
||||
pkgs.writeText "${safeName}.mobileconfig" ''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>EmailAccountDescription</key>
|
||||
<string>${domain} Mail</string>
|
||||
<key>EmailAccountName</key>
|
||||
<string>${email}</string>
|
||||
<key>EmailAccountType</key>
|
||||
<string>EmailTypeIMAP</string>
|
||||
<key>EmailAddress</key>
|
||||
<string>${email}</string>
|
||||
<key>IncomingMailServerAuthentication</key>
|
||||
<string>EmailAuthPassword</string>
|
||||
<key>IncomingMailServerHostName</key>
|
||||
<string>${cfg.fqdn}</string>
|
||||
<key>IncomingMailServerPortNumber</key>
|
||||
<integer>993</integer>
|
||||
<key>IncomingMailServerUseSSL</key>
|
||||
<true/>
|
||||
<key>IncomingMailServerUsername</key>
|
||||
<string>${email}</string>
|
||||
<key>OutgoingMailServerAuthentication</key>
|
||||
<string>EmailAuthPassword</string>
|
||||
<key>OutgoingMailServerHostName</key>
|
||||
<string>${cfg.fqdn}</string>
|
||||
<key>OutgoingMailServerPortNumber</key>
|
||||
<integer>587</integer>
|
||||
<key>OutgoingMailServerUseSSL</key>
|
||||
<true/>
|
||||
<key>OutgoingMailServerUsername</key>
|
||||
<string>${email}</string>
|
||||
<key>OutgoingPasswordSameAsIncomingPassword</key>
|
||||
<true/>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures IMAP and SMTP for ${email}.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Mail</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.billenius.mobileconfig.${safeName}.mail</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.mail.managed</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${mailUuid}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CalDAVAccountDescription</key>
|
||||
<string>${domain} Calendar</string>
|
||||
<key>CalDAVHostName</key>
|
||||
<string>${radicaleHost}</string>
|
||||
<key>CalDAVPort</key>
|
||||
<integer>443</integer>
|
||||
<key>CalDAVUseSSL</key>
|
||||
<true/>
|
||||
<key>CalDAVUsername</key>
|
||||
<string>${email}</string>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures CalDAV for ${email}.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Calendar</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.billenius.mobileconfig.${safeName}.caldav</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.caldav.account</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${caldavUuid}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CardDAVAccountDescription</key>
|
||||
<string>${domain} Contacts</string>
|
||||
<key>CardDAVHostName</key>
|
||||
<string>${radicaleHost}</string>
|
||||
<key>CardDAVPort</key>
|
||||
<integer>443</integer>
|
||||
<key>CardDAVUseSSL</key>
|
||||
<true/>
|
||||
<key>CardDAVUsername</key>
|
||||
<string>${email}</string>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures CardDAV for ${email}.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Contacts</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.billenius.mobileconfig.${safeName}.carddav</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.carddav.account</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${carddavUuid}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures mail, calendar, and contacts for ${email}.</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>${domain} Mail</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.billenius.mobileconfig.${safeName}</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>${domain}</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>${profileUuid}</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
'';
|
||||
|
||||
mobileconfigProfiles = lib.mapAttrs (
|
||||
email: _: {
|
||||
inherit email;
|
||||
safeName = safeAccountName email;
|
||||
profile = mkMobileconfig email;
|
||||
}
|
||||
) cfg.loginAccounts;
|
||||
|
||||
mobileconfigLandingPage = pkgs.writeText "mobileconfig-index.html" ''
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>${domain} Apple Profile</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>${domain} Apple Profile</h1>
|
||||
<p>Open this page in Safari on iPhone, iPad, or macOS and enter your email address to download the configuration profile.</p>
|
||||
<form method="get" action="/mobileconfig/">
|
||||
<label for="emailaddress">Email address</label>
|
||||
<input id="emailaddress" name="emailaddress" type="email" autocomplete="email" required>
|
||||
<button type="submit">Download profile</button>
|
||||
</form>
|
||||
<p>The profile configures IMAP, SMTP, CalDAV, and CardDAV. You will still be asked for your password during installation.</p>
|
||||
</body>
|
||||
</html>
|
||||
'';
|
||||
|
||||
mobileconfigRedirectConfig =
|
||||
lib.concatStrings (
|
||||
lib.mapAttrsToList (
|
||||
email: profile: ''
|
||||
if ($arg_emailaddress = "${email}") {
|
||||
return 302 /mobileconfig/${profile.safeName}.mobileconfig;
|
||||
}
|
||||
''
|
||||
) mobileconfigProfiles
|
||||
);
|
||||
|
||||
mobileconfigLocations = lib.listToAttrs (
|
||||
[
|
||||
{
|
||||
name = "= /mobileconfig";
|
||||
value.return = "308 /mobileconfig/";
|
||||
}
|
||||
{
|
||||
name = "= /mobileconfig/";
|
||||
value.extraConfig = ''
|
||||
${mobileconfigRedirectConfig}
|
||||
return 302 /mobileconfig/index.html;
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "= /mobileconfig/index.html";
|
||||
value.extraConfig = ''
|
||||
default_type text/html;
|
||||
alias ${mobileconfigLandingPage};
|
||||
'';
|
||||
}
|
||||
]
|
||||
++ lib.mapAttrsToList (
|
||||
_: profile: {
|
||||
name = "= /mobileconfig/${profile.safeName}.mobileconfig";
|
||||
value.extraConfig = ''
|
||||
default_type application/x-apple-aspen-config;
|
||||
add_header Content-Disposition 'attachment; filename="${profile.safeName}.mobileconfig"' always;
|
||||
alias ${profile.profile};
|
||||
'';
|
||||
}
|
||||
) mobileconfigProfiles
|
||||
);
|
||||
|
||||
defaultMobileconfigLocation =
|
||||
let
|
||||
accounts = lib.attrNames mobileconfigProfiles;
|
||||
in
|
||||
if lib.length accounts == 1 then
|
||||
let
|
||||
profile = mobileconfigProfiles.${builtins.head accounts};
|
||||
in
|
||||
{
|
||||
"= /mobileconfig/billenius.mobileconfig".extraConfig = ''
|
||||
default_type application/x-apple-aspen-config;
|
||||
add_header Content-Disposition 'attachment; filename="billenius.mobileconfig"' always;
|
||||
alias ${profile.profile};
|
||||
'';
|
||||
}
|
||||
else
|
||||
{ };
|
||||
in
|
||||
{
|
||||
services.nginx.virtualHosts.${mobileconfigHost}.locations = mobileconfigLocations // defaultMobileconfigLocation;
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user