at 21.11-pre 4.6 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.opendkim; 8 9 defaultSock = "local:/run/opendkim/opendkim.sock"; 10 11 keyFile = "${cfg.keyPath}/${cfg.selector}.private"; 12 13 args = [ "-f" "-l" 14 "-p" cfg.socket 15 "-d" cfg.domains 16 "-k" keyFile 17 "-s" cfg.selector 18 ] ++ optionals (cfg.configFile != null) [ "-x" cfg.configFile ]; 19 20in { 21 imports = [ 22 (mkRenamedOptionModule [ "services" "opendkim" "keyFile" ] [ "services" "opendkim" "keyPath" ]) 23 ]; 24 25 ###### interface 26 27 options = { 28 29 services.opendkim = { 30 31 enable = mkOption { 32 type = types.bool; 33 default = false; 34 description = "Whether to enable the OpenDKIM sender authentication system."; 35 }; 36 37 socket = mkOption { 38 type = types.str; 39 default = defaultSock; 40 description = "Socket which is used for communication with OpenDKIM."; 41 }; 42 43 user = mkOption { 44 type = types.str; 45 default = "opendkim"; 46 description = "User for the daemon."; 47 }; 48 49 group = mkOption { 50 type = types.str; 51 default = "opendkim"; 52 description = "Group for the daemon."; 53 }; 54 55 domains = mkOption { 56 type = types.str; 57 default = "csl:${config.networking.hostName}"; 58 example = "csl:example.com,mydomain.net"; 59 description = '' 60 Local domains set (see <literal>opendkim(8)</literal> for more information on datasets). 61 Messages from them are signed, not verified. 62 ''; 63 }; 64 65 keyPath = mkOption { 66 type = types.path; 67 description = '' 68 The path that opendkim should put its generated private keys into. 69 The DNS settings will be found in this directory with the name selector.txt. 70 ''; 71 default = "/var/lib/opendkim/keys"; 72 }; 73 74 selector = mkOption { 75 type = types.str; 76 description = "Selector to use when signing."; 77 }; 78 79 configFile = mkOption { 80 type = types.nullOr types.path; 81 default = null; 82 description = "Additional opendkim configuration."; 83 }; 84 85 }; 86 87 }; 88 89 90 ###### implementation 91 92 config = mkIf cfg.enable { 93 94 users.users = optionalAttrs (cfg.user == "opendkim") { 95 opendkim = { 96 group = cfg.group; 97 uid = config.ids.uids.opendkim; 98 }; 99 }; 100 101 users.groups = optionalAttrs (cfg.group == "opendkim") { 102 opendkim.gid = config.ids.gids.opendkim; 103 }; 104 105 environment.systemPackages = [ pkgs.opendkim ]; 106 107 systemd.tmpfiles.rules = [ 108 "d '${cfg.keyPath}' - ${cfg.user} ${cfg.group} - -" 109 ]; 110 111 systemd.services.opendkim = { 112 description = "OpenDKIM signing and verification daemon"; 113 after = [ "network.target" ]; 114 wantedBy = [ "multi-user.target" ]; 115 116 preStart = '' 117 cd "${cfg.keyPath}" 118 if ! test -f ${cfg.selector}.private; then 119 ${pkgs.opendkim}/bin/opendkim-genkey -s ${cfg.selector} -d all-domains-generic-key 120 echo "Generated OpenDKIM key! Please update your DNS settings:\n" 121 echo "-------------------------------------------------------------" 122 cat ${cfg.selector}.txt 123 echo "-------------------------------------------------------------" 124 fi 125 ''; 126 127 serviceConfig = { 128 ExecStart = "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}"; 129 User = cfg.user; 130 Group = cfg.group; 131 RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim"; 132 StateDirectory = "opendkim"; 133 StateDirectoryMode = "0700"; 134 ReadWritePaths = [ cfg.keyPath ]; 135 136 AmbientCapabilities = []; 137 CapabilityBoundingSet = ""; 138 DevicePolicy = "closed"; 139 LockPersonality = true; 140 MemoryDenyWriteExecute = true; 141 NoNewPrivileges = true; 142 PrivateDevices = true; 143 PrivateMounts = true; 144 PrivateTmp = true; 145 PrivateUsers = true; 146 ProtectClock = true; 147 ProtectControlGroups = true; 148 ProtectHome = true; 149 ProtectHostname = true; 150 ProtectKernelLogs = true; 151 ProtectKernelModules = true; 152 ProtectKernelTunables = true; 153 ProtectSystem = "strict"; 154 RemoveIPC = true; 155 RestrictAddressFamilies = [ "AF_INET" "AF_INET6 AF_UNIX" ]; 156 RestrictNamespaces = true; 157 RestrictRealtime = true; 158 RestrictSUIDSGID = true; 159 SystemCallArchitectures = "native"; 160 SystemCallFilter = [ "@system-service" "~@privileged @resources" ]; 161 UMask = "0077"; 162 }; 163 }; 164 165 }; 166}