From afcc5de071dfffdc507995d1845372ba40dc1dc2 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Isma=C3=ABl=20Bouya?=
Date: Mon, 1 Jul 2019 22:07:52 +0200
Subject: [PATCH] Implement mta-sts and move mail services to specific domain
---
modules/private/default.nix | 1 +
modules/private/dns.nix | 16 +++-
modules/private/mail/postfix.nix | 7 ++
modules/private/websites/default.nix | 1 +
.../private/websites/tools/mail/default.nix | 75 +++++++++++++++++++
.../private/websites/tools/mail/mta-sts.nix | 55 ++++++++++++++
.../tools/{tools => mail}/rainloop.nix | 0
.../tools/{tools => mail}/roundcubemail.nix | 0
.../websites/tools/mail/www/index.html | 73 ++++++++++++++++++
.../private/websites/tools/tools/default.nix | 35 +--------
10 files changed, 228 insertions(+), 35 deletions(-)
create mode 100644 modules/private/websites/tools/mail/default.nix
create mode 100644 modules/private/websites/tools/mail/mta-sts.nix
rename modules/private/websites/tools/{tools => mail}/rainloop.nix (100%)
rename modules/private/websites/tools/{tools => mail}/roundcubemail.nix (100%)
create mode 100644 modules/private/websites/tools/mail/www/index.html
diff --git a/modules/private/default.nix b/modules/private/default.nix
index 026e69d..552ee8c 100644
--- a/modules/private/default.nix
+++ b/modules/private/default.nix
@@ -46,6 +46,7 @@ set = {
mgoblinTool = ./websites/tools/mgoblin;
peertubeTool = ./websites/tools/peertube;
toolsTool = ./websites/tools/tools;
+ mailTool = ./websites/tools/mail;
mail = ./mail;
mailMilters = ./mail/milters.nix;
diff --git a/modules/private/dns.nix b/modules/private/dns.nix
index 6647c14..01a3cbb 100644
--- a/modules/private/dns.nix
+++ b/modules/private/dns.nix
@@ -94,10 +94,10 @@
${conf.entries}
${if lib.attrsets.hasAttr "withEmail" conf && lib.lists.length conf.withEmail > 0 then ''
- mail IN A ${myconfig.env.servers.immaeEu.ips.main.ip4}
mx-1 IN A ${myconfig.env.servers.eldiron.ips.main.ip4}
- ${builtins.concatStringsSep "\n" (map (i: "mail IN AAAA ${i}") myconfig.env.servers.immaeEu.ips.main.ip6)}
+ mx-2 IN A ${myconfig.env.servers.immaeEu.ips.main.ip4}
${builtins.concatStringsSep "\n" (map (i: "mx-1 IN AAAA ${i}") myconfig.env.servers.eldiron.ips.main.ip6)}
+ ${builtins.concatStringsSep "\n" (map (i: "mx-2 IN AAAA ${i}") myconfig.env.servers.immaeEu.ips.main.ip6)}
${lib.concatStringsSep "\n\n" (map (e:
let
n = if e.domain == "" then "@" else "${e.domain} ";
@@ -105,8 +105,8 @@
in
''
; ------------------ mail: ${n} ---------------------------
- ${n} IN MX 10 mail.${conf.name}.
- ${n} IN MX 50 mx-1.${conf.name}.
+ ${n} IN MX 10 mx-1.${conf.name}.
+ ${n} IN MX 20 mx-2.${conf.name}.
; https://tools.ietf.org/html/rfc6186
_submission._tcp${suffix} SRV 0 1 587 smtp.immae.eu.
@@ -116,6 +116,14 @@
_pop3s._tcp${suffix} SRV 10 1 995 pop3.immae.eu.
_sieve._tcp${suffix} SRV 0 1 4190 imap.immae.eu.
+ ; MTA-STS
+ ; https://blog.delouw.ch/2018/12/16/using-mta-sts-to-enhance-email-transport-security-and-privacy/
+ ; https://support.google.com/a/answer/9261504
+ _mta-sts${suffix} IN TXT "v=STSv1;id=20190630054629Z"
+ _smtp._tls${suffix} IN TXT "v=TLSRPTv1;rua=mailto:postmaster+mta-sts@immae.eu"
+ mta-sts${suffix} IN A ${myconfig.env.servers.eldiron.ips.main.ip4}
+ ${builtins.concatStringsSep "\n" (map (i: "mta-sts${suffix} IN AAAA ${i}") myconfig.env.servers.eldiron.ips.main.ip6)}
+
; Mail sender authentications
${n} IN TXT "v=spf1 mx ~all"
_dmarc${suffix} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; fo=1; rua=mailto:postmaster+rua@immae.eu; ruf=mailto:postmaster+ruf@immae.eu;"
diff --git a/modules/private/mail/postfix.nix b/modules/private/mail/postfix.nix
index 53bf650..dfe6129 100644
--- a/modules/private/mail/postfix.nix
+++ b/modules/private/mail/postfix.nix
@@ -190,6 +190,13 @@
milter_macro_daemon_name = "ORIGINATING";
smtpd_milters = "unix:${config.myServices.mail.milters.sockets.opendkim}";
};
+ # FIXME: Mail adressed to localhost.immae.eu will still have mx-1 as
+ # prioritized MX, which provokes "mail for localhost.immae.eu loops
+ # back to myself" errors. This transport entry forces to push
+ # e-mails to its right destination.
+ transport = ''
+ localhost.immae.eu smtp:[immae.eu]:25
+ '';
destination = ["localhost"];
# This needs to reverse DNS
hostname = "eldiron.immae.eu";
diff --git a/modules/private/websites/default.nix b/modules/private/websites/default.nix
index add4e42..63dd53d 100644
--- a/modules/private/websites/default.nix
+++ b/modules/private/websites/default.nix
@@ -264,6 +264,7 @@ in
tools.mediagoblin.enable = true;
tools.peertube.enable = true;
tools.tools.enable = true;
+ tools.email.enable = true;
};
};
}
diff --git a/modules/private/websites/tools/mail/default.nix b/modules/private/websites/tools/mail/default.nix
new file mode 100644
index 0000000..ea0a27f
--- /dev/null
+++ b/modules/private/websites/tools/mail/default.nix
@@ -0,0 +1,75 @@
+{ lib, pkgs, config, myconfig, ... }:
+let
+ roundcubemail = pkgs.callPackage ./roundcubemail.nix {
+ inherit (pkgs.webapps) roundcubemail roundcubemail-plugins roundcubemail-skins;
+ env = myconfig.env.tools.roundcubemail;
+ };
+ rainloop = pkgs.callPackage ./rainloop.nix {};
+ cfg = config.myServices.websites.tools.email;
+in
+{
+ options.myServices.websites.tools.email = {
+ enable = lib.mkEnableOption "enable email website";
+ };
+
+ imports = [
+ ./mta-sts.nix
+ ];
+
+ config = lib.mkIf cfg.enable {
+ secrets.keys = roundcubemail.keys;
+
+ services.websites.env.tools.modules =
+ [ "proxy_fcgi" ]
+ ++ rainloop.apache.modules
+ ++ roundcubemail.apache.modules;
+
+ services.websites.env.tools.vhostConfs.mail = {
+ certName = "mail";
+ addToCerts = true;
+ hosts = ["mail.immae.eu"];
+ root = "/run/current-system/webapps/_mail";
+ extraConfig = [
+ rainloop.apache.vhostConf
+ roundcubemail.apache.vhostConf
+ ''
+
+ Require all granted
+ Options -Indexes
+
+ ''
+ ];
+ };
+ systemd.services = {
+ phpfpm-rainloop = {
+ after = lib.mkAfter rainloop.phpFpm.serviceDeps;
+ wants = rainloop.phpFpm.serviceDeps;
+ };
+ phpfpm-roundcubemail = {
+ after = lib.mkAfter roundcubemail.phpFpm.serviceDeps;
+ wants = roundcubemail.phpFpm.serviceDeps;
+ };
+ };
+
+ services.phpfpm.pools.roundcubemail = {
+ listen = roundcubemail.phpFpm.socket;
+ extraConfig = roundcubemail.phpFpm.pool;
+ phpOptions = config.services.phpfpm.phpOptions + roundcubemail.phpFpm.phpConfig;
+ };
+ services.phpfpm.poolConfigs = {
+ rainloop = rainloop.phpFpm.pool;
+ };
+ system.activationScripts = {
+ roundcubemail = roundcubemail.activationScript;
+ rainloop = rainloop.activationScript;
+ };
+
+ myServices.websites.webappDirs = {
+ _mail = ./www;
+ "${roundcubemail.apache.webappName}" = roundcubemail.webRoot;
+ "${rainloop.apache.webappName}" = rainloop.webRoot;
+ };
+
+ };
+
+}
diff --git a/modules/private/websites/tools/mail/mta-sts.nix b/modules/private/websites/tools/mail/mta-sts.nix
new file mode 100644
index 0000000..bedefda
--- /dev/null
+++ b/modules/private/websites/tools/mail/mta-sts.nix
@@ -0,0 +1,55 @@
+{ lib, pkgs, config, myconfig, ... }:
+let
+ domains = (lib.remove null (lib.flatten (map
+ (zone: map
+ (e: if e.receive
+ then {
+ domain = "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}";
+ mail = zone.name;
+ }
+ else null
+ )
+ (zone.withEmail or [])
+ )
+ myconfig.env.dns.masterZones
+ )));
+ # FIXME: increase the id number in modules/private/dns.nix when this
+ # file change (date -u +'%Y%m%d%H%M%S'Z)
+ file = domain: pkgs.writeText "mta-sts-${domain.domain}.txt" ''
+ version: STSv1
+ mode: testing
+ mx: mx-1.${domain.mail}
+ mx: mx-2.${domain.mail}
+ max_age: 604800
+ '';
+ root = pkgs.runCommand "mta-sts_root" {} ''
+ mkdir -p $out
+ ${builtins.concatStringsSep "\n" (map (d:
+ "cp ${file d} $out/${d.domain}.txt"
+ ) domains)}
+ '';
+in
+{
+ config.myServices.websites.webappDirs = {
+ _mta-sts = root;
+ };
+
+ config.services.websites.env.tools.vhostConfs.mta_sts = {
+ certName = "mail";
+ addToCerts = true;
+ hosts = ["mta-sts.mail.immae.eu"] ++ map (v: "mta-sts.${v.domain}") domains;
+ root = "/run/current-system/webapps/_mta-sts";
+ extraConfig = [
+ ''
+ RewriteEngine on
+ RewriteCond %{HTTP_HOST} ^mta-sts.(.*)$
+ RewriteRule ^/.well-known/mta-sts.txt$ %{DOCUMENT_ROOT}/%1.txt [L]
+
+ Require all granted
+ Options -Indexes
+
+ ''
+ ];
+ };
+
+}
diff --git a/modules/private/websites/tools/tools/rainloop.nix b/modules/private/websites/tools/mail/rainloop.nix
similarity index 100%
rename from modules/private/websites/tools/tools/rainloop.nix
rename to modules/private/websites/tools/mail/rainloop.nix
diff --git a/modules/private/websites/tools/tools/roundcubemail.nix b/modules/private/websites/tools/mail/roundcubemail.nix
similarity index 100%
rename from modules/private/websites/tools/tools/roundcubemail.nix
rename to modules/private/websites/tools/mail/roundcubemail.nix
diff --git a/modules/private/websites/tools/mail/www/index.html b/modules/private/websites/tools/mail/www/index.html
new file mode 100644
index 0000000..3727c42
--- /dev/null
+++ b/modules/private/websites/tools/mail/www/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+ E-mail configuration
+
+
+
+
+ Email configuration. For automatic configuration in your smart e-mail
+ client, use login@mail.immae.eu. If it
+ doesnât work, the details are there:
+
+ - IMAP: imap.immae.eu
+
+ - No unencrypted access
+ - STARTTLS: 143 (recommended)
+ - SSL: 993
+
+
+ - POP3: pop3.immae.eu
+
+ - No unencrypted access
+ - STARTTLS: 110 (recommended)
+ - SSL: 995
+
+
+ - SMTP: smtp.immae.eu
+
+ - No unencrypted access
+ - STARTTLS: 587
+
+
+ - Sieve: imap.immae.eu
+
+ - No unencrypted access
+ - STARTTLS: 4190
+
+
+
+
+ Webmails:
+
+
+
+
+
diff --git a/modules/private/websites/tools/tools/default.nix b/modules/private/websites/tools/tools/default.nix
index 9908d99..5b368e0 100644
--- a/modules/private/websites/tools/tools/default.nix
+++ b/modules/private/websites/tools/tools/default.nix
@@ -10,11 +10,6 @@ let
inherit (pkgs.webapps) ttrss ttrss-plugins;
env = myconfig.env.tools.ttrss;
};
- roundcubemail = pkgs.callPackage ./roundcubemail.nix {
- inherit (pkgs.webapps) roundcubemail roundcubemail-plugins roundcubemail-skins;
- env = myconfig.env.tools.roundcubemail;
- };
- rainloop = pkgs.callPackage ./rainloop.nix {};
kanboard = pkgs.callPackage ./kanboard.nix {
env = myconfig.env.tools.kanboard;
};
@@ -51,21 +46,16 @@ in {
secrets.keys =
kanboard.keys
++ ldap.keys
- ++ roundcubemail.keys
++ shaarli.keys
++ ttrss.keys
++ wallabag.keys
++ yourls.keys;
- services.websites.env.integration.modules =
- rainloop.apache.modules;
-
services.websites.env.tools.modules =
[ "proxy_fcgi" ]
++ adminer.apache.modules
++ ympd.apache.modules
++ ttrss.apache.modules
- ++ roundcubemail.apache.modules
++ wallabag.apache.modules
++ yourls.apache.modules
++ rompr.apache.modules
@@ -90,7 +80,6 @@ in {
''
- rainloop.apache.vhostConf
];
};
@@ -101,6 +90,8 @@ in {
root = "/var/lib/ftp/tools.immae.eu";
extraConfig = [
''
+ RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
+
DirectoryIndex index.php index.htm index.html
AllowOverride all
@@ -113,7 +104,6 @@ in {
adminer.apache.vhostConf
ympd.apache.vhostConf
ttrss.apache.vhostConf
- roundcubemail.apache.vhostConf
wallabag.apache.vhostConf
yourls.apache.vhostConf
rompr.apache.vhostConf
@@ -145,6 +135,8 @@ in {
RedirectMatch 301 ^/taskweb(.*)$ https://task.immae.eu/taskweb$1
+ RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
+
RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1
''
];
@@ -163,14 +155,6 @@ in {
after = lib.mkAfter ldap.phpFpm.serviceDeps;
wants = ldap.phpFpm.serviceDeps;
};
- phpfpm-rainloop = {
- after = lib.mkAfter rainloop.phpFpm.serviceDeps;
- wants = rainloop.phpFpm.serviceDeps;
- };
- phpfpm-roundcubemail = {
- after = lib.mkAfter roundcubemail.phpFpm.serviceDeps;
- wants = roundcubemail.phpFpm.serviceDeps;
- };
phpfpm-shaarli = {
after = lib.mkAfter shaarli.phpFpm.serviceDeps;
wants = shaarli.phpFpm.serviceDeps;
@@ -217,12 +201,6 @@ in {
paths = [ "/var/secrets/mpd" ];
};
- services.phpfpm.pools.roundcubemail = {
- listen = roundcubemail.phpFpm.socket;
- extraConfig = roundcubemail.phpFpm.pool;
- phpOptions = config.services.phpfpm.phpOptions + roundcubemail.phpFpm.phpConfig;
- };
-
services.phpfpm.pools.devtools = {
listen = "/var/run/phpfpm/devtools.sock";
extraConfig = ''
@@ -254,7 +232,6 @@ in {
shaarli = shaarli.phpFpm.pool;
dokuwiki = dokuwiki.phpFpm.pool;
ldap = ldap.phpFpm.pool;
- rainloop = rainloop.phpFpm.pool;
kanboard = kanboard.phpFpm.pool;
tools = ''
listen = /var/run/phpfpm/tools.sock
@@ -277,13 +254,11 @@ in {
system.activationScripts = {
adminer = adminer.activationScript;
ttrss = ttrss.activationScript;
- roundcubemail = roundcubemail.activationScript;
wallabag = wallabag.activationScript;
yourls = yourls.activationScript;
rompr = rompr.activationScript;
shaarli = shaarli.activationScript;
dokuwiki = dokuwiki.activationScript;
- rainloop = rainloop.activationScript;
kanboard = kanboard.activationScript;
ldap = ldap.activationScript;
};
@@ -293,12 +268,10 @@ in {
"${dokuwiki.apache.webappName}" = dokuwiki.webRoot;
"${ldap.apache.webappName}" = "${ldap.webRoot}/htdocs";
"${rompr.apache.webappName}" = rompr.webRoot;
- "${roundcubemail.apache.webappName}" = roundcubemail.webRoot;
"${shaarli.apache.webappName}" = shaarli.webRoot;
"${ttrss.apache.webappName}" = ttrss.webRoot;
"${wallabag.apache.webappName}" = wallabag.webRoot;
"${yourls.apache.webappName}" = yourls.webRoot;
- "${rainloop.apache.webappName}" = rainloop.webRoot;
"${kanboard.apache.webappName}" = kanboard.webRoot;
};
--
2.41.0