Self-host your own digital island
1{ pkgs, config, lib, ... }:
2
3with lib;
4let
5 cfg = config.eilean;
6 domain = config.networking.domain;
7 subdomain = "mail.${domain}";
8in {
9 options.eilean.mailserver = {
10 enable = mkEnableOption "mailserver";
11 systemAccountPasswordFile = mkOption {
12 type = types.nullOr types.str;
13 default = null;
14 };
15 };
16
17 config = mkIf cfg.mailserver.enable {
18 security.acme-eon.certs."${subdomain}" = lib.mkIf cfg.acme-eon {
19 group = "turnserver";
20 reloadServices = [ "postfix.service" "dovecot.service" ];
21 };
22
23 mailserver = {
24 enable = true;
25 fqdn = subdomain;
26 domains = [ "${domain}" ];
27
28 loginAccounts = {
29 "system@${domain}" = {
30 passwordFile = cfg.mailserver.systemAccountPasswordFile;
31 aliases = [
32 (mkIf cfg.gitea.enable "git@${domain}")
33 (mkIf cfg.mastodon.enable "mastodon@${domain}")
34 ];
35 };
36 };
37
38 # Use Let's Encrypt certificates. Note that this needs to set up a stripped
39 # down nginx and opens port 80.
40 certificateScheme = if cfg.acme-eon then "manual" else "acme-nginx";
41 certificateFile = lib.mkIf cfg.acme-eon "${
42 config.security.acme-eon.certs.${subdomain}.directory
43 }/fullchain.pem";
44 keyFile = lib.mkIf cfg.acme-eon
45 "${config.security.acme-eon.certs.${subdomain}.directory}/key.pem";
46 localDnsResolver = false;
47 };
48
49 services.nginx.enable = true;
50 services.nginx.virtualHosts."${config.mailserver.fqdn}".extraConfig = ''
51 return 301 $scheme://${domain}$request_uri;
52 '';
53
54 systemd.services.dovecot2 = lib.mkIf cfg.acme-eon {
55 wants = [ "acme-eon-${subdomain}.service" ];
56 after = [ "acme-eon-${subdomain}.service" ];
57 };
58
59 systemd.services.postfix = lib.mkIf cfg.acme-eon {
60 wants = [ "acme-eon-${subdomain}.service" ];
61 after = [ "acme-eon-${subdomain}.service" ];
62 };
63
64 services.postfix.config = {
65 smtpd_tls_protocols =
66 mkForce "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
67 smtp_tls_protocols =
68 mkForce "TLSv1.3, TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
69 smtpd_tls_mandatory_protocols =
70 mkForce "TLSv1.3, !TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
71 smtp_tls_mandatory_protocols =
72 mkForce "TLSv1.3, !TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
73 };
74
75 eilean.dns.enable = true;
76 eilean.services.dns.zones.${config.networking.domain}.records = [
77 {
78 name = "mail";
79 type = "A";
80 value = cfg.serverIpv4;
81 }
82 {
83 name = "mail";
84 type = "AAAA";
85 value = cfg.serverIpv6;
86 }
87 {
88 name = "@";
89 type = "MX";
90 value = "10 mail";
91 }
92 {
93 name = "@";
94 type = "TXT";
95 value = ''"v=spf1 a:mail.${config.networking.domain} -all"'';
96 }
97 {
98 name = "_dmarc";
99 ttl = 10800;
100 type = "TXT";
101 value = ''"v=DMARC1; p=reject"'';
102 }
103 ];
104 };
105}