Files
2026-05-24 21:03:47 +02:00

313 lines
10 KiB
ReStructuredText
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.. _setup-guide:
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>`_.
Requirements
~~~~~~~~~~~~
To set up a self-hosted mail server, you need the following:
* Small (e.g. 1C/2G) server running NixOS
* Stable IPv4 and - strongly recommended - IPv6 addresses
* Ability to configure a Reverse DNS (PTR record) for your IP addresses
* Access to SMTP traffic on port 25/tcp - some hosters make you ask for this
* A registered domain name with DNS record management access
Once these requirements are in place, you can begin setting up your selfhosted
mailserver.
.. note::
Below we'll assume that your server got assigned the public IP addresses
``192.0.2.1`` (IPv4) and ``2001:db8::1`` (IPv6) and that you control the
``example.com`` domain.
Configure forward DNS records
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here we set up ``mail.example.com`` as the forward hostname for your mail server
to point to the IP addresses allocated to the server. This allows reaching
the server under this name and to reference it later in MX records for mail
delivery.
Now edit the ``example.com`` zone and create the following DNS records:
.. csv-table::
:header: "Name", "TTL", "Type", "Value"
:widths: 30, 10, 10, 50
mail.example.com., 3600, A, 192.0.2.1
mail.example.com., 3600, AAAA, 2001:db8::1
.. note::
If your server does not have an IPv6 address, you must skip the ``AAAA``
record.
Verify DNS record propagation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before we continue with the next step, we require that the forward DNS record
has propagated. For that it's best to check an authoritative nameserver for
``example.com`` so that we don't look at cached DNS records.
.. code-block:: console
# Find the authoritative nameservers for example.com
$ nix-shell -p dig --command "dig NS example.com +short"
ns1.example.org.
ns2.example.org.
# Query the A record from an authoritative nameserver
$ nix-shell -p dig --command "dig @ns1.example.org A mail.example.com +short"
192.0.2.1
# Query the AAAA record from an authoritative nameserver
$ nix-shell -p dig --command "dig @ns1.example.org AAAA mail.example.com +short"
2001:db8::1
DNS propagation usually takes a few minutes, so you might need to retry these
queries. Once the IP addresses appear you can continue with the next step.
Setup the server
~~~~~~~~~~~~~~~~
The following configuration describes a fairly complete mail server, capable
of sending and receiving mail for statically configured accounts. It includes
encrypted SMTP and IMAP services for secure delivery and retrieval, and relies
on ACME HTTP-01 to automatically obtain and maintain a TLS certificate.
While `more options`_ are available, the configuration below covers the most
common settings to get your mail server up and running.
.. _more options: options.html
.. literalinclude:: ./setup-example.nix
:language: nix
After a ``nixos-rebuild switch`` your server should be running all the necessary
mail services.
Configure DNS records
~~~~~~~~~~~~~~~~~~~~~
Reverse DNS
^^^^^^^^^^^
Earlier, we configured forward DNS from your hostname to your IP address. Now we
will configure reverse DNS so that your IP address points back to your hostname.
If your forward and reverse DNS do not match, many mail servers will reject or
flag your emails as spam, severely impairing delivery.
Your server provider should allow you to configure reverse DNS (PTR record)
records for the IP addresses you control, typically through their control panel
or account management interface:
- Configure ``192.0.2.1`` to point to ``mail.example.com.``
- Configure ``2001:db8::1`` to point to ``mail.example.com.``, if you have IPv6
addressing
Alternatively, if you interact with a proper DNS setup, the actual DNS records
look like this:
.. csv-table::
:header: "Name", "TTL", "Type", "Value"
:widths: 30, 10, 10, 50
1.2.0.192.in-addr.arpa., 86400, PTR, mail.example.com.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa., 86400, PTR, mail.example.com.
.. note::
Reverse DNS uses reverse notation for naming its records:
* IPv4 reverses the order of the octets and appends ``in-addr.arpa.``, so
``192.0.2.1`` becomes ``1.2.0.192.in-addr.arpa.``
* IPv6 fully expands the address and reverses each hex digit before
concatenating it with dots and appending ``ip6.arpa.``
.. code-block:: console
nix-shell -p haskellPackages.ip6addr --command "ip6addr --ptr 2001:db8::1"
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.IP6.ARPA.
.. warning::
We don't recommend setting up a mail server if you are unable to configure
reverse DNS on your public IP addresses because mails would inevitable be
marked as spam. Note that many residential ISP providers don't allow you to
set a reverse DNS entry and prohibit sending mail through policy blocklists
like Spamhaus PBL.
DNS propagation often isn't instant, so verify before continuing:
.. code-block:: console
$ nix-shell -p dig --command "dig -x 192.0.2.1 +short"
mail.example.com.
$ nix-shell -p dig --command "dig -x 2001:db8::1 +short"
mail.example.com.
MX record
^^^^^^^^^
The MX record instructs other mailservers where to deliver mail for a domain
name.
Create the MX record for ``example.com`` to point to the hostname of the server.
.. csv-table::
:header: "Name", "TTL", "Priority", "Type", "Value"
:widths: 30, 10, 10, 10, 50
example.com., 3600, MX, 10, mail.example.com.
The priority field determines the order when multiple servers are configured.
It is not important in this scenario but setting a value is mandatory and 10
leaves some wiggle room below and above, should you ever need that.
.. code-block:: console
$ nix-shell -p dig --command "dig @ns1.example.org MX example.com +short"
10 mail.example.com.
SPF record
^^^^^^^^^^
With `SPF`_ we can specify which mail servers are authorized to send mail on
behalf of a domain name.
.. _SPF: https://en.wikipedia.org/wiki/Sender_Policy_Framework
The SPF record is TXT record and we can tie it in with the MX record we created
in the previous step. Finishing with ``-all`` indicates that without any match
the mail should be rejected.
.. csv-table::
:header: "Name", "TTL", "Type", "Value"
:widths: 30, 10, 10, 50
example.com., 86400, TXT, v=spf1 mx -all
.. code-block:: console
$ nix-shell -p dig --command "dig TXT example.com +short"
v=spf1 mx -all
DKIM record
^^^^^^^^^^^
On system activation a `DKIM`_ keypair for ``example.com`` was generated. The
mail server uses this key to sign outgoing emails, allowing receiving servers to
verify the authenticity of the sender domain and ensuring that the signed parts
of the message have not been tampered with.
.. _DKIM: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
Now, check ``/var/dkim/example.com.mail.txt``, which contains the proposed DNS
record for the ``mail`` DKIM selector.
.. code-block:: none
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7hSess/UgEjaaq/NDn5KtW2iZzYljhf45DH3tN/kqcJ04JJk/Z1rS7CMJQ/pYZSSnQOju0H25uOtODvhqXPDxDdtCyDSrx54z/38lGNtA76/iWy/ikjb9hEkb2k3HuKex3P4KhhOC1pytDEFnh/T2aBxPNOigc/cpqm1U9RbnAwvArtx9dgOAgiV8rOIgPgyrPw1B3cJG3hgFYU2"
"GwXMoiFQPgwm7bkjelmThqXozA7jFJfnYt49jjrIYCv8X/nQx9cNpVAv2852mhU/3uuy6sa4MPjT6RiK9BJCMyDnqSpTPCjIubL4VhGCuzp7RPBkayWnlaH0X8PWGq6BQ0eBwIDAQAB"
) ;
Based on the content of this file, we can create the DKIM TXT record for the
``mail`` selector in the ``example.com`` zone. For the ``p=`` value, glue the
two long strings back together without any quotes and spaces and put them into
your record below.
.. csv-table::
:header: "Name", "TTL", "Type", "Value"
:widths: 30, 10, 10, 50
mail._domainkey.example.com., 86400, TXT, v=DKIM1; k=rsa; p=MIIBIjANBgk...Q0eBwIDAQAB
.. code-block:: console
$ nix-shell -p dig --command "dig @ns1.example.org TXT mail._domainkey.example.com +short"
"v=DKIM1; k=rsa; p=MIIBIjANBgk...Q0eBwIDAQAB"
DMARC record
^^^^^^^^^^^^
Finally, DMARC lets you define a policy for how strictly SPF and DKIM should be
checked and how to handle validation failures. For a new server, its important
to have a DMARC record in place, even if it doesnt enforce any actions yet,
because it improves deliverability by showing receiving servers that your domain
is properly managed and reducing the risk of email spoofing.
.. csv-table::
:header: "Name", "TTL", "Type", "Value"
:widths: 30, 10, 10, 50
_dmarc.example.com., 86400, TXT, v=DMARC1; p=none;
Verify propagation one final time.
.. code-block:: console
$ nix-shell -p dig --command "dig @ns1.example.org TXT _dmarc.example.com +short"
"v=DMARC1; p=none"
Test your Setup
~~~~~~~~~~~~~~~
Write an email to your aunt — shes been waiting far too long for your reply,
and this is your chance to finally make her day. Or, if you prefer a less
emotional test, send a message to `mail-tester.com`_ to see how your outgoing
mail scores.
You can also let `MXToolbox`_ take a peek at your setup. If you followed the
steps carefully, everything should be working perfectly!
.. _mail-tester.com: https://mail-tester.com/
.. _MXToolbox: https://mxtoolbox.com/
Join the community
~~~~~~~~~~~~~~~~~~
The community has a lively chat room on Matrix at `#nixos-mailserver:nixos.org`_
where you can ask questions, get help, share ideas, or discuss contributions.
.. _#nixos-mailserver:nixos.org: https://matrix.to/#/#nixos-mailserver:nixos.org
Next steps
~~~~~~~~~~
Your server scored perfect results already, so these steps are entirely
optional.
Are you feeling adventurous? Dive into our `advanced configurations`_ to explore
additional features and capabilities that let you fine-tune and extend your
mail setup.
If you want to take things even further, more elaborate testing services can
give you a clearer picture of your mail service and suggest ways to improve
it.
- `internet.nl`_ (supported by the Dutch Government)
- `MECSA`_ (supported by the European Commission)
Finally, you can also browse the full list of `options`_ provided by NixOS mailserver.
.. _advanced configurations: advanced-configurations.html
.. _options: options.html
.. _internet.nl: https://internet.nl/test-mail/
.. _MECSA: https://mecsa.jrc.ec.europa.eu/