summaryrefslogtreecommitdiffstats
path: root/docs/setup-guide.rst
blob: 61b1559f30843e95bc4c6e0d2af15d0da9e61640 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
Setup Guide
===========

Mail servers can be a tricky thing to set up. This guide is supposed to
run you through the most important steps to achieve a 10/10 score on
`<https://mail-tester.com>`_.

What you need is:

- a server running NixOS with a public IP
- a domain name.

.. note::

   In the following, we consider a server with the public IP ``1.2.3.4``
   and the domain ``example.com``.

First, we will set the minimum DNS configuration to be able to deploy
an up and running mail server. Once the server is deployed, we could
then set all DNS entries required to send and receive mails on this
server.

Setup DNS A record for server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Add a DNS record to the domain ``example.com`` with the following
entries

==================== ===== ==== =============
Name (Subdomain)     TTL   Type Value
==================== ===== ==== =============
``mail.example.com`` 10800 A    ``1.2.3.4``
==================== ===== ==== =============

You can check this with

::

   $ ping mail.example.com
   64 bytes from mail.example.com (1.2.3.4): icmp_seq=1 ttl=46 time=21.3 ms
   ...

Note that it can take a while until a DNS entry is propagated. This
DNS entry is required for the Let's Encrypt certificate generation
(which is used in the below configuration example).

Setup the server
~~~~~~~~~~~~~~~~

The following describes a server setup that is fairly complete. Even
though there are more possible options (see the `NixOS Mailserver
options documentation <options.html>`_), these should be the most
common ones.

.. code:: nix

   { config, pkgs, ... }: {
     imports = [
       (builtins.fetchTarball {
         # Pick a release version you are interested in and set its hash, e.g.
         url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-23.05/nixos-mailserver-nixos-23.05.tar.gz";
         # To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
         # release="nixos-23.05"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
         sha256 = "0000000000000000000000000000000000000000000000000000";
       })
     ];

     mailserver = {
       enable = true;
       fqdn = "mail.example.com";
       domains = [ "example.com" ];

       # A list of all login accounts. To create the password hashes, use
       # nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
       loginAccounts = {
         "user1@example.com" = {
           hashedPasswordFile = "/a/file/containing/a/hashed/password";
           aliases = ["postmaster@example.com"];
         };
         "user2@example.com" = { ... };
       };

       # Use Let's Encrypt certificates. Note that this needs to set up a stripped
       # down nginx and opens port 80.
       certificateScheme = "acme-nginx";
     };
     security.acme.acceptTerms = true;
     security.acme.defaults.email = "security@example.com";
   }

After a ``nixos-rebuild switch`` your server should be running all
mail components.

Setup all other DNS requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Set rDNS (reverse DNS) entry for server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Wherever you have rented your server, you should be able to set reverse
DNS entries for the IP’s you own. Add an entry resolving ``1.2.3.4``
to ``mail.example.com``.

.. warning::

   We don't recommend setting up a mail server if you are not able to
   set a reverse DNS on your public IP because sent emails would be
   mostly marked as spam. Note that many residential ISP providers
   don't allow you to set a reverse DNS entry.

You can check this with

::

   $ nix-shell -p bind --command "host 1.2.3.4"
   4.3.2.1.in-addr.arpa domain name pointer mail.example.com.

Note that it can take a while until a DNS entry is propagated.

Set a ``MX`` record
^^^^^^^^^^^^^^^^^^^


Add a ``MX`` record to the domain ``example.com``.

================ ==== ======== =================
Name (Subdomain) Type Priority Value
================ ==== ======== =================
example.com      MX   10       mail.example.com
================ ==== ======== =================

You can check this with

::

   $ nix-shell -p bind --command "host -t mx example.com"
   example.com mail is handled by 10 mail.example.com.

Note that it can take a while until a DNS entry is propagated.

Set a ``SPF`` record
^^^^^^^^^^^^^^^^^^^^

Add a `SPF <https://en.wikipedia.org/wiki/Sender_Policy_Framework>`_
record to the domain ``example.com``.

================ ===== ==== ================================
Name (Subdomain) TTL   Type Value
================ ===== ==== ================================
example.com      10800 TXT  `v=spf1 a:mail.example.com -all`
================ ===== ==== ================================

You can check this with

::

   $ nix-shell -p bind --command "host -t TXT example.com"
   example.com descriptive text "v=spf1 a:mail.example.com -all"

Note that it can take a while until a DNS entry is propagated.

Set ``DKIM`` signature
^^^^^^^^^^^^^^^^^^^^^^

On your server, the ``opendkim`` systemd service generated a file
containing your DKIM public key in the file
``/var/dkim/example.com.mail.txt``. The content of this file looks
like

::

   mail._domainkey IN TXT "v=DKIM1; k=rsa; s=email; p=<really-long-key>" ; ----- DKIM mail for domain.tld

where ``really-long-key`` is your public key.

Based on the content of this file, we can add a ``DKIM`` record to the
domain ``example.com``.

=========================== ===== ==== ==============================
Name (Subdomain)            TTL   Type Value
=========================== ===== ==== ==============================
mail._domainkey.example.com 10800 TXT  ``v=DKIM1; p=<really-long-key>``
=========================== ===== ==== ==============================

You can check this with

::

   $ nix-shell -p bind --command "host -t txt mail._domainkey.example.com"
   mail._domainkey.example.com descriptive text "v=DKIM1;p=<really-long-key>"

Note that it can take a while until a DNS entry is propagated.

Set a ``DMARC`` record
^^^^^^^^^^^^^^^^^^^^^^

Add a ``DMARC`` record to the domain ``example.com``.

======================== ===== ==== ====================
Name (Subdomain)         TTL   Type Value
======================== ===== ==== ====================
_dmarc.example.com       10800 TXT  ``v=DMARC1; p=none``
======================== ===== ==== ====================

You can check this with

::

   $ nix-shell -p bind --command "host -t TXT _dmarc.example.com"
   _dmarc.example.com descriptive text "v=DMARC1; p=none"

Note that it can take a while until a DNS entry is propagated.


Test your Setup
~~~~~~~~~~~~~~~

Write an email to your aunt (who has been waiting for your reply far too
long), and sign up for some of the finest newsletters the Internet has.
Maybe you want to sign up for the `SNM Announcement
List <https://www.freelists.org/list/snm>`__?

Besides that, you can send an email to
`mail-tester.com <https://www.mail-tester.com/>`__ and see how you
score, and let `mxtoolbox.com <http://mxtoolbox.com/>`__ take a look at
your setup, but if you followed the steps closely then everything should
be awesome!