From 692a677194b00cbdcb11a59b732e2decbe237c8c Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Wed, 30 Aug 2017 00:58:44 +0200 Subject: [PATCH 01/12] make configuration a nixos module --- default.nix | 277 +++++++++++++++++++++++++++++++++++++ mail-config.nix | 161 --------------------- mail-server/networking.nix | 2 +- mail-server/postfix.nix | 18 +-- mail-server/services.nix | 4 +- mail-server/users.nix | 10 +- 6 files changed, 292 insertions(+), 180 deletions(-) create mode 100644 default.nix delete mode 100644 mail-config.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..96e6ad6 --- /dev/null +++ b/default.nix @@ -0,0 +1,277 @@ + +# 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"; + }; + + host_prefix = 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' + ''; + }; + + login_accounts = 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" + ``` + ''; + }; + + valiases = mkOption { + type = types.attrsOf (types.enum (builtins.attrNames cfg.login_accounts)); + 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`). + ''; + }; + + vmail_id_start = mkOption { + type = types.int; + default = 5000; + description = '' + The unix UID where the login_accounts are created. 5000 means that the first + user will get 5000, the second 5001, ... + ''; + }; + + vmail_user_name = 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. + ''; + }; + + vmail_group_name = 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. + ''; + }; + + mail_dir = mkOption { + type = types.string; + default = "/var/vmail"; + description = '' + Where to store the mail. + ''; + }; + + certificate_scheme = 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. + ''; + }; + + cert_file = mkOption { + type = types.path; + example = "/root/mail-server.crt"; + description = '' + Scheme 1) + Location of the certificate + ''; + }; + + key_file = mkOption { + type = types.path; + example = "/root/mail-server.key"; + description = '' + Scheme 1) + Location of the key file + ''; + }; + + cert_dir = 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. + ''; + }; + + enable_imap = 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 + ''; + }; + + enable_pop3 = 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 + + virus_scanning = mkOption { + type = types.bool; + default = false; + description = '' + Whether to activate virus scanning. Note that virus scanning is _very_ + expensive memory wise. + ''; + }; + + dkim_signing = mkOption { + type = types.bool; + default = true; + description = '' + Whether to activate dkim signing. + TODO: Explain how to put signature into domain record + ''; + }; + + dkim_selector = mkOption { + type = types.string; + default = "mail"; + description = '' + + ''; + }; + + dkim_dir = mkOption { + type = types.path; + default = "/var/dkim"; + description = '' + + ''; + }; + }; + + config = mkIf cfg.enable { + services = import ./mail-server/services.nix { + inherit lib; + inherit (cfg) 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; + inherit (cfg) certificate_scheme; + }; + + networking = import ./mail-server/networking.nix { + inherit (cfg) domain host_prefix enable_imap enable_pop3; + }; + + systemd = import ./mail-server/systemd.nix { + inherit pkgs; + inherit (cfg) mail_dir vmail_group_name certificate_scheme cert_dir host_prefix + domain dkim_selector dkim_dir; + }; + + users = import ./mail-server/users.nix { + inherit lib; + inherit (cfg) vmail_id_start vmail_user_name vmail_group_name domain mail_dir + login_accounts; + }; + }; +} 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/networking.nix b/mail-server/networking.nix index bd8ccd2..990c13a 100644 --- a/mail-server/networking.nix +++ b/mail-server/networking.nix @@ -17,7 +17,7 @@ { domain, host_prefix, enable_imap, enable_pop3 }: { - hostName = "${host_prefix}.${domain}"; + #hostName = "${host_prefix}.${domain}"; firewall = { enable = true; diff --git a/mail-server/postfix.nix b/mail-server/postfix.nix index d9ff629..fb4dbc1 100644 --- a/mail-server/postfix.nix +++ b/mail-server/postfix.nix @@ -14,22 +14,18 @@ # 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 }: +{ lib, mail_dir, domain, valiases, cert, key }: let - # valiasToString :: { from = "..."; to = "..." } -> String - valiasToString = x: "${x.from}@${domain} ${x.to}@${domain}\n"; - # 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 = valiases.${from}; + in "${from}@${domain} ${to}@${domain}") + (builtins.attrNames valiases); # 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; diff --git a/mail-server/services.nix b/mail-server/services.nix index ae007fe..259cbfe 100644 --- a/mail-server/services.nix +++ b/mail-server/services.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, vmail_user_name, vmail_group_name, valiases, domain, enable_imap, +{ lib, 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 }: @@ -44,7 +44,7 @@ in }; postfix = import ./postfix.nix { - inherit mail_dir domain valiases cert key; + inherit lib mail_dir domain valiases cert key; }; dovecot2 = import ./dovecot.nix { diff --git a/mail-server/users.nix b/mail-server/users.nix index e84de1b..de1c1ab 100644 --- a/mail-server/users.nix +++ b/mail-server/users.nix @@ -14,7 +14,7 @@ # 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, +{ lib, vmail_id_start, vmail_user_name, vmail_group_name, domain, mail_dir, login_accounts }: let @@ -28,15 +28,15 @@ let }]; # accountsToUser :: String -> UserRecord - accountsToUser = x: { - name = x.name + "@" + domain; + accountsToUser = account: { + name = account.name + "@" + domain; isNormalUser = false; group = vmail_group_name; - hashedPassword = x.password; + inherit (account) hashedPassword; }; # mail_user :: [ UserRecord ] - mail_user = map accountsToUser login_accounts; + mail_user = map accountsToUser (lib.attrValues login_accounts); in { From 691f034f9dbef8f58ac467099794d860315f6a28 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 12:58:25 +0200 Subject: [PATCH 02/12] update nixops for module config --- nixops/single-server.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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"; + }; }; } From 061054926d7c1affff670361ccdccea0e9c10c9c Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 12:59:07 +0200 Subject: [PATCH 03/12] make clamav a module --- default.nix | 10 ++++++++-- mail-server/clamav.nix | 11 ++++++++--- mail-server/services.nix | 4 ---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index 96e6ad6..2edb0eb 100644 --- a/default.nix +++ b/default.nix @@ -82,6 +82,7 @@ in mkpasswd -m sha-512 "super secret password" ``` ''; + default = {}; }; valiases = mkOption { @@ -98,6 +99,7 @@ in forwarded to some valid email address. (Alternatively you can create login accounts for `postmaster` and (or) `abuse`). ''; + default = {}; }; vmail_id_start = mkOption { @@ -245,12 +247,16 @@ in }; }; + imports = [ + ./mail-server/clamav.nix + ]; + config = mkIf cfg.enable { services = import ./mail-server/services.nix { inherit lib; inherit (cfg) 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; + enable_imap enable_pop3 dkim_signing dkim_selector dkim_dir + certificate_scheme cert_file key_file cert_dir virus_scanning; }; environment = import ./mail-server/environment.nix { diff --git a/mail-server/clamav.nix b/mail-server/clamav.nix index acea48f..9bf0737 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.virus_scanning { + services.clamav.daemon.enable = true; + services.clamav.updater.enable = true; + }; } diff --git a/mail-server/services.nix b/mail-server/services.nix index 259cbfe..880536c 100644 --- a/mail-server/services.nix +++ b/mail-server/services.nix @@ -51,8 +51,4 @@ in inherit vmail_group_name vmail_user_name mail_dir enable_imap enable_pop3 cert key; }; - - clamav = import ./clamav.nix { - inherit virus_scanning; - }; } From b5fccc7e39be5a69ea0d4b64e1763ab7f2d019fd Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 13:23:37 +0200 Subject: [PATCH 04/12] camelCase --- default.nix | 43 +++++++++++++++++++------------------ mail-server/clamav.nix | 2 +- mail-server/dovecot.nix | 10 ++++----- mail-server/environment.nix | 4 ++-- mail-server/networking.nix | 4 ++-- mail-server/postfix.nix | 8 +++---- mail-server/rmilter.nix | 4 ++-- mail-server/services.nix | 24 ++++++++++----------- mail-server/systemd.nix | 12 +++++------ mail-server/users.nix | 18 ++++++++-------- 10 files changed, 65 insertions(+), 64 deletions(-) diff --git a/default.nix b/default.nix index 2edb0eb..a2158a6 100644 --- a/default.nix +++ b/default.nix @@ -32,7 +32,7 @@ in description = "The domain that this mail server serves. So far only one domain is supported"; }; - host_prefix = mkOption { + hostPrefix = mkOption { type = types.str; default = "mail"; description = '' @@ -41,7 +41,7 @@ in ''; }; - login_accounts = mkOption { + loginAccounts = mkOption { type = types.loaOf (types.submodule ({ name, ... }: { options = { name = mkOption { @@ -85,8 +85,8 @@ in default = {}; }; - valiases = mkOption { - type = types.attrsOf (types.enum (builtins.attrNames cfg.login_accounts)); + virtualAliases = mkOption { + type = types.attrsOf (types.enum (builtins.attrNames cfg.loginAccounts)); example = { info = "user1"; postmaster = "user1"; @@ -102,16 +102,16 @@ in default = {}; }; - vmail_id_start = mkOption { + vmailUIDStart = mkOption { type = types.int; default = 5000; description = '' - The unix UID where the login_accounts are created. 5000 means that the first + The unix UID where the loginAccounts are created. 5000 means that the first user will get 5000, the second 5001, ... ''; }; - vmail_user_name = mkOption { + vmailUserName = mkOption { type = types.str; default = "vmail"; description = '' @@ -120,7 +120,7 @@ in ''; }; - vmail_group_name = mkOption { + vmailGroupName = mkOption { type = types.str; default = "vmail"; description = '' @@ -129,7 +129,7 @@ in ''; }; - mail_dir = mkOption { + mailDirectory = mkOption { type = types.string; default = "/var/vmail"; description = '' @@ -137,7 +137,7 @@ in ''; }; - certificate_scheme = mkOption { + certificateScheme = mkOption { type = types.enum [ 1 2 ]; default = 2; description = '' @@ -154,7 +154,7 @@ in ''; }; - cert_file = mkOption { + certificateFile = mkOption { type = types.path; example = "/root/mail-server.crt"; description = '' @@ -163,7 +163,7 @@ in ''; }; - key_file = mkOption { + keyFile = mkOption { type = types.path; example = "/root/mail-server.key"; description = '' @@ -212,7 +212,7 @@ in # imapSsl = mkOption {} #< TODO # pop3Ssl = mkOption {} #< TODO - virus_scanning = mkOption { + virusScanning = mkOption { type = types.bool; default = false; description = '' @@ -254,30 +254,31 @@ in config = mkIf cfg.enable { services = import ./mail-server/services.nix { inherit lib; - inherit (cfg) mail_dir vmail_user_name vmail_group_name valiases domain + inherit (cfg) mailDirectory vmailUserName vmailGroupName virtualAliases domain enable_imap enable_pop3 dkim_signing dkim_selector dkim_dir - certificate_scheme cert_file key_file cert_dir virus_scanning; + certificateScheme certificateFile keyFile cert_dir virusScanning; }; environment = import ./mail-server/environment.nix { inherit pkgs; - inherit (cfg) certificate_scheme; + inherit (cfg) certificateScheme; }; networking = import ./mail-server/networking.nix { - inherit (cfg) domain host_prefix enable_imap enable_pop3; + inherit (cfg) domain hostPrefix enable_imap enable_pop3; }; systemd = import ./mail-server/systemd.nix { inherit pkgs; - inherit (cfg) mail_dir vmail_group_name certificate_scheme cert_dir host_prefix - domain dkim_selector dkim_dir; + inherit (cfg) mailDirectory vmailGroupName certificateScheme cert_dir + hostPrefix domain dkim_selector dkim_dir; }; users = import ./mail-server/users.nix { inherit lib; - inherit (cfg) vmail_id_start vmail_user_name vmail_group_name domain mail_dir - login_accounts; + inherit (cfg) vmailUIDStart vmailUserName vmailGroupName domain + mailDirectory + loginAccounts; }; }; } diff --git a/mail-server/clamav.nix b/mail-server/clamav.nix index 9bf0737..5542a95 100644 --- a/mail-server/clamav.nix +++ b/mail-server/clamav.nix @@ -20,7 +20,7 @@ let cfg = config.mailserver; in { - config = lib.mkIf cfg.virus_scanning { + config = lib.mkIf cfg.virusScanning { services.clamav.daemon.enable = true; services.clamav.updater.enable = true; }; diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix index b294ac1..d94539e 100644 --- a/mail-server/dovecot.nix +++ b/mail-server/dovecot.nix @@ -14,27 +14,27 @@ # 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, +{ vmailGroupName, vmailUserName, mailDirectory, enable_imap, enable_pop3, cert, key }: let # maildir in format "/${domain}/${user}/" - dovecot_maildir = "maildir:${mail_dir}/%d/%n/"; + dovecot_maildir = "maildir:${mailDirectory}/%d/%n/"; in { enable = true; enableImap = enable_imap; enablePop3 = enable_pop3; - mailGroup = vmail_group_name; - mailUser = vmail_user_name; + mailGroup = vmailGroupName; + mailUser = vmailUserName; mailLocation = dovecot_maildir; sslServerCert = cert; sslServerKey = key; enableLmtp = true; extraConfig = '' #Extra Config - mail_access_groups = ${vmail_group_name} + mail_access_groups = ${vmailGroupName} ssl = required service lmtp { diff --git a/mail-server/environment.nix b/mail-server/environment.nix index 3b61430..4ffdd2a 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, certificate_scheme }: +{ pkgs, certificateScheme }: { systemPackages = with pkgs; [ dovecot opendkim openssh postfix clamav rspamd rmilter - ] ++ (if certificate_scheme == 2 then [ openssl ] else []); + ] ++ (if certificateScheme == 2 then [ openssl ] else []); } diff --git a/mail-server/networking.nix b/mail-server/networking.nix index 990c13a..81c2d15 100644 --- a/mail-server/networking.nix +++ b/mail-server/networking.nix @@ -14,10 +14,10 @@ # 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 }: +{ domain, hostPrefix, enable_imap, enable_pop3 }: { - #hostName = "${host_prefix}.${domain}"; + #hostName = "${hostPrefix}.${domain}"; firewall = { enable = true; diff --git a/mail-server/postfix.nix b/mail-server/postfix.nix index fb4dbc1..cc2817e 100644 --- a/mail-server/postfix.nix +++ b/mail-server/postfix.nix @@ -14,15 +14,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, mail_dir, domain, valiases, cert, key }: +{ lib, mailDirectory, domain, virtualAliases, cert, key }: let # valiases_postfix :: [ String ] valiases_postfix = map (from: - let to = valiases.${from}; + let to = virtualAliases.${from}; in "${from}@${domain} ${to}@${domain}") - (builtins.attrNames valiases); + (builtins.attrNames virtualAliases); # valiases_file :: Path valiases_file = builtins.toFile "valias" (lib.concatStringsSep "\n" valiases_postfix); @@ -60,7 +60,7 @@ in # virtual mail system virtual_uid_maps = static:5000 virtual_gid_maps = static:5000 - virtual_mailbox_base = ${mail_dir} + 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 diff --git a/mail-server/rmilter.nix b/mail-server/rmilter.nix index 911eaf8..ea62a9f 100644 --- a/mail-server/rmilter.nix +++ b/mail-server/rmilter.nix @@ -14,10 +14,10 @@ # 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 }: +{ domain, virusScanning, dkim_signing, dkim_dir, dkim_selector }: let - clamav = if virus_scanning + clamav = if virusScanning then '' clamav { diff --git a/mail-server/services.nix b/mail-server/services.nix index 880536c..7d2188c 100644 --- a/mail-server/services.nix +++ b/mail-server/services.nix @@ -14,22 +14,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, 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 }: +{ lib, mailDirectory, vmailUserName, vmailGroupName, virtualAliases, domain, enable_imap, +enable_pop3, virusScanning, dkim_signing, dkim_selector, dkim_dir, +certificateScheme, certificateFile, keyFile, cert_dir }: let # cert :: PATH - cert = if certificate_scheme == 1 - then cert_file - else if certificate_scheme == 2 + cert = if certificateScheme == 1 + then certificateFile + else if certificateScheme == 2 then "${cert_dir}/cert-${domain}.pem" else ""; # key :: PATH - key = if certificate_scheme == 1 - then key_file - else if certificate_scheme == 2 + key = if certificateScheme == 1 + then keyFile + else if certificateScheme == 2 then "${cert_dir}/key-${domain}.pem" else ""; in @@ -40,15 +40,15 @@ in }; rmilter = import ./rmilter.nix { - inherit domain virus_scanning dkim_signing dkim_selector dkim_dir; + inherit domain virusScanning dkim_signing dkim_selector dkim_dir; }; postfix = import ./postfix.nix { - inherit lib mail_dir domain valiases cert key; + inherit lib mailDirectory domain virtualAliases cert key; }; dovecot2 = import ./dovecot.nix { - inherit vmail_group_name vmail_user_name mail_dir enable_imap + inherit vmailGroupName vmailUserName mailDirectory enable_imap enable_pop3 cert key; }; } diff --git a/mail-server/systemd.nix b/mail-server/systemd.nix index 817a760..fe3c688 100644 --- a/mail-server/systemd.nix +++ b/mail-server/systemd.nix @@ -14,15 +14,15 @@ # 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, +{ pkgs, mailDirectory, vmailGroupName, certificateScheme, cert_dir, hostPrefix, domain, dkim_selector, dkim_dir}: let - create_certificate = if certificate_scheme == 2 then + create_certificate = if certificateScheme == 2 then '' # Create certificates if they do not exist yet dir="${cert_dir}" - fqdn="${host_prefix}.${domain}" + fqdn="${hostPrefix}.${domain}" case $fqdn in /*) fqdn=$(cat "$fqdn");; esac key="''${dir}/key-${domain}.pem"; cert="''${dir}/cert-${domain}.pem"; @@ -68,9 +68,9 @@ in preStart = '' # Create mail directory and set permissions - mkdir -p "${mail_dir}" - chgrp "${vmail_group_name}" "${mail_dir}" - chmod 02770 "${mail_dir}" + mkdir -p "${mailDirectory}" + chgrp "${vmailGroupName}" "${mailDirectory}" + chmod 02770 "${mailDirectory}" ${create_certificate} ''; diff --git a/mail-server/users.nix b/mail-server/users.nix index de1c1ab..cae2b83 100644 --- a/mail-server/users.nix +++ b/mail-server/users.nix @@ -14,35 +14,35 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, vmail_id_start, vmail_user_name, vmail_group_name, domain, mail_dir, -login_accounts }: +{ lib, vmailUIDStart, vmailUserName, vmailGroupName, domain, mailDirectory, +loginAccounts }: 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 = account: { name = account.name + "@" + domain; isNormalUser = false; - group = vmail_group_name; + group = vmailGroupName; inherit (account) hashedPassword; }; # mail_user :: [ UserRecord ] - mail_user = map accountsToUser (lib.attrValues login_accounts); + mail_user = map accountsToUser (lib.attrValues loginAccounts); in { # set the vmail gid to a specific value groups = { - vmail = { gid = vmail_id_start; }; + vmail = { gid = vmailUIDStart; }; }; # define all users From ebb2a5caf7c207ed4a8e52f95a6739b74f19eb5e Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 13:29:49 +0200 Subject: [PATCH 05/12] camelCase 2 --- default.nix | 23 ++++++++++++----------- mail-server/dovecot.nix | 6 +++--- mail-server/networking.nix | 6 +++--- mail-server/rmilter.nix | 8 ++++---- mail-server/services.nix | 17 +++++++++-------- mail-server/systemd.nix | 20 ++++++++++---------- 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/default.nix b/default.nix index a2158a6..5b5e015 100644 --- a/default.nix +++ b/default.nix @@ -172,7 +172,7 @@ in ''; }; - cert_dir = mkOption { + certificateDirectory = mkOption { type = types.path; default = "/var/certs"; description = '' @@ -183,7 +183,7 @@ in ''; }; - enable_imap = mkOption { + enableImap = mkOption { type = types.bool; default = true; description = '' @@ -196,7 +196,7 @@ in ''; }; - enable_pop3 = mkOption { + enablePop3 = mkOption { type = types.bool; default = false; description = '' @@ -221,7 +221,7 @@ in ''; }; - dkim_signing = mkOption { + dkimSigning = mkOption { type = types.bool; default = true; description = '' @@ -230,7 +230,7 @@ in ''; }; - dkim_selector = mkOption { + dkimSelector = mkOption { type = types.string; default = "mail"; description = '' @@ -238,7 +238,7 @@ in ''; }; - dkim_dir = mkOption { + dkimKeyDirectory = mkOption { type = types.path; default = "/var/dkim"; description = '' @@ -255,8 +255,8 @@ in services = import ./mail-server/services.nix { inherit lib; inherit (cfg) mailDirectory vmailUserName vmailGroupName virtualAliases domain - enable_imap enable_pop3 dkim_signing dkim_selector dkim_dir - certificateScheme certificateFile keyFile cert_dir virusScanning; + enableImap enablePop3 dkimSigning dkimSelector dkimKeyDirectory + certificateScheme certificateFile keyFile certificateDirectory virusScanning; }; environment = import ./mail-server/environment.nix { @@ -265,13 +265,14 @@ in }; networking = import ./mail-server/networking.nix { - inherit (cfg) domain hostPrefix enable_imap enable_pop3; + inherit (cfg) domain hostPrefix enableImap enablePop3; }; systemd = import ./mail-server/systemd.nix { inherit pkgs; - inherit (cfg) mailDirectory vmailGroupName certificateScheme cert_dir - hostPrefix domain dkim_selector dkim_dir; + inherit (cfg) mailDirectory vmailGroupName certificateScheme + certificateDirectory + hostPrefix domain dkimSelector dkimKeyDirectory; }; users = import ./mail-server/users.nix { diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix index d94539e..15d08ee 100644 --- a/mail-server/dovecot.nix +++ b/mail-server/dovecot.nix @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ vmailGroupName, vmailUserName, mailDirectory, enable_imap, enable_pop3, cert, +{ vmailGroupName, vmailUserName, mailDirectory, enableImap, enablePop3, cert, key }: let @@ -24,8 +24,8 @@ let in { enable = true; - enableImap = enable_imap; - enablePop3 = enable_pop3; + enableImap = enableImap; + enablePop3 = enablePop3; mailGroup = vmailGroupName; mailUser = vmailUserName; mailLocation = dovecot_maildir; diff --git a/mail-server/networking.nix b/mail-server/networking.nix index 81c2d15..750f2e8 100644 --- a/mail-server/networking.nix +++ b/mail-server/networking.nix @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ domain, hostPrefix, enable_imap, enable_pop3 }: +{ domain, hostPrefix, enableImap, enablePop3 }: { #hostName = "${hostPrefix}.${domain}"; @@ -22,7 +22,7 @@ firewall = { enable = true; allowedTCPPorts = [ 25 587 ] - ++ (if enable_imap then [ 143 ] else []) - ++ (if enable_pop3 then [ 110 ] else []); + ++ (if enableImap then [ 143 ] else []) + ++ (if enablePop3 then [ 110 ] else []); }; } diff --git a/mail-server/rmilter.nix b/mail-server/rmilter.nix index ea62a9f..d003779 100644 --- a/mail-server/rmilter.nix +++ b/mail-server/rmilter.nix @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ domain, virusScanning, dkim_signing, dkim_dir, dkim_selector }: +{ domain, virusScanning, dkimSigning, dkimKeyDirectory, dkimSelector }: let clamav = if virusScanning @@ -25,14 +25,14 @@ let }; '' else ""; - dkim = if dkim_signing + dkim = if dkimSigning then '' dkim { domain { - key = "${dkim_dir}"; + key = "${dkimKeyDirectory}"; domain = "*"; - selector = "${dkim_selector}"; + selector = "${dkimSelector}"; }; sign_alg = sha256; auth_only = yes; diff --git a/mail-server/services.nix b/mail-server/services.nix index 7d2188c..c17b961 100644 --- a/mail-server/services.nix +++ b/mail-server/services.nix @@ -14,23 +14,24 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, mailDirectory, vmailUserName, vmailGroupName, virtualAliases, domain, enable_imap, -enable_pop3, virusScanning, dkim_signing, dkim_selector, dkim_dir, -certificateScheme, certificateFile, keyFile, cert_dir }: +{ lib, mailDirectory, vmailUserName, vmailGroupName, virtualAliases, domain, +enableImap, enablePop3, virusScanning, dkimSigning, dkimSelector, +dkimKeyDirectory, certificateScheme, certificateFile, keyFile, +certificateDirectory }: let # cert :: PATH cert = if certificateScheme == 1 then certificateFile else if certificateScheme == 2 - then "${cert_dir}/cert-${domain}.pem" + then "${certificateDirectory}/cert-${domain}.pem" else ""; # key :: PATH key = if certificateScheme == 1 then keyFile else if certificateScheme == 2 - then "${cert_dir}/key-${domain}.pem" + then "${certificateDirectory}/key-${domain}.pem" else ""; in { @@ -40,7 +41,7 @@ in }; rmilter = import ./rmilter.nix { - inherit domain virusScanning dkim_signing dkim_selector dkim_dir; + inherit domain virusScanning dkimSigning dkimSelector dkimKeyDirectory; }; postfix = import ./postfix.nix { @@ -48,7 +49,7 @@ in }; dovecot2 = import ./dovecot.nix { - inherit vmailGroupName vmailUserName mailDirectory enable_imap - enable_pop3 cert key; + inherit vmailGroupName vmailUserName mailDirectory enableImap + enablePop3 cert key; }; } diff --git a/mail-server/systemd.nix b/mail-server/systemd.nix index fe3c688..24d4a7e 100644 --- a/mail-server/systemd.nix +++ b/mail-server/systemd.nix @@ -14,14 +14,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ pkgs, mailDirectory, vmailGroupName, certificateScheme, cert_dir, hostPrefix, -domain, dkim_selector, dkim_dir}: +{ pkgs, mailDirectory, vmailGroupName, certificateScheme, certificateDirectory, hostPrefix, +domain, dkimSelector, dkimKeyDirectory}: let create_certificate = if certificateScheme == 2 then '' # Create certificates if they do not exist yet - dir="${cert_dir}" + dir="${certificateDirectory}" fqdn="${hostPrefix}.${domain}" case $fqdn in /*) fqdn=$(cat "$fqdn");; esac key="''${dir}/key-${domain}.pem"; @@ -29,7 +29,7 @@ let if [ ! -f "''${key}" ] || [ ! -f "''${cert}" ] then - mkdir -p "${cert_dir}" + mkdir -p "${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,20 +37,20 @@ let '' else ""; - dkim_key = "${dkim_dir}/${dkim_selector}.private"; - dkim_txt = "${dkim_dir}/${dkim_selector}.txt"; + dkim_key = "${dkimKeyDirectory}/${dkimSelector}.private"; + dkim_txt = "${dkimKeyDirectory}/${dkimSelector}.txt"; create_dkim_cert = '' # Create dkim dir - mkdir -p "${dkim_dir}" - chown rmilter:rmilter "${dkim_dir}" + mkdir -p "${dkimKeyDirectory}" + chown rmilter:rmilter "${dkimKeyDirectory}" if [ ! -f "${dkim_key}" ] || [ ! -f "${dkim_txt}" ] then - ${pkgs.opendkim}/bin/opendkim-genkey -s "${dkim_selector}" \ + ${pkgs.opendkim}/bin/opendkim-genkey -s "${dkimSelector}" \ -d ${domain} \ - --directory="${dkim_dir}" + --directory="${dkimKeyDirectory}" chown rmilter:rmilter "${dkim_key}" fi ''; From 26ac1346609eeab7ca2ba7360a515604f36f221c Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 13:58:42 +0200 Subject: [PATCH 06/12] make users into module --- default.nix | 7 +------ mail-server/users.nix | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/default.nix b/default.nix index 5b5e015..d570c52 100644 --- a/default.nix +++ b/default.nix @@ -249,6 +249,7 @@ in imports = [ ./mail-server/clamav.nix + ./mail-server/users.nix ]; config = mkIf cfg.enable { @@ -275,11 +276,5 @@ in hostPrefix domain dkimSelector dkimKeyDirectory; }; - users = import ./mail-server/users.nix { - inherit lib; - inherit (cfg) vmailUIDStart vmailUserName vmailGroupName domain - mailDirectory - loginAccounts; - }; }; } diff --git a/mail-server/users.nix b/mail-server/users.nix index cae2b83..a8cbcc9 100644 --- a/mail-server/users.nix +++ b/mail-server/users.nix @@ -14,8 +14,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, vmailUIDStart, vmailUserName, vmailGroupName, domain, mailDirectory, -loginAccounts }: +{ config, pkgs, lib, ... }: + +with config.mailserver; let vmail_user = [{ @@ -40,11 +41,14 @@ let in { - # set the vmail gid to a specific value - groups = { - vmail = { gid = vmailUIDStart; }; - }; - # 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; + }; } From 201c532a67f285120a350407b0f483851979b034 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 14:04:07 +0200 Subject: [PATCH 07/12] environment to module --- default.nix | 6 +----- mail-server/environment.nix | 13 +++++++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index d570c52..1d44211 100644 --- a/default.nix +++ b/default.nix @@ -250,6 +250,7 @@ in imports = [ ./mail-server/clamav.nix ./mail-server/users.nix + ./mail-server/environment.nix ]; config = mkIf cfg.enable { @@ -260,11 +261,6 @@ in certificateScheme certificateFile keyFile certificateDirectory virusScanning; }; - environment = import ./mail-server/environment.nix { - inherit pkgs; - inherit (cfg) certificateScheme; - }; - networking = import ./mail-server/networking.nix { inherit (cfg) domain hostPrefix enableImap enablePop3; }; diff --git a/mail-server/environment.nix b/mail-server/environment.nix index 4ffdd2a..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, certificateScheme }: +{ config, pkgs, lib, ... }: +let + cfg = config.mailserver; +in { - systemPackages = with pkgs; [ - dovecot opendkim openssh postfix clamav rspamd rmilter - ] ++ (if certificateScheme == 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 []); + }; } From 9ac491f87df0ba838b3c9ec2e9f1c4999f2135a1 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 14:58:33 +0200 Subject: [PATCH 08/12] networking to module --- default.nix | 6 +----- mail-server/networking.nix | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/default.nix b/default.nix index 1d44211..242888e 100644 --- a/default.nix +++ b/default.nix @@ -251,6 +251,7 @@ in ./mail-server/clamav.nix ./mail-server/users.nix ./mail-server/environment.nix + ./mail-server/networking.nix ]; config = mkIf cfg.enable { @@ -261,16 +262,11 @@ in certificateScheme certificateFile keyFile certificateDirectory virusScanning; }; - networking = import ./mail-server/networking.nix { - inherit (cfg) domain hostPrefix enableImap enablePop3; - }; - systemd = import ./mail-server/systemd.nix { inherit pkgs; inherit (cfg) mailDirectory vmailGroupName certificateScheme certificateDirectory hostPrefix domain dkimSelector dkimKeyDirectory; }; - }; } diff --git a/mail-server/networking.nix b/mail-server/networking.nix index 750f2e8..e355252 100644 --- a/mail-server/networking.nix +++ b/mail-server/networking.nix @@ -14,15 +14,21 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ domain, hostPrefix, enableImap, enablePop3 }: +{ config, pkgs, lib, ... }: +let + cfg = config.mailserver; +in { - #hostName = "${hostPrefix}.${domain}"; + config = with cfg; lib.mkIf enable { - firewall = { - enable = true; - allowedTCPPorts = [ 25 587 ] - ++ (if enableImap then [ 143 ] else []) - ++ (if enablePop3 then [ 110 ] else []); + networking.hostName = "${hostPrefix}.${domain}"; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 25 587 ] + ++ (if enableImap then [ 143 ] else []) + ++ (if enablePop3 then [ 110 ] else []); + }; }; } From 3eb363fc71be2c35ef297d371220125242ac1d37 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sat, 2 Sep 2017 15:08:50 +0200 Subject: [PATCH 09/12] systemd to module --- default.nix | 7 +---- mail-server/systemd.nix | 69 ++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/default.nix b/default.nix index 242888e..82a4075 100644 --- a/default.nix +++ b/default.nix @@ -252,6 +252,7 @@ in ./mail-server/users.nix ./mail-server/environment.nix ./mail-server/networking.nix + ./mail-server/systemd.nix ]; config = mkIf cfg.enable { @@ -262,11 +263,5 @@ in certificateScheme certificateFile keyFile certificateDirectory virusScanning; }; - systemd = import ./mail-server/systemd.nix { - inherit pkgs; - inherit (cfg) mailDirectory vmailGroupName certificateScheme - certificateDirectory - hostPrefix domain dkimSelector dkimKeyDirectory; - }; }; } diff --git a/mail-server/systemd.nix b/mail-server/systemd.nix index 24d4a7e..fb2ceb0 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, mailDirectory, vmailGroupName, certificateScheme, certificateDirectory, hostPrefix, -domain, dkimSelector, dkimKeyDirectory}: +{ config, pkgs, lib, ... }: let - create_certificate = if certificateScheme == 2 then + cfg = config.mailserver; + + create_certificate = if cfg.certificateScheme == 2 then '' # Create certificates if they do not exist yet - dir="${certificateDirectory}" - fqdn="${hostPrefix}.${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 "${certificateDirectory}" + 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,49 +38,53 @@ let '' else ""; - dkim_key = "${dkimKeyDirectory}/${dkimSelector}.private"; - dkim_txt = "${dkimKeyDirectory}/${dkimSelector}.txt"; + dkim_key = "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.private"; + dkim_txt = "${cfg.dkimKeyDirectory}/${cfg.dkimSelector}.txt"; create_dkim_cert = '' # Create dkim dir - mkdir -p "${dkimKeyDirectory}" - chown rmilter:rmilter "${dkimKeyDirectory}" + mkdir -p "${cfg.dkimKeyDirectory}" + chown rmilter:rmilter "${cfg.dkimKeyDirectory}" if [ ! -f "${dkim_key}" ] || [ ! -f "${dkim_txt}" ] then - ${pkgs.opendkim}/bin/opendkim-genkey -s "${dkimSelector}" \ - -d ${domain} \ - --directory="${dkimKeyDirectory}" + ${pkgs.opendkim}/bin/opendkim-genkey -s "${cfg.dkimSelector}" \ + -d ${cfg.domain} \ + --directory="${cfg.dkimKeyDirectory}" chown rmilter:rmilter "${dkim_key}" fi ''; in { - # Set the correct permissions for dovecot vmail folder. See - # . We choose - # to use the systemd service to set the folder permissions whenever - # dovecot gets started. - services.dovecot2.after = [ "postfix.service" ]; - # Check for certificate before both postfix and dovecot to make sure it - # exists. - services.postfix = { - preStart = - '' + config = with cfg; lib.mkIf enable { + # Set the correct permissions for dovecot vmail folder. See + # . We choose + # to use the systemd service to set the folder permissions whenever + # dovecot gets started. + systemd.services.dovecot2.after = [ "postfix.service" ]; + + # Check for certificate before both postfix and dovecot to make sure it + # exists. + systemd.services.postfix = { + preStart = + '' # Create mail directory and set permissions mkdir -p "${mailDirectory}" chgrp "${vmailGroupName}" "${mailDirectory}" chmod 02770 "${mailDirectory}" - ${create_certificate} - ''; - }; + ${create_certificate} + ''; + }; - services.rmilter = { - preStart = - '' + systemd.services.rmilter = { + preStart = + '' ${create_dkim_cert} - ''; + ''; + }; + }; } From 28225fb1d690dac6d0cbb910c0878bc27d79c754 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sun, 3 Sep 2017 11:13:34 +0200 Subject: [PATCH 10/12] complete module rewrite --- default.nix | 13 ++--- mail-server/dovecot.nix | 103 +++++++++++++++++++++------------------ mail-server/postfix.nix | 96 +++++++++++++++++++----------------- mail-server/rmilter.nix | 28 ++++++----- mail-server/services.nix | 47 +++++++----------- 5 files changed, 144 insertions(+), 143 deletions(-) diff --git a/default.nix b/default.nix index 82a4075..ecdf6b8 100644 --- a/default.nix +++ b/default.nix @@ -253,15 +253,8 @@ in ./mail-server/environment.nix ./mail-server/networking.nix ./mail-server/systemd.nix + ./mail-server/dovecot.nix + ./mail-server/postfix.nix + ./mail-server/rmilter.nix ]; - - config = mkIf cfg.enable { - services = import ./mail-server/services.nix { - inherit lib; - inherit (cfg) mailDirectory vmailUserName vmailGroupName virtualAliases domain - enableImap enablePop3 dkimSigning dkimSelector dkimKeyDirectory - certificateScheme certificateFile keyFile certificateDirectory virusScanning; - }; - - }; } diff --git a/mail-server/dovecot.nix b/mail-server/dovecot.nix index 15d08ee..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 -{ vmailGroupName, vmailUserName, mailDirectory, enableImap, enablePop3, cert, -key }: +{ config, pkgs, lib, ... }: + +with (import ./common.nix { inherit config; }); let + cfg = config.mailserver; + # maildir in format "/${domain}/${user}/" - dovecot_maildir = "maildir:${mailDirectory}/%d/%n/"; + dovecot_maildir = "maildir:${cfg.mailDirectory}/%d/%n/"; in { - enable = true; - enableImap = enableImap; - enablePop3 = enablePop3; - mailGroup = vmailGroupName; - mailUser = vmailUserName; - mailLocation = dovecot_maildir; - sslServerCert = cert; - sslServerKey = key; - enableLmtp = true; - extraConfig = '' - #Extra Config - mail_access_groups = ${vmailGroupName} - 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/postfix.nix b/mail-server/postfix.nix index cc2817e..b914ad5 100644 --- a/mail-server/postfix.nix +++ b/mail-server/postfix.nix @@ -14,21 +14,25 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, mailDirectory, domain, virtualAliases, cert, key }: +{ config, pkgs, lib, ... }: + +with (import ./common.nix { inherit config; }); let + cfg = config.mailserver; + # valiases_postfix :: [ String ] valiases_postfix = map (from: - let to = virtualAliases.${from}; - in "${from}@${domain} ${to}@${domain}") - (builtins.attrNames virtualAliases); + let to = cfg.virtualAliases.${from}; + in "${from}@${cfg.domain} ${to}@${cfg.domain}") + (builtins.attrNames cfg.virtualAliases); # valiases_file :: Path 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 @@ -39,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 = ${mailDirectory} - 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 d003779..f358e2f 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, virusScanning, dkimSigning, dkimKeyDirectory, dkimSelector }: +{ config, pkgs, lib, ... }: let - clamav = if virusScanning + cfg = config.mailserver; + + clamav = if cfg.virusScanning then '' clamav { @@ -25,14 +27,14 @@ let }; '' else ""; - dkim = if dkimSigning + dkim = if cfg.dkimSigning then '' dkim { domain { - key = "${dkimKeyDirectory}"; + key = "${cfg.dkimKeyDirectory}"; domain = "*"; - selector = "${dkimSelector}"; + selector = "${cfg.dkimSelector}"; }; sign_alg = sha256; auth_only = yes; @@ -41,15 +43,17 @@ let else ""; in { - enable = true; - # debug = true; - postfix.enable = true; - rspamd.enable = true; - extraConfig = - '' + config = with cfg; lib.mkIf enable { + services.rmilter.enable = true; + # services.rmilter.debug = true; + services.rmilter.postfix.enable = true; + services.rmilter.rspamd.enable = true; + services.rmilter.extraConfig = + '' ${clamav} ${dkim} - ''; + ''; + }; } diff --git a/mail-server/services.nix b/mail-server/services.nix index c17b961..2cebdaf 100644 --- a/mail-server/services.nix +++ b/mail-server/services.nix @@ -14,42 +14,31 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -{ lib, mailDirectory, vmailUserName, vmailGroupName, virtualAliases, domain, -enableImap, enablePop3, virusScanning, dkimSigning, dkimSelector, -dkimKeyDirectory, certificateScheme, certificateFile, keyFile, -certificateDirectory }: + +{ config, pkgs, lib, ... }: let + cfg = config.mailserver; + # cert :: PATH - cert = if certificateScheme == 1 - then certificateFile - else if certificateScheme == 2 - then "${certificateDirectory}/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 certificateScheme == 1 - then keyFile - else if certificateScheme == 2 - then "${certificateDirectory}/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 virusScanning dkimSigning dkimSelector dkimKeyDirectory; - }; - - postfix = import ./postfix.nix { - inherit lib mailDirectory domain virtualAliases cert key; - }; - - dovecot2 = import ./dovecot.nix { - inherit vmailGroupName vmailUserName mailDirectory enableImap - enablePop3 cert key; - }; + + imports = [ + ./rmilter.nix + ./postfix.nix key + ./dovecot.nix + ]; } From e5d3786ff5e049e90f7a099edc082a07e9b7bf50 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sun, 3 Sep 2017 11:15:01 +0200 Subject: [PATCH 11/12] tyding up code --- mail-server/rmilter.nix | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mail-server/rmilter.nix b/mail-server/rmilter.nix index f358e2f..1f30ede 100644 --- a/mail-server/rmilter.nix +++ b/mail-server/rmilter.nix @@ -44,16 +44,18 @@ let in { config = with cfg; lib.mkIf enable { - services.rmilter.enable = true; - # services.rmilter.debug = true; - services.rmilter.postfix.enable = true; - services.rmilter.rspamd.enable = true; - services.rmilter.extraConfig = - '' - ${clamav} + services.rmilter = { + enable = true; + #debug = true; + postfix.enable = true; + rspamd.enable = true; + extraConfig = + '' + ${clamav} - ${dkim} - ''; + ${dkim} + ''; + }; }; } From aa31e8fda67f08348b97327d16222c028e391038 Mon Sep 17 00:00:00 2001 From: Robin Raymond Date: Sun, 3 Sep 2017 11:15:18 +0200 Subject: [PATCH 12/12] add file missing in last commit --- mail-server/common.nix | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 mail-server/common.nix 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 ""; +}