diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000..ecdf6b8
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,260 @@
+
+# nixos-mailserver: a simple mail server
+# Copyright (C) 2016-2017 Robin Raymond
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.mailserver;
+in
+{
+ options.mailserver = {
+ enable = mkEnableOption "nixos-mailserver";
+
+ domain = mkOption {
+ type = types.str;
+ example = "example.com";
+ description = "The domain that this mail server serves. So far only one domain is supported";
+ };
+
+ hostPrefix = mkOption {
+ type = types.str;
+ default = "mail";
+ description = ''
+ The prefix of the FQDN of the server. In this example the FQDN of the server
+ is given by 'mail.example.com'
+ '';
+ };
+
+ loginAccounts = mkOption {
+ type = types.loaOf (types.submodule ({ name, ... }: {
+ options = {
+ name = mkOption {
+ type = types.str;
+ example = "user1";
+ description = "Username";
+ };
+
+ hashedPassword = mkOption {
+ type = types.str;
+ example = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
+ description = ''
+ Hashed password. Use `mkpasswd` as follows
+
+ ```
+ mkpasswd -m sha-512 "super secret password"
+ ```
+ '';
+ };
+ };
+
+ config.name = mkDefault name;
+ }));
+ example = {
+ user1 = {
+ hashedPassword = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
+ };
+ user2 = {
+ hashedPassword = "$6$oE0ZNv2n7Vk9gOf$9xcZWCCLGdMflIfuA0vR1Q1Xblw6RZqPrP94mEit2/81/7AKj2bqUai5yPyWE.QYPyv6wLMHZvjw3Rlg7yTCD/";
+ };
+ };
+ description = ''
+ The login account of the domain. Every account is mapped to a unix user,
+ e.g. `user1@example.com`. To generate the passwords use `mkpasswd` as
+ follows
+
+ ```
+ mkpasswd -m sha-512 "super secret password"
+ ```
+ '';
+ default = {};
+ };
+
+ virtualAliases = mkOption {
+ type = types.attrsOf (types.enum (builtins.attrNames cfg.loginAccounts));
+ example = {
+ info = "user1";
+ postmaster = "user1";
+ abuse = "user1";
+ };
+ description = ''
+ Virtual Aliases. A virtual alias `info = "user1"` means that
+ all mail to `info@example.com` is forwarded to `user1@example.com`. Note
+ that it is expected that `postmaster@example.com` and `abuse@example.com` is
+ forwarded to some valid email address. (Alternatively you can create login
+ accounts for `postmaster` and (or) `abuse`).
+ '';
+ default = {};
+ };
+
+ vmailUIDStart = mkOption {
+ type = types.int;
+ default = 5000;
+ description = ''
+ The unix UID where the loginAccounts are created. 5000 means that the first
+ user will get 5000, the second 5001, ...
+ '';
+ };
+
+ vmailUserName = mkOption {
+ type = types.str;
+ default = "vmail";
+ description = ''
+ The user name and group name of the user that owns the directory where all
+ the mail is stored.
+ '';
+ };
+
+ vmailGroupName = mkOption {
+ type = types.str;
+ default = "vmail";
+ description = ''
+ The user name and group name of the user that owns the directory where all
+ the mail is stored.
+ '';
+ };
+
+ mailDirectory = mkOption {
+ type = types.string;
+ default = "/var/vmail";
+ description = ''
+ Where to store the mail.
+ '';
+ };
+
+ certificateScheme = mkOption {
+ type = types.enum [ 1 2 ];
+ default = 2;
+ description = ''
+ Certificate Files. There are three options for these.
+
+ 1) You specify locations and manually copy certificates there.
+ 2) You let the server create new (self signed) certificates on the fly.
+ 3) You let the server create a certificate via `Let's Encrypt`. Note that
+ this implies that a stripped down webserver has to be started. This also
+ 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) and 2) work as of yet.
+ '';
+ };
+
+ certificateFile = mkOption {
+ type = types.path;
+ example = "/root/mail-server.crt";
+ description = ''
+ Scheme 1)
+ Location of the certificate
+ '';
+ };
+
+ keyFile = mkOption {
+ type = types.path;
+ example = "/root/mail-server.key";
+ description = ''
+ Scheme 1)
+ Location of the key file
+ '';
+ };
+
+ certificateDirectory = mkOption {
+ type = types.path;
+ default = "/var/certs";
+ description = ''
+ Sceme 2)
+ This is the folder where the certificate will be created. The name is
+ hardcoded to "cert-.pem" and "key-.pem" and the
+ certificate is valid for 10 years.
+ '';
+ };
+
+ enableImap = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable imap / pop3. Both variants are only supported in the
+ (sane) startTLS configuration. (TODO: Allow SSL ports). The ports are
+
+ 110 - Pop3
+ 143 - IMAP
+ 587 - SMTP with login
+ '';
+ };
+
+ enablePop3 = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable POP3. Both variants are only supported in the
+ (sane) startTLS configuration. (TODO: Allow SSL ports). The ports are
+
+ 110 - Pop3
+ 143 - IMAP
+ 587 - SMTP with login
+ '';
+ };
+
+ # imapSsl = mkOption {} #< TODO
+ # pop3Ssl = mkOption {} #< TODO
+
+ virusScanning = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to activate virus scanning. Note that virus scanning is _very_
+ expensive memory wise.
+ '';
+ };
+
+ dkimSigning = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to activate dkim signing.
+ TODO: Explain how to put signature into domain record
+ '';
+ };
+
+ dkimSelector = mkOption {
+ type = types.string;
+ default = "mail";
+ description = ''
+
+ '';
+ };
+
+ dkimKeyDirectory = mkOption {
+ type = types.path;
+ default = "/var/dkim";
+ description = ''
+
+ '';
+ };
+ };
+
+ imports = [
+ ./mail-server/clamav.nix
+ ./mail-server/users.nix
+ ./mail-server/environment.nix
+ ./mail-server/networking.nix
+ ./mail-server/systemd.nix
+ ./mail-server/dovecot.nix
+ ./mail-server/postfix.nix
+ ./mail-server/rmilter.nix
+ ];
+}
diff --git a/mail-config.nix b/mail-config.nix
deleted file mode 100644
index a8e3203..0000000
--- a/mail-config.nix
+++ /dev/null
@@ -1,161 +0,0 @@
-# nixos-mailserver: a simple mail server
-# Copyright (C) 2016-2017 Robin Raymond
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see
-
-{ config, pkgs, ... }:
-
-let
-
- #
- # The domain that this mail server serves. So far only one domain is supported
- #
- domain = "example.com";
-
- #
- # The prefix of the FQDN of the server. In this example the FQDN of the server
- # is given by 'mail.example.com'
- #
- host_prefix = "mail";
-
- #
- # The login account of the domain. Every account is mapped to a unix user,
- # e.g. `user1@example.com`. To generate the passwords use `mkpasswd` as
- # follows
- #
- # ```
- # mkpasswd -m sha-512 "super secret password"
- # ```
- #
- login_accounts = [
- { name = "user1";
- password = "$6$evQJs5CFQyPAW09S$Cn99Y8.QjZ2IBnSu4qf1vBxDRWkaIZWOtmu1Ddsm3.H3CFpeVc0JU4llIq8HQXgeatvYhh5O33eWG3TSpjzu6/";
- }
- { name = "user2";
- password = "$6$oE0ZNv2n7Vk9gOf$9xcZWCCLGdMflIfuA0vR1Q1Xblw6RZqPrP94mEit2/81/7AKj2bqUai5yPyWE.QYPyv6wLMHZvjw3Rlg7yTCD/";
- }
- ];
-
- #
- # Virtual Aliases. A virtual alias { from = "info"; to = "user1"; } means that
- # all mail to `info@example.com` is forwarded to `user1@example.com`. Note
- # that it is expected that `postmaster@example.com` and `abuse@example.com` is
- # forwarded to some valid email address. (Alternatively you can create login
- # accounts for `postmaster` and (or) `abuse`).
- #
- valiases = [
- { from = "info";
- to = "user1";
- }
- { from = "postmaster";
- to = "user1";
- }
- { from = "abuse";
- to = "user1";
- }
- ];
-
- #
- # The unix UID where the login_accounts are created. 5000 means that the first
- # user will get 5000, the second 5001, ...
- #
- vmail_id_start = 5000;
-
- #
- # The user name and group name of the user that owns the directory where all
- # the mail is stored.
- #
- vmail_user_name = "vmail";
- vmail_group_name = "vmail";
-
- #
- # Where to store the mail.
- #
- mail_dir = "/var/vmail";
-
- #
- # Certificate Files. There are three options for these.
- #
- # 1) You specify locations and manually copy certificates there.
- # 2) You let the server create new (self signed) certificates on the fly.
- # 3) You let the server create a certificate via `Let's Encrypt`. Note that
- # this implies that a stripped down webserver has to be started. This also
- # 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) 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)
- # 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 = "/var/certs";
-
- #
- # Whether to enable imap / pop3. Both variants are only supported in the
- # (sane) startTLS configuration. (TODO: Allow SSL ports). The ports are
- #
- # 110 - Pop3
- # 143 - IMAP
- # 587 - SMTP with login
- #
- enable_imap = true;
- enable_pop3 = false;
- # imap_ssl = false; #< TODO
- # pop3_ssl = false; #< TODO
-
- #
- # Whether to activate virus scanning. Note that virus scanning is _very_
- # expensive memory wise.
- #
- virus_scanning = false;
-
- #
- # Whether to activate dkim signing.
- # TODO: Explain how to put signature into domain record
- #
- dkim_signing = true;
- dkim_selector = "mail";
- dkim_dir = "/var/dkim";
-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 dkim_selector
- dkim_dir certificate_scheme cert_file key_file cert_dir;
- };
-
- environment = import ./mail-server/environment.nix {
- inherit pkgs certificate_scheme;
- };
-
- networking = import ./mail-server/networking.nix {
- inherit domain host_prefix enable_imap enable_pop3;
- };
-
- systemd = import ./mail-server/systemd.nix {
- inherit mail_dir vmail_group_name certificate_scheme cert_dir host_prefix
- domain pkgs dkim_selector dkim_dir;
- };
-
- users = import ./mail-server/users.nix {
- inherit vmail_id_start vmail_user_name vmail_group_name domain mail_dir
- login_accounts;
- };
-}
diff --git a/mail-server/clamav.nix b/mail-server/clamav.nix
index acea48f..5542a95 100644
--- a/mail-server/clamav.nix
+++ b/mail-server/clamav.nix
@@ -14,10 +14,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ virus_scanning }:
+{ config, pkgs, lib, ... }:
+let
+ cfg = config.mailserver;
+in
{
- daemon.enable = virus_scanning;
- updater.enable = virus_scanning;
+ config = lib.mkIf cfg.virusScanning {
+ services.clamav.daemon.enable = true;
+ services.clamav.updater.enable = true;
+ };
}
diff --git a/mail-server/common.nix b/mail-server/common.nix
new file mode 100644
index 0000000..f32d898
--- /dev/null
+++ b/mail-server/common.nix
@@ -0,0 +1,36 @@
+# nixos-mailserver: a simple mail server
+# Copyright (C) 2016-2017 Robin Raymond
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+
+{ config }:
+
+let
+ cfg = config.mailserver;
+in
+{
+ # cert :: PATH
+ certificatePath = if cfg.certificateScheme == 1
+ then cfg.certificateFile
+ else if cfg.certificateScheme == 2
+ then "${cfg.certificateDirectory}/cert-${cfg.domain}.pem"
+ else "";
+
+ # key :: PATH
+ keyPath = if cfg.certificateScheme == 1
+ then cfg.keyFile
+ else if cfg.certificateScheme == 2
+ then "${cfg.certificateDirectory}/key-${cfg.domain}.pem"
+ else "";
+}
diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix
index b294ac1..3caca10 100644
--- a/mail-server/dovecot.nix
+++ b/mail-server/dovecot.nix
@@ -14,73 +14,80 @@
# 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, cert,
-key }:
+{ config, pkgs, lib, ... }:
+
+with (import ./common.nix { inherit config; });
let
+ cfg = config.mailserver;
+
# maildir in format "/${domain}/${user}/"
- dovecot_maildir = "maildir:${mail_dir}/%d/%n/";
+ dovecot_maildir = "maildir:${cfg.mailDirectory}/%d/%n/";
in
{
- enable = true;
- enableImap = enable_imap;
- enablePop3 = enable_pop3;
- mailGroup = vmail_group_name;
- mailUser = vmail_user_name;
- mailLocation = dovecot_maildir;
- sslServerCert = cert;
- sslServerKey = key;
- enableLmtp = true;
- extraConfig = ''
- #Extra Config
- mail_access_groups = ${vmail_group_name}
- ssl = required
+ config = with cfg; lib.mkIf enable {
+ services.dovecot2 = {
+ enable = true;
+ enableImap = enableImap;
+ enablePop3 = enablePop3;
+ mailGroup = vmailGroupName;
+ mailUser = vmailUserName;
+ mailLocation = dovecot_maildir;
+ sslServerCert = certificatePath;
+ sslServerKey = keyPath;
+ enableLmtp = true;
+ extraConfig = ''
+ #Extra Config
+ mail_access_groups = ${vmailGroupName}
+ ssl = required
- service lmtp {
- unix_listener /var/lib/postfix/queue/private/dovecot-lmtp {
+ service lmtp {
+ unix_listener /var/lib/postfix/queue/private/dovecot-lmtp {
group = postfix
mode = 0600
user = postfix # TODO: < make variable
- }
- }
+ }
+ }
- service auth {
- unix_listener /var/lib/postfix/queue/private/auth {
+ service auth {
+ unix_listener /var/lib/postfix/queue/private/auth {
mode = 0660
user = postfix # TODO: < make variable
group = postfix # TODO: < make variable
- }
- }
+ }
+ }
- auth_mechanisms = plain login
+ auth_mechanisms = plain login
- namespace inbox {
+ namespace inbox {
- #prefix = INBOX.
- # the namespace prefix isn't added again to the mailbox names.
- inbox = yes
- # ...
+ #prefix = INBOX.
+ # the namespace prefix isn't added again to the mailbox names.
+ inbox = yes
+ # ...
- mailbox "Trash" {
- auto = no
- special_use = \Trash
- }
+ mailbox "Trash" {
+ auto = no
+ special_use = \Trash
+ }
- mailbox "Junk" {
- auto = subscribe
- special_use = \Junk
- }
+ mailbox "Junk" {
+ auto = subscribe
+ special_use = \Junk
+ }
- mailbox "Drafts" {
- auto = subscribe
- special_use = \Drafts
- }
+ mailbox "Drafts" {
+ auto = subscribe
+ special_use = \Drafts
+ }
- mailbox "Sent" {
- auto = subscribe
- special_use = \Sent
- }
- }
- '';
+ mailbox "Sent" {
+ auto = subscribe
+ special_use = \Sent
+ }
+ }
+ '';
+ };
+ };
}
diff --git a/mail-server/environment.nix b/mail-server/environment.nix
index 3b61430..48e68c7 100644
--- a/mail-server/environment.nix
+++ b/mail-server/environment.nix
@@ -14,10 +14,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ pkgs, certificate_scheme }:
+{ config, pkgs, lib, ... }:
+let
+ cfg = config.mailserver;
+in
{
- systemPackages = with pkgs; [
- dovecot opendkim openssh postfix clamav rspamd rmilter
- ] ++ (if certificate_scheme == 2 then [ openssl ] else []);
+ config = with cfg; lib.mkIf enable {
+ environment.systemPackages = with pkgs; [
+ dovecot opendkim openssh postfix clamav rspamd rmilter
+ ] ++ (if certificateScheme == 2 then [ openssl ] else []);
+ };
}
diff --git a/mail-server/networking.nix b/mail-server/networking.nix
index fa3ff7e..62b2f3b 100644
--- a/mail-server/networking.nix
+++ b/mail-server/networking.nix
@@ -14,14 +14,20 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ domain, host_prefix, enable_imap, enable_pop3 }:
+{ config, pkgs, lib, ... }:
+let
+ cfg = config.mailserver;
+in
{
- hostName = "${host_prefix}.${domain}";
+ config = with cfg; lib.mkIf enable {
- firewall = {
- allowedTCPPorts = [ 25 587 ]
- ++ (if enable_imap then [ 143 ] else [])
- ++ (if enable_pop3 then [ 110 ] else []);
+ networking.hostName = "${hostPrefix}.${domain}";
+
+ networking.firewall = {
+ allowedTCPPorts = [ 25 587 ]
+ ++ (if enableImap then [ 143 ] else [])
+ ++ (if enablePop3 then [ 110 ] else []);
+ };
};
}
diff --git a/mail-server/postfix.nix b/mail-server/postfix.nix
index d9ff629..b914ad5 100644
--- a/mail-server/postfix.nix
+++ b/mail-server/postfix.nix
@@ -14,25 +14,25 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ mail_dir, domain, valiases, cert, key }:
+{ config, pkgs, lib, ... }:
+
+with (import ./common.nix { inherit config; });
let
- # valiasToString :: { from = "..."; to = "..." } -> String
- valiasToString = x: "${x.from}@${domain} ${x.to}@${domain}\n";
+ cfg = config.mailserver;
# valiases_postfix :: [ String ]
- valiases_postfix = map valiasToString valiases;
-
- # concatString :: [ String ] -> String
- concatString = l: if l == []
- then ""
- else (builtins.head l) + (concatString (builtins.tail l));
+ valiases_postfix = map
+ (from:
+ let to = cfg.virtualAliases.${from};
+ in "${from}@${cfg.domain} ${to}@${cfg.domain}")
+ (builtins.attrNames cfg.virtualAliases);
# valiases_file :: Path
- valiases_file = builtins.toFile "valias" (concatString valiases_postfix);
+ valiases_file = builtins.toFile "valias" (lib.concatStringsSep "\n" valiases_postfix);
# vhosts_file :: Path
- vhosts_file = builtins.toFile "vhosts" domain;
+ vhosts_file = builtins.toFile "vhosts" cfg.domain;
# vaccounts_file :: Path
# see
@@ -43,50 +43,54 @@ let
in
{
- enable = true;
- networksStyle = "host";
- mapFiles."valias" = valiases_file;
- mapFiles."vaccounts" = vaccounts_file;
- sslCert = cert;
- sslKey = key;
- enableSubmission = true;
+ config = with cfg; lib.mkIf enable {
- extraConfig =
- ''
+ services.postfix = {
+ enable = true;
+ networksStyle = "host";
+ mapFiles."valias" = valiases_file;
+ mapFiles."vaccounts" = vaccounts_file;
+ sslCert = certificatePath;
+ sslKey = keyPath;
+ enableSubmission = true;
- # Extra Config
+ extraConfig =
+ ''
+ # Extra Config
- smtpd_banner = $myhostname ESMTP NO UCE
- smtpd_tls_auth_only = yes
- disable_vrfy_command = yes
- message_size_limit = 20971520
+ smtpd_banner = $myhostname ESMTP NO UCE
+ smtpd_tls_auth_only = yes
+ disable_vrfy_command = yes
+ message_size_limit = 20971520
- # virtual mail system
- virtual_uid_maps = static:5000
- virtual_gid_maps = static:5000
- virtual_mailbox_base = ${mail_dir}
- virtual_mailbox_domains = ${vhosts_file}
- virtual_alias_maps = hash:/var/lib/postfix/conf/valias
- virtual_transport = lmtp:unix:private/dovecot-lmtp
+ # virtual mail system
+ virtual_uid_maps = static:5000
+ virtual_gid_maps = static:5000
+ virtual_mailbox_base = ${mailDirectory}
+ virtual_mailbox_domains = ${vhosts_file}
+ virtual_alias_maps = hash:/var/lib/postfix/conf/valias
+ virtual_transport = lmtp:unix:private/dovecot-lmtp
- # sasl with dovecot
- smtpd_sasl_type = dovecot
- smtpd_sasl_path = private/auth
- smtpd_sasl_auth_enable = yes
- smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
- '';
+ # sasl with dovecot
+ smtpd_sasl_type = dovecot
+ smtpd_sasl_path = private/auth
+ smtpd_sasl_auth_enable = yes
+ smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
+ '';
- submissionOptions =
- {
- smtpd_tls_security_level = "encrypt";
- smtpd_sasl_auth_enable = "yes";
- smtpd_sasl_type = "dovecot";
- smtpd_sasl_path = "private/auth";
- smtpd_sasl_security_options = "noanonymous";
- smtpd_sasl_local_domain = "$myhostname";
- smtpd_client_restrictions = "permit_sasl_authenticated,reject";
- smtpd_sender_login_maps = "hash:/etc/postfix/vaccounts";
- smtpd_sender_restrictions = "reject_sender_login_mismatch";
- smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
+ submissionOptions =
+ {
+ smtpd_tls_security_level = "encrypt";
+ smtpd_sasl_auth_enable = "yes";
+ smtpd_sasl_type = "dovecot";
+ smtpd_sasl_path = "private/auth";
+ smtpd_sasl_security_options = "noanonymous";
+ smtpd_sasl_local_domain = "$myhostname";
+ smtpd_client_restrictions = "permit_sasl_authenticated,reject";
+ smtpd_sender_login_maps = "hash:/etc/postfix/vaccounts";
+ smtpd_sender_restrictions = "reject_sender_login_mismatch";
+ smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
+ };
+ };
};
}
diff --git a/mail-server/rmilter.nix b/mail-server/rmilter.nix
index 911eaf8..1f30ede 100644
--- a/mail-server/rmilter.nix
+++ b/mail-server/rmilter.nix
@@ -14,10 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ domain, virus_scanning, dkim_signing, dkim_dir, dkim_selector }:
+{ config, pkgs, lib, ... }:
let
- clamav = if virus_scanning
+ cfg = config.mailserver;
+
+ clamav = if cfg.virusScanning
then
''
clamav {
@@ -25,14 +27,14 @@ let
};
''
else "";
- dkim = if dkim_signing
+ dkim = if cfg.dkimSigning
then
''
dkim {
domain {
- key = "${dkim_dir}";
+ key = "${cfg.dkimKeyDirectory}";
domain = "*";
- selector = "${dkim_selector}";
+ selector = "${cfg.dkimSelector}";
};
sign_alg = sha256;
auth_only = yes;
@@ -41,15 +43,19 @@ let
else "";
in
{
- enable = true;
- # debug = true;
- postfix.enable = true;
- rspamd.enable = true;
- extraConfig =
- ''
- ${clamav}
+ config = with cfg; lib.mkIf enable {
+ services.rmilter = {
+ enable = true;
+ #debug = true;
+ postfix.enable = true;
+ rspamd.enable = true;
+ extraConfig =
+ ''
+ ${clamav}
- ${dkim}
- '';
+ ${dkim}
+ '';
+ };
+ };
}
diff --git a/mail-server/services.nix b/mail-server/services.nix
index ae007fe..2cebdaf 100644
--- a/mail-server/services.nix
+++ b/mail-server/services.nix
@@ -14,45 +14,31 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ mail_dir, vmail_user_name, vmail_group_name, valiases, domain, enable_imap,
-enable_pop3, virus_scanning, dkim_signing, dkim_selector, dkim_dir,
-certificate_scheme, cert_file, key_file, cert_dir }:
+
+{ config, pkgs, lib, ... }:
let
+ cfg = config.mailserver;
+
# cert :: PATH
- cert = if certificate_scheme == 1
- then cert_file
- else if certificate_scheme == 2
- then "${cert_dir}/cert-${domain}.pem"
+ cert = if cfg.certificateScheme == 1
+ then cfg.certificateFile
+ else if cfg.certificateScheme == 2
+ then "${cfg.certificateDirectory}/cert-${cfg.domain}.pem"
else "";
# key :: PATH
- key = if certificate_scheme == 1
- then key_file
- else if certificate_scheme == 2
- then "${cert_dir}/key-${domain}.pem"
+ key = if cfg.certificateScheme == 1
+ then cfg.keyFile
+ else if cfg.certificateScheme == 2
+ then "${cfg.certificateDirectory}/key-${cfg.domain}.pem"
else "";
in
{
- # rspamd
- rspamd = {
- enable = true;
- };
-
- rmilter = import ./rmilter.nix {
- inherit domain virus_scanning dkim_signing dkim_selector dkim_dir;
- };
-
- postfix = import ./postfix.nix {
- inherit mail_dir domain valiases cert key;
- };
-
- dovecot2 = import ./dovecot.nix {
- inherit vmail_group_name vmail_user_name mail_dir enable_imap
- enable_pop3 cert key;
- };
-
- clamav = import ./clamav.nix {
- inherit virus_scanning;
- };
+
+ imports = [
+ ./rmilter.nix
+ ./postfix.nix key
+ ./dovecot.nix
+ ];
}
diff --git a/mail-server/systemd.nix b/mail-server/systemd.nix
index c862b9e..9cae899 100644
--- a/mail-server/systemd.nix
+++ b/mail-server/systemd.nix
@@ -14,22 +14,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ pkgs, mail_dir, vmail_group_name, certificate_scheme, cert_dir, host_prefix,
-domain, dkim_selector, dkim_dir}:
+{ config, pkgs, lib, ... }:
let
- create_certificate = if certificate_scheme == 2 then
+ cfg = config.mailserver;
+
+ create_certificate = if cfg.certificateScheme == 2 then
''
# Create certificates if they do not exist yet
- dir="${cert_dir}"
- fqdn="${host_prefix}.${domain}"
+ dir="${cfg.certificateDirectory}"
+ fqdn="${cfg.hostPrefix}.${cfg.domain}"
case $fqdn in /*) fqdn=$(cat "$fqdn");; esac
- key="''${dir}/key-${domain}.pem";
- cert="''${dir}/cert-${domain}.pem";
+ key="''${dir}/key-${cfg.domain}.pem";
+ cert="''${dir}/cert-${cfg.domain}.pem";
if [ ! -f "''${key}" ] || [ ! -f "''${cert}" ]
then
- mkdir -p "${cert_dir}"
+ mkdir -p "${cfg.certificateDirectory}"
(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}"
@@ -37,47 +38,50 @@ let
''
else "";
- dkim_key = "${dkim_dir}/${dkim_selector}.private";
- dkim_txt = "${dkim_dir}/${dkim_selector}.txt";
+ dkim_key = "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.private";
+ dkim_txt = "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.txt";
create_dkim_cert =
''
# Create dkim dir
- mkdir -p "${dkim_dir}"
- chown rmilter:rmilter "${dkim_dir}"
+ mkdir -p "${cfg.dkimKeyDirectory}"
+ chown rmilter:rmilter "${cfg.dkimKeyDirectory}"
if [ ! -f "${dkim_key}" ] || [ ! -f "${dkim_txt}" ]
then
- ${pkgs.opendkim}/bin/opendkim-genkey -s "${dkim_selector}" \
- -d ${domain} \
- --directory="${dkim_dir}"
+ ${pkgs.opendkim}/bin/opendkim-genkey -s "${cfg.dkimSelector}" \
+ -d ${cfg.domain} \
+ --directory="${cfg.dkimKeyDirectory}"
chown rmilter:rmilter "${dkim_key}"
fi
'';
in
{
- # Make sure postfix gets started first, so that the certificates are in place
- services.dovecot2.after = [ "postfix.service" ];
+ config = with cfg; lib.mkIf enable {
+ # Make sure postfix gets started first, so that the certificates are in place
+ systemd.services.dovecot2.after = [ "postfix.service" ];
- # Create certificates and maildir folder
- services.postfix = {
- preStart =
- ''
+ # Create certificates and maildir folder
+ systemd.services.postfix = {
+ preStart =
+ ''
# Create mail directory and set permissions. See
# .
mkdir -p "${mail_dir}"
chgrp "${vmail_group_name}" "${mail_dir}"
chmod 02770 "${mail_dir}"
- ${create_certificate}
- '';
- };
+ ${create_certificate}
+ '';
+ };
+
+ # Create dkim certificates
+ systemd.services.rmilter = {
+ preStart =
+ ''
+ ${create_dkim_cert}
+ '';
+ };
- # Create dkim certificates
- services.rmilter = {
- preStart =
- ''
- ${create_dkim_cert}
- '';
};
}
diff --git a/mail-server/users.nix b/mail-server/users.nix
index e84de1b..a8cbcc9 100644
--- a/mail-server/users.nix
+++ b/mail-server/users.nix
@@ -14,37 +14,41 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-{ vmail_id_start, vmail_user_name, vmail_group_name, domain, mail_dir,
-login_accounts }:
+{ config, pkgs, lib, ... }:
+
+with config.mailserver;
let
vmail_user = [{
- name = vmail_user_name;
+ name = vmailUserName;
isNormalUser = false;
- uid = vmail_id_start;
- home = mail_dir;
+ uid = vmailUIDStart;
+ home = mailDirectory;
createHome = true;
- group = vmail_group_name;
+ group = vmailGroupName;
}];
# accountsToUser :: String -> UserRecord
- accountsToUser = x: {
- name = x.name + "@" + domain;
+ accountsToUser = account: {
+ name = account.name + "@" + domain;
isNormalUser = false;
- group = vmail_group_name;
- hashedPassword = x.password;
+ group = vmailGroupName;
+ inherit (account) hashedPassword;
};
# mail_user :: [ UserRecord ]
- mail_user = map accountsToUser login_accounts;
+ mail_user = map accountsToUser (lib.attrValues loginAccounts);
in
{
- # set the vmail gid to a specific value
- groups = {
- vmail = { gid = vmail_id_start; };
- };
- # define all users
- extraUsers = vmail_user ++ mail_user;
+ config = lib.mkIf enable {
+ # set the vmail gid to a specific value
+ users.groups = {
+ vmail = { gid = vmailUIDStart; };
+ };
+
+ # define all users
+ users.extraUsers = vmail_user ++ mail_user;
+ };
}
diff --git a/nixops/single-server.nix b/nixops/single-server.nix
index a6aa831..a96da0b 100644
--- a/nixops/single-server.nix
+++ b/nixops/single-server.nix
@@ -5,7 +5,12 @@
{ config, pkgs, ... }:
{
imports = [
- ./../mail-config.nix
+ ./../default.nix
];
+
+ mailserver = {
+ enable = true;
+ domain = "example.com";
+ };
};
}