Self-host your own digital island
1# nixos-mailserver: a simple mail server 2# Copyright (C) 2016-2018 Robin Raymond 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 17{ config, pkgs, lib, ... }: 18 19with config.mailserver; 20 21let 22 vmail_user = { 23 name = vmailUserName; 24 isSystemUser = true; 25 uid = vmailUID; 26 home = mailDirectory; 27 createHome = true; 28 group = vmailGroupName; 29 }; 30 31 32 virtualMailUsersActivationScript = pkgs.writeScript "activate-virtual-mail-users" '' 33 #!${pkgs.stdenv.shell} 34 35 set -euo pipefail 36 37 # Create directory to store user sieve scripts if it doesn't exist 38 if (! test -d "${sieveDirectory}"); then 39 mkdir "${sieveDirectory}" 40 chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}" 41 chmod 770 "${sieveDirectory}" 42 fi 43 44 # Copy user's sieve script to the correct location (if it exists). If it 45 # is null, remove the file. 46 ${lib.concatMapStringsSep "\n" ({ name, sieveScript }: 47 if lib.isString sieveScript then '' 48 if (! test -d "${sieveDirectory}/${name}"); then 49 mkdir -p "${sieveDirectory}/${name}" 50 chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}" 51 chmod 770 "${sieveDirectory}/${name}" 52 fi 53 cat << 'EOF' > "${sieveDirectory}/${name}/default.sieve" 54 ${sieveScript} 55 EOF 56 chown "${vmailUserName}:${vmailGroupName}" "${sieveDirectory}/${name}/default.sieve" 57 '' else '' 58 if (test -f "${sieveDirectory}/${name}/default.sieve"); then 59 rm "${sieveDirectory}/${name}/default.sieve" 60 fi 61 if (test -f "${sieveDirectory}/${name}.svbin"); then 62 rm "${sieveDirectory}/${name}/default.svbin" 63 fi 64 '') (map (user: { inherit (user) name sieveScript; }) 65 (lib.attrValues loginAccounts))} 66 ''; 67in { 68 config = lib.mkIf enable { 69 # assert that all accounts provide a password 70 assertions = (map (acct: { 71 assertion = (acct.hashedPassword != null || acct.hashedPasswordFile != null); 72 message = "${acct.name} must provide either a hashed password or a password hash file"; 73 }) (lib.attrValues loginAccounts)); 74 75 # warn for accounts that specify both password and file 76 warnings = (map 77 (acct: "${acct.name} specifies both a password hash and hash file; hash file will be used") 78 (lib.filter 79 (acct: (acct.hashedPassword != null && acct.hashedPasswordFile != null)) 80 (lib.attrValues loginAccounts))); 81 82 # set the vmail gid to a specific value 83 users.groups = { 84 "${vmailGroupName}" = { gid = vmailUID; }; 85 }; 86 87 # define all users 88 users.users = { 89 "${vmail_user.name}" = lib.mkForce vmail_user; 90 }; 91 92 systemd.services.activate-virtual-mail-users = { 93 wantedBy = [ "multi-user.target" ]; 94 before = [ "dovecot2.service" ]; 95 serviceConfig = { 96 ExecStart = virtualMailUsersActivationScript; 97 }; 98 enable = true; 99 }; 100 }; 101}