diff --git a/mail-config.nix b/mail-config.nix index e812519..e968fb5 100644 --- a/mail-config.nix +++ b/mail-config.nix @@ -82,15 +82,18 @@ let # implies that the FQDN must be set as an `A` record to point to the IP of # the server. TODO: Explain more details # - # TODO: Only certificate scheme 1) works as of yet. - certificate_scheme = 1; + # TODO: Only certificate scheme 1) and 2) work as of yet. + certificate_scheme = 2; # Sceme 1) cert_file = "/root/mail-server.crt"; key_file = "/root/mail-server.key"; # Sceme 2) - cert_folder = "/root/certs"; + # This is the folder where the certificate will be created. The name is + # hardcoded to "cert-${domain}.pem" and "key-${domain}.pem" and the + # certificate is valid for 10 years. + cert_dir = "/root/certs"; # # Whether to enable imap / pop3. Both variants are only supported in the @@ -123,11 +126,11 @@ in services = import ./mail-server/services.nix { inherit mail_dir vmail_user_name vmail_group_name valiases domain enable_imap enable_pop3 virus_scanning dkim_signing - certificate_scheme cert_file key_file; - }; + certificate_scheme cert_file key_file cert_dir; + }; environment = import ./mail-server/environment.nix { - inherit pkgs; + inherit pkgs certificate_scheme; }; networking = import ./mail-server/networking.nix { @@ -135,7 +138,8 @@ in }; systemd = import ./mail-server/systemd.nix { - inherit mail_dir vmail_group_name; + inherit mail_dir vmail_group_name certificate_scheme cert_dir host_prefix + domain pkgs; }; users = import ./mail-server/users.nix { diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix index 4b83d55..b294ac1 100644 --- a/mail-server/dovecot.nix +++ b/mail-server/dovecot.nix @@ -14,23 +14,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ vmail_group_name, vmail_user_name, mail_dir, enable_imap, enable_pop3, -certificate_scheme, cert_file, key_file }: +{ vmail_group_name, vmail_user_name, mail_dir, enable_imap, enable_pop3, cert, +key }: + let # maildir in format "/${domain}/${user}/" dovecot_maildir = "maildir:${mail_dir}/%d/%n/"; - # cert :: PATH - cert = if certificate_scheme == 1 - then cert_file - else ""; - - # key :: PATH - key = if certificate_scheme == 1 - then key_file - else ""; - - in { enable = true; diff --git a/mail-server/environment.nix b/mail-server/environment.nix index 7f4d5d7..3b61430 100644 --- a/mail-server/environment.nix +++ b/mail-server/environment.nix @@ -14,10 +14,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ pkgs, ... }: +{ pkgs, certificate_scheme }: { systemPackages = with pkgs; [ dovecot opendkim openssh postfix clamav rspamd rmilter - ]; + ] ++ (if certificate_scheme == 2 then [ openssl ] else []); } diff --git a/mail-server/postfix.nix b/mail-server/postfix.nix index d132b24..bc34593 100644 --- a/mail-server/postfix.nix +++ b/mail-server/postfix.nix @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ mail_dir, domain, valiases, certificate_scheme, cert_file, key_file }: +{ mail_dir, domain, valiases, cert, key }: let # valiasToString :: { from = "..."; to = "..." } -> String @@ -34,16 +34,6 @@ let # vhosts_file :: Path vhosts_file = builtins.toFile "vhosts" domain; - # cert :: PATH - cert = if certificate_scheme == 1 - then cert_file - else ""; - - # key :: PATH - key = if certificate_scheme == 1 - then key_file - else ""; - in { enable = true; diff --git a/mail-server/services.nix b/mail-server/services.nix index b872586..6cea1c4 100644 --- a/mail-server/services.nix +++ b/mail-server/services.nix @@ -16,8 +16,23 @@ { mail_dir, vmail_user_name, vmail_group_name, valiases, domain, enable_imap, enable_pop3, virus_scanning, dkim_signing, certificate_scheme, cert_file, -key_file }: +key_file, cert_dir }: +let + # cert :: PATH + cert = if certificate_scheme == 1 + then cert_file + else if certificate_scheme == 2 + then "${cert_dir}/cert-${domain}.pem" + else ""; + + # key :: PATH + key = if certificate_scheme == 1 + then key_file + else if certificate_scheme == 2 + then "${cert_dir}/key-${domain}.pem" + else ""; +in { # rspamd rspamd = { @@ -29,11 +44,11 @@ key_file }: }; postfix = import ./postfix.nix { - inherit mail_dir domain valiases certificate_scheme cert_file key_file; + inherit mail_dir domain valiases cert key; }; dovecot2 = import ./dovecot.nix { inherit vmail_group_name vmail_user_name mail_dir enable_imap - enable_pop3 certificate_scheme cert_file key_file; + enable_pop3 cert key; }; } diff --git a/mail-server/systemd.nix b/mail-server/systemd.nix index 0d2fe23..d6dcefb 100644 --- a/mail-server/systemd.nix +++ b/mail-server/systemd.nix @@ -14,8 +14,29 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ mail_dir, vmail_group_name }: +{ pkgs, mail_dir, vmail_group_name, certificate_scheme, cert_dir, host_prefix, +domain }: +let + create_certificate = if certificate_scheme == 2 then + '' + # Create certificates if they do not exist yet + dir="${cert_dir}" + fqdn="${host_prefix}.${domain}" + case $fqdn in /*) fqdn=$(cat "$fqdn");; esac + key="''${dir}/key-${domain}.pem"; + cert="''${dir}/cert-${domain}.pem"; + + if [ ! -f "''${key}" ] || [ ! -f "''${cert}" ] + then + mkdir -p "${cert_dir}" + (umask 077; "${pkgs.openssl}/bin/openssl" genrsa -out "''${key}" 2048) && + "${pkgs.openssl}/bin/openssl" req -new -key "''${key}" -x509 -subj "/CN=''${fqdn}" \ + -days 3650 -out "''${cert}" + fi + '' + else ""; +in { # Set the correct permissions for dovecot vmail folder. See # . We choose @@ -23,8 +44,18 @@ # dovecot gets started. services.dovecot2.preStart = '' - mkdir -p ${mail_dir} - chgrp ${vmail_group_name} ${mail_dir} - chmod 02770 ${mail_dir} + # Create mail directory and set permissions + mkdir -p "${mail_dir}" + chgrp "${vmail_group_name}" "${mail_dir}" + chmod 02770 "${mail_dir}" + + ${create_certificate} + ''; + + # Check for certificate before both postfix and dovecot to make sure it + # exists. + services.postfix.preStart = + '' + ${create_certificate} ''; }