Install | Topics | Beyond Lino
Get started¶
What you need¶
We assume that your server has a static IP address. We use Postfix as MTA. This document is written for Debian 13.
Types of mail servers¶
We differentiate three types of mail server setups: “minimal”, “standard” and “full”.
minimal |
standard |
full |
Send email notifications from cron, monit, Django to selected recipients who have disabled their spam control for this server. |
Send emails to external recipients and business partners |
Also receive end-user emails and let users retrieve them |
Postfix |
STARTTLS, DKIM |
Dovecot |
Configure your DNS¶
Before installing Postfix, set up your DNS records in your zone file at the provider of your domain. You need an MX record to avoid getting refused by certain email providers. Remember that changes in the DNS setup can take 24 hours to propagate.
The DNS setup depends on whether your mail server runs under its own domain (mydomain.org) or on a subdomain of an umbrella domain (foo.mylino.net).
If your mail server runs under its own domain:
Type |
Host |
Priority |
Destination |
|---|---|---|---|
A |
mydomain.org. |
12.34.56.78 |
|
A |
mail.mydomain.org. |
12.34.56.78 |
|
MX |
mydomain.org. |
10 |
mail.mydomain.org |
Why this additional A record for mail.mydomain.org instead of simply letting
the MX record point to mydomain.org? In a small system, both names resolve
to the same IP address. But it can make sense to have your mail server on a
different machine than your web server or other application servers. Already for
security reasons. Or in order to be scalable. It seems that the mail
subdomain (or sometimes smtp or mx) is general practice.
If your server is under an umbrella domain, you add the following entries to the zone file of the umbrella domain, the A record makes your FQDN point to your server’s IP address and the MX record says the mail server is running at that same address.
Type |
Host |
Priority |
Destination |
|---|---|---|---|
A |
foo |
12.34.56.78 |
|
MX |
foo |
10 |
foo.mylino.net |
For a subdomain mail server your zone file looks like this:
foo IN A 12.34.56.78
foo IN MX 0 foo
foo IN TXT "v=spf1 ip4:12.34.56.78 a ~all"
_dmarc.foo IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:postmaster@foo.mylino.net; sp=quarantine; aspf=r"
_dmarc IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:postmaster@foo.mylino.net; sp=quarantine; aspf=r"
foo._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; p=MIIBI....DAQAB; s=email;" )
You may add the three TXT records later, you don’t need then when setting up a minimal server. We will explain them below in the sections DMARC, SPF, DKIM (DomainKeys Identified Mail).
Set your PTR record for reverse DNS¶
For every mail server you should configure the PTR record of your IP address. Without a correct PTR record, the SMTP servers of your recipients are likely to refuse to talk with your server.
You do this at the provider of your server (the owner of the IP address). They usually have a means for you to tell them the domain name assigned to an IP address. For example:
Hetzner: Networking –> Public Network –> Click on the ••• next to your IP address –> Edit Reverse DNS
How to check whether your PTR record is correctly set:
$ sudo apt install dnsutils
$ nslookup mydomain.org
Name: mydomain.org
Address: 12.34.56.78
$ dig -x 12.34.56.78
;; ANSWER SECTION:
78.56.34.12.in-addr.arpa. 86400 IN PTR mydomain.org.
Reverse DNS means that the owner of an IP address declares publicly the FQDN that points to this address. While DNS maps a domain name to an IP address, reverse DNS maps an IP address to a domain name. It is a way of publicly declaring that your server at that IP address is responding to your domain name.
Install Postfix¶
Installing Postfix on Debian will automatically uninstall exim4:
$ sudo apt install postfix
Installing Postfix will start by asking you to select a “General mail configuration type”:
No configuration
Internet Site
Internet with smarthost
Satellite system
Local only
You select either “Internet” or “Internet with smarthost”. “Smarthost” is a historical word for a relay host.
In both cases the installer then asks for your system’s mail name:
┌─────────────────────────┤ Postfix Configuration ├────────────────────────
│ The 'mail name' is the domain name used to 'qualify' _ALL_ mail
│ addresses without a domain name. This includes mail to and from <root>:
│ please do not make your machine send out mail from root@example.org
│ unless root@example.org has told you to.
│
│ This name will also be used by other programs. It should be the single,
│ fully qualified domain name (FQDN).
│
│ Thus, if a mail address on the local host is foo@example.org, the
│ correct value for this option would be example.org.
│
│ System mail name:
│
│ mydomain.org
│
│ <Ok> <Cancel>
│
└──────────────────────────────────────────────────────────────────────────
- mail name¶
The fully qualified domain name of your server, without any special subdomain, i.e. just the name after the
@of the email addresses for which you want to manage mails.
The Postfix installer stores your answer to this question in
/etc/mailname, a one-line text file used by every well-educated
MTA to know its own hostname (source). You can verify this after
installation:
$ cat /etc/mailname
mydomain.org
When you selected “Internet with smarthost”, you get a next question asking for the name of your relay host:
┌─────────────────────────┤ Postfix Configuration ├────────────────────────
│ Please specify a domain, host, host:port, [address] or [address]:port.
│ Use the form [destination] to turn off MX lookups. Leave this blank for
│ no relay host.
│
│ Do not specify more than one host.
│
│ The relayhost parameter specifies the default external host to send mail
│ to when no entry is matched in the optional transport(5) table. When no
│ relay host is given, mail is routed directly to the destination.
│
│ SMTP relay host (blank for none):
│
│ smtp.zone.eu
│
│ <Ok> <Cancel>
│
└──────────────────────────────────────────────────────────────────────────
Some typical answers:
relay.ovh.com (https://www.ovhcloud.com)
smtp.zone.eu (https://www.zone.ee)
After installing Postfix¶
Check your /etc/aliases file. On a simple or standard server it should
contain something like:
monit: root
info: root
postmaster: root
cron: root
root: me@proximus.be
Don’t forget to compile the /etc/aliases file after editing it:
# newaliases
Here is my recipe for configuring a simple mail server:
# postconf myhostname=`cat /etc/mailname`
# systemctl restart postfix
To verify the basic parameters of a simple mail server:
# postconf myhostname mydestination myorigin
myhostname = mydomain.org
mydestination = $myhostname,localhost
myorigin = /etc/mailname
Configure monit to send emails¶
If you use monit, then check /etc/monit/conf.d/lino.conf and add the
following lines:
set mailserver localhost
set alert me@mydomain.org
DMARC¶
Most email providers (including Proximus, Google, and Microsoft) increasingly require DMARC for all sending domains and subdomains. A DMARC entry instructs the receiving mail server how to give feedback to your mail server in case your message doesn’t satisfy their requirements. Without it, your emails are much more likely to be throttled or sent straight to the spam folder.
If your mail server is on a subdomain, you need to define the following entry in the zone file:
_dmarc.foo IN TXT "v=DMARC1;p=reject;pct=100;rua=mailto:postmaster@foo.mylino.net;sp=none;aspf=r"
More about DMARC
The p tag means “Policy for the primary domain”. A message can “pass” (p=pass), go into “quarantine” (p=quarantine) or get “rejected” (p=reject).
p=none: Monitoring only. Failed emails are delivered normally, but aggregate reports are sent back to you.
p=quarantine: Suspicious or failing emails are sent to the recipient’s spam or junk folder.
p=reject: Failing emails are blocked entirely during the SMTP connection. [1] (https://dmarcian.com/policy-modes-quarantine-vs-reject/), [2] (https://www.suped.com/learn/dmarc/dmarc-policies-explained-pnone-pquarantine-and-preject), [3] (https://www.valimail.com/blog/dmarc-syntax/)
The sp tag is the same for subdomains.
A DMARC resource record in the DNS looks like this:
v=DMARC1; p=none
Or like this:
v=DMARC1;p=reject;pct=100;rua=mailto:postmaster@mydomain.org
In this example the sending mail server asks the receiver to reject all non-aligned messages and send an aggregate report about the rejections to <postmaster@mydomain.org>.
DMARC Policy Not Enabled It is recommended to use a quarantine or reject policy. To enable BIMI, it is required to have one of these at 100%.
DMARC records use the same “tag-value” syntax for DNS-based key records defined in DKIM.
Enable TLS¶
Postfix uses TLS as a server when receiving mail (SMTPD) and as a client when sending mail (SMTP). Both need to be configured separately.
If your mail server is on a subdomain together with the web server, you can use
the certificate of the web server. Otherwise use certbot to install a
certificate for the mail server:
# certbot certonly --standalone -d mail.mydomain.org
# General TLS parameters:
smtpd_tls_cert_file=/etc/letsencrypt/live/foo.mylino.net/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/foo.mylino.net/privkey.pem
# How postfix handles incoming SMTP connections:
smtpd_tls_security_level = may
smtpd_use_tls=yes
# How postfix handles outgoing SMTP connections:
smtp_tls_security_level = may
smtp_use_tls=yes
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
SPF¶
An SPF record tells the ISP of your recipient to only allow mail from this domain if it comes from the IP addresses listed in the foo.mylino.net MX or A records, and reject everything else.
Some ISPs instantly drop or flag emails from subdomains if they lack an SPF record. You need to explicitly authorize the subdomain to send its own mail. Add this TXT record to your DNS:
type: txt
Name/Host: my
Value: v=spf1 mx a -all
The Sender policy framework (SPF) is defined by RFC 7208) as an authentication process that ties the envelope from field (defined by RFC 5321) to a set of authorized sender IP addresses. This authorization is published in a TXT record in DNS. Receivers can check SPF at the beginning of an SMTP transaction, compare the connecting IP address to the IP specified by the envelope from field domain and thus validate whether that IP is authorized to send mail.
The SPF TXT record contains (1) a version indicator, (2) a list of allowed IPs and (3) an authorization type.
version indicator is always the same string
v=spf1IPs can be
keyword “mx” means “”
either IPv4 space or IPv6 space
Authorization type can be one of the following:
+all |
pass |
Allow all mail |
-all |
fail |
Only allow mail that matches one of the parameters (ip4, MX, etc) in the record |
~all |
softfail |
Allow mail whether or not it matches the parameters in the record |
?all |
neutral |
No policy statement |
Example:
v=spf1 mx ~all
Example (assuming that 12.34.56.78 is the IP address of the server):
v=spf1 ip4:12.34.56.78 -all
To enable SPF, the following should be applied. First, install corresponding postfix package:
# apt install postfix-policyd-spf-python
Second, append postfix settings to /etc/postfix/master.cf:
policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf
and to /etc/postfix/main.cf:
policyd-spf_time_limit = 3600 smtpd_recipient_restrictions = … , check_policy_service unix:private/policyd-spf
Install DKIM¶
This recipe uses mail as the selector. Selectors are used when you have more
than one mail server per domain, e.g. one for “advertisement” and another for
“invoicing”. Common alternative values for the default selector are dkim or
simply default.
To set up DKIM for multiple mail servers on subdomains, assign a unique selector and publish an independent DKIM TXT record in your DNS for each specific subdomain.
On your mail server, install the system package:
# apt install opendkim opendkim-tools
Edit your /etc/opendkim.conf and set the following values:
Domain mydomain.org
Selector mail
KeyFile /etc/dkimkeys/mail.private
Socket local:/var/spool/postfix/opendkim/opendkim.sock
OpenDKIM must put the socket inside the Postfix chroot so Postfix can actually see it.
Create the directory for the socket file
# mkdir -p /var/spool/postfix/opendkim
# sudo chown opendkim:postfix /var/spool/postfix/opendkim
# chmod 750 /var/spool/postfix/opendkim
Add user “postfix” to group “opendkim”:
# adduser postfix opendkim
Edit your /etc/postfix/main.cf and set the following values:
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_type} {auth_authen}
Note that the socket file is specified here relative to the Postfix root.
Generate your DKIM key:
# opendkim-genkey -r -h rsa-sha256 -d mydomain.org -D /etc/dkimkeys -s foo
This will create two files, foo.private and foo.txt in
/etc/dkimkeys. The private key is used to sign outgoing emails.
Both files are readable only by their owner. Change the owner and group of these
files to opendkim:
# chown -Rv opendkim:opendkim /etc/dkimkeys/foo.*
Look at the content of your foo.txt to see your public key:
# cat /etc/dkimkeys/foo.txt
mail._domainkey IN TXT ( "v=DKIM1; h=rsa-sha256; k=rsa; s=email; "
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; t=y; "
"p=AySFjB..."
"...xorQAB" ) ; ----- DKIM key mail for mydomain.org
Paste the public key into a TXT record of your zone file:
v=DKIM1; h=rsa-sha256; k=rsa; p=AySFjB......xorQAB
Restart the services:
# systemctl restart postfix opendkim
Check whether the socket file exists:
# ls -la /var/spool/postfix/opendkim/
Check the status of the opendkim service:
# systemctl status opendkim
Watch the journal of the services:
# journalctl -u opendkim
# journalctl -u postfix
Create
/etc/opendkim/KeyTableand add the following line:mydomain.org mydomain.org:mail:/etc/opendkim/keys/mail.privateCreate
/etc/opendkim/SigningTableand insert:*@mydomain.org mail._domainkey.mydomain.orgFinally, create
/etc/opendkim/TrustedHostsand insert:127.0.0.1 ::1 localhost *.mydomain.org
Test your DKIM configuration¶
Use opendkim-testkey:
$ sudo apt install opendkim-tools
$ sudo opendkim-testkey -d mydomain.org -s foo -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/dkimkeys/mail.private
opendkim-testkey: checking key 'mail._domainkey.mydomain.org'
opendkim-testkey: key secure
opendkim-testkey: key OK
$ dig TXT _dmarc.foo.mylino.net +short
$ dig TXT _dmarc.foo.mydomain.org +short
Credentials for a relay host¶
If you use a relay host and your relay host requires a username and password, then you need to install SASL. Install the library modules:
$ sudo apt-get install libsasl2-modules
Write your credentials to the sasl_password file:
$ sudo nano /etc/postfix/sasl_passwd
Example content:
smtp.zone.eu:587 vps@mydomain.org:1234abcd
After editing your sasl_passwd file, you must compile it:
$ sudo postmap /etc/postfix/sasl_passwd
And your sasl_passwd file must be accessible only by root:
$ sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
And in your /etc/postfix/main.cf file you must instruct Postfix to use
this file:
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
More settings in the /etc/postfix/main.cf file:
smtp_tls_security_level = encrypt
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3