Self-host your own digital island
1# nixos-mailserver: a simple mail server 2# Copyright (C) 2017 Brian Olsen 3# 4# This program is free software: you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation, either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <http://www.gnu.org/licenses/> 16{ config, lib, pkgs, ... }: 17 18with lib; 19 20let 21 cfg = config.mailserver; 22 23 dkimUser = config.services.opendkim.user; 24 dkimGroup = config.services.opendkim.group; 25 26 createDomainDkimCert = dom: 27 let 28 dkim_key = "${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.key"; 29 dkim_txt = "${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.txt"; 30 in 31 '' 32 if [ ! -f "${dkim_key}" ] 33 then 34 ${pkgs.opendkim}/bin/opendkim-genkey -s "${cfg.dkimSelector}" \ 35 -d "${dom}" \ 36 --bits="${toString cfg.dkimKeyBits}" \ 37 --directory="${cfg.dkimKeyDirectory}" 38 mv "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.private" "${dkim_key}" 39 mv "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.txt" "${dkim_txt}" 40 echo "Generated key for domain ${dom} selector ${cfg.dkimSelector}" 41 fi 42 ''; 43 createAllCerts = lib.concatStringsSep "\n" (map createDomainDkimCert cfg.domains); 44 45 keyTable = pkgs.writeText "opendkim-KeyTable" 46 (lib.concatStringsSep "\n" (lib.flip map cfg.domains 47 (dom: "${dom} ${dom}:${cfg.dkimSelector}:${cfg.dkimKeyDirectory}/${dom}.${cfg.dkimSelector}.key"))); 48 signingTable = pkgs.writeText "opendkim-SigningTable" 49 (lib.concatStringsSep "\n" (lib.flip map cfg.domains (dom: "${dom} ${dom}"))); 50 51 dkim = config.services.opendkim; 52 args = [ "-f" "-l" ] ++ lib.optionals (dkim.configFile != null) [ "-x" dkim.configFile ]; 53in 54{ 55 config = mkIf (cfg.dkimSigning && cfg.enable) { 56 services.opendkim = { 57 enable = true; 58 selector = cfg.dkimSelector; 59 keyPath = cfg.dkimKeyDirectory; 60 domains = "csl:${builtins.concatStringsSep "," cfg.domains}"; 61 configFile = pkgs.writeText "opendkim.conf" ('' 62 Canonicalization ${cfg.dkimHeaderCanonicalization}/${cfg.dkimBodyCanonicalization} 63 UMask 0002 64 Socket ${dkim.socket} 65 KeyTable file:${keyTable} 66 SigningTable file:${signingTable} 67 '' + (lib.optionalString cfg.debug '' 68 Syslog yes 69 SyslogSuccess yes 70 LogWhy yes 71 '')); 72 }; 73 74 users.users = optionalAttrs (config.services.postfix.user == "postfix") { 75 postfix.extraGroups = [ "${dkimGroup}" ]; 76 }; 77 systemd.services.opendkim = { 78 preStart = lib.mkForce createAllCerts; 79 serviceConfig = { 80 ExecStart = lib.mkForce "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}"; 81 PermissionsStartOnly = lib.mkForce false; 82 }; 83 }; 84 systemd.tmpfiles.rules = [ 85 "d '${cfg.dkimKeyDirectory}' - ${dkimUser} ${dkimGroup} - -" 86 ]; 87 }; 88}