16 KiB
title | date | draft | categories | tags | |||
---|---|---|---|---|---|---|---|
Install | 2020-08-21T17:09:10+03:00 | false |
|
|
Setting up mail server on NixOS
This document will guide you through steps of setting up NixOS mailserver. This mailserver deployment includes:
- SMTP Server (postfix)
- IMAP/POP3 Server (dovecot)
- SSL/TLS/STARTLS support
- Automatic certificates assignment with ACME and LetsEncrypt
- Spam filtering via rspamd
- Virus scanning via clamav
This server is incredibly fast to deploy and incredibly easy to manage
System Requirements
- 1 vCPU
- At least 1 GB RAM
- At least 10 GB of storage
- NixOS 20.03
- Dedicated domain or subdomain
- Set of ports, allowed by your external firewall and ISP (both TCP and UDP)
- HTTP (80)
- HTTPS (443)
- SMTP (25)
- Submission (587)
- STARTLS IMAP (143)
- STARTLS POP3 (110)
If your system and network setup meets all of the requirements, we can start setting up your system. There's several options for you to choose from, when we speak about server setup
Automated installation(using a script)
Requirements for automated install
- ACME Support by your domain registrar
- Hetzner account
- Hetzner API token (see below, how to get it)
- ClodFlare account
- CloudFlare API token (see below, how to get it)
- AWS account
- AWS Secret Access Key (see below, how to get it)
- AWS Access Key ID (see below, how to get it)
Getting reuqired tokens, keys and IDs
- Get Hetzner API key
{{< rawhtml >}}
{{< /rawhtml >}}{{< rawhtml >}}
{{< /rawhtml >}}{{< rawhtml >}}
{{< rawhtml >}}Running a script
From now, you`re ready to start setting up a mailbox. To run a script, type:
bash <(curl -s https://selfprivacy.org/server.sh)
Manual Installation
See instructions below
Setting up the system
If you are planning to run NixOS mailserver on physical on-premise machine, please reffer to NixOS Installation Guide
If you running your server on Cloud Providers like: DigitalOcean, Scaleway, Hetzner etc. we will use nixos-infect script to transform your Ubuntu, Debian or Fedora system into NixOS.
A few words about nixos-infect
NixOS-Infect - user-made script for replacing crucial Linux system files of the distro, supported by your cloud provider, transforming it into NixOS. This script performs such tasks, as:
- Network settings collection (interfaces, routing)
- openSSH server settings collection
- Environment variables collection
- NixOS rootfs extraction
- Post-installation system builds and bootloader config
All data, collected by nixos-infect, will be converted into NixOS configuration files and then, applied to the new system, when it will be ready
One thing, you should bare in mind. NixOS-Infect supports only limited list of Cloud Providers. Make sure that your provider is supported, otherwise use generic provider (which do not guarantee you any success) Providers that are currently supported:
- DigitalOcean
- Vultr
- Hetzner
OVH VPS(experimental)
Using nixos-infect script
If your provider is supported or you decided to use generic provider, run the following command that corresponds to your choice:
DigitalOcean
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=digitalocean NIX_CHANNEL=nixos-20.03 bash 2>&1 | tee /tmp/infect.log
Vultr
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=vultr NIX_CHANNEL=nixos-20.03 bash
Hetzner Cloud
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | NIX_CHANNEL=nixos-20.03 bash 2>&1 | tee /tmp/infect.log
Generic (tested on Scaleway)
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=vultr NIX_CHANNEL=nixos-20.03 bash
Wait, until the process is finished. If everything worked correctly, your system should reboot. After system boots up, you will appear in the NixOS shell. From this moment, we can start setting up NixOS mail
Populating DNS server with necessary records
Each and every mailserver in the world, requires some DNS configuration to work properly. During further reading, you'll find all necessory DNS record templates. There's also DNS zonefile template available for direct export into CloudFlare.
A Records
Firstly, you need to point domain name, you would like to use for mailserver, directly to your machine's external IP. For example, if you have domain name example.com
, you need to create this record:
- Name: @
- TTL: 1 Hour
- Points to: "Your external IPv4 address"
example.com. 1 IN A <Your.external.IP>
But, if you have domain with some sort of subdomain (for example: subdomain.example.com), your record should look like this:
- Name: subdomain
- TTL: 1 Hour
- Points to: "Your external IPv4 address"
AAAA Records (IPv6 only)
If you have an IPv6 address, then you also need to perform this step. AAAA record does exactly the same thing as A record (directs domain to IP address), but for IPv6
- Name: @
- TTL: 1 Hour
- Points to: "Your external IPv6 address"
subdomain.example.com. 1 IN A <Your.external.IP>
MX Records
After that, you'll need to define, which domain or IP, handles mail on your specific domain (in this example it's: example.com). We are going describe specific scenario, when mail for your domain is being handled on the same domain, because 99% of mail servers configured this way.
- Name: @
- Points to: @
- Priority: 10
- TTL: 1 Hour
example.com. 1 IN MX 10 example.com.
At this point, basic DNS configuration is finished, but we'll be required to return to this a bit later.
Configuring NixOS firewall
Open /etc/nixos/configuration.nix
file for editing. Find networking.allowPing = true
line, and insert this two lines after it:
networking.firewall.allowedTCPPorts = [ 22 443 80 143 993 587 25 465 ];
networking.firewall.allowedUDPPorts = [ 80 443 143 993 587 25 465 ];
Installing and configuring NixOS mailserver
First, you need to copy mailserver config to your NixOS machine. It can be done via scp
using SSH (Please note that this requires opened 22 port).
{ config, pkgs, ... }:
{
imports = [
(builtins.fetchTarball {
# Pick a commit from the branch you are interested in
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/4008d0cb/nixos-mailserver-4008d0cb.tar.gz";
# And set its hash
sha256 = "1y9svi3nrg24ky1gqbpa3zhnhhin399h0cmnf81hb4yn75mlqiqx";
})
];
mailserver = {
enable = true;
fqdn = "<your-fqdn>";
domains = [ "<your-subdomains>" ];
# A list of all login accounts. To create the password hashes, use
# mkpasswd -m sha-512 "super secret password"
loginAccounts = {
"<user>@<your.domain>" = {
hashedPassword = "<your-hashed-password>";
aliases = [
"<user>@<your.domain2>"
];
# Make this user the catchAll address for domains example.com and
# example2.com
catchAll = [
"<your-domain>"
];
};
};
# Extra virtual aliases. These are email addresses that are forwarded to
# loginAccounts addresses.
extraVirtualAliases = {
# address = forward address;
"<alias>@<your-domain>" = "<user>@<your-domain>";
};
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
# down nginx and opens port 80.
certificateScheme = 3;
# Enable IMAP and POP3
enableImap = true;
enablePop3 = true;
enableImapSsl = true;
enablePop3Ssl = true;
#certificateFile = "~/cert.pem";
#keyFile = "~/privKey.pem";
# Enable the ManageSieve protocol
enableManageSieve = true;
# whether to scan inbound emails for viruses (note that this requires at least
# 1 Gb RAM for the server. Without virus scanning 256 MB RAM should be plenty)
virusScanning = true;
};
security.acme = {
acceptTerms = true;
# Replace the email here!
email = "<your-existing-email-address>";
};
}
Now, let's look at this config in more details
Setting your Fully Qualified Domain Name
Variable fqdn
corresponds to FQDN in mailserver config. For example, if your domain, dedicated for mailserver is: example.com
, then your fqdn variable will look like this
fqdn = "example.com";
If you set up mailserver on sort of subdomain (for example: subdomain.example.com
), then your variable will look like this
fqdn = "subdomain.example.com"
Defining domains list, to use with mailserver
At the next string after fqdn
variable, goes domains
array. There should be specified all domains, that will be associated with this mailserver. For example: if you are going to run mailserver on domains: example.com
, mail.example.com
, example2.com
, your domains
array should look like this:
domains = [ "example.com", "mail.example.com", "example2.com" ]
Defining login accounts
Next goes loginAccounts = { ... }
scope. There, you'll need to define username, hashed password and domain for assigning this user to it. For example, if you want to create user mailuser
on domain example.com
with password VerySecurePassword
, your config should look like this:
loginAccounts = {
"mailuser@example.com" = {
hashedPassword = "$6$5AiHele5DmyzzAuu$4fNrQD9fGi3J29dxQjRqQvwKw.PTbPideuYp9MTeaArnHBQHBZ/EJttKP5etWml2httbY3mOajPwLwr2ZbiV40";
aliases = [
"mailuser@example.com"
];
catchAll = [
"mailuser@example.com"
];
};
};
Hashing your password
Your password can be hashed with this command: mkpasswd -m sha-512 "YourPassword"
Please pay attention, that mailserver requires SHA512 hashing algorithm
catchAll list
This list is being used to define, which mail users will receive all of the mail, from all domains and all users associated with this mailserver
Setting up virtual addresses
Mailserver allows you to create virtual mail addresses if you need. Mail from such addresses will be stored on real user's mailbox. Main difference between virtual addresses and aliases, that you can use virtual address to log in into user account to which, this virtual address associated.
extraVirtualAliases = {
# address = forward address;
"abuse@ruleit.stream" = "user@ruleit.stream";
};
Choosing certificate resolution method
As NixOS mailserver supports STARTLS/STARSSL, there's necessity in a security certificate, which will prove your identity in further client-server communication.
Currently, there's three ways of provisioning certificate to a mail server
- Manual provisioning
- Generate self-signed
- LetsEncrypt certificate resolution with ACME
To choose one of this methods, you have to assign corresponding value to certificateScheme
variable, like this:
certificateScheme = 3;
1 - for manual provisioning, 2 - for automated self-signed certificate generation, 3 - for LetsEncrypt certificate resolution with ACME.
Manual provisioning
To use manual provisioning, you have to define two additional variables (they're commented in the example config): certificateFile
and keyFile
.
certificateFile = "~/cert.pem";
keyFile = "~/privKey.pem";
ACME resolution
WARNING!!! For ACME resolution, your DNS provider have to directly support ACME protocol.
Accpeting LetsEncrypt Terms of Service
At the end of example config, you can find security.acme
code snippet. There's several variables, you should assign values to
acceptTerms
Defines, whenever you accept terms of service, or not. Can be true
or false
Defines e-mail address to which send notifications on certificate expiry. Can be your existing email or email, you're currently setting up
Setting up DKIM selector
For further DNS configuration, you'll need a random word or letters set, to act as a DKIM selector. For setting up DKIM selector, please assign value to dkimSelector
variable, like this:
dkimSelector = "selector";
This value will be used to set up some sort of forgery protection to your mail, later.
SPF/DMARC/DKIM setup
At this point, you'll have to be very careful, because the smallest mistake during this step, may result in improper mailserver work. All of your mails may be treated as spam and you risk to put your domain in all blacklists of this world.
SPF Record
SPF - is a framework that has been designed to protect your mail from forgery and MITM attacks. It's very easy to configure. All, you have to add into your DNS record is:
example.com. 1 IN TXT "v=spf1 a mx ip4:<your IPv4> ip6:<Your IPv6 (if any)> -all"
If you do not have IPv6, then your record will look like this:
example.com. 1 IN TXT "v=spf1 a mx ip4:<your IPv4> -all"
DKIM Record
DKIM - is a way of signing your messages to be able to prove identity of this mails later. DKIM requires you to define key, to sign all mail you send with it. This key is being generated by NixOS Simple Mailserver during first startup. By default, it can be found in /var/dkim
directory. If your domain is: example.com
, your key will be stored in a file /var/dkim/example.com.yourDKIMSelector.txt
. Inside this file you'll find something similar to this:
yourDKIMSelector._domainkey IN TXT ( "v=DKIM1; k=rsa; " "p=REALLY-LONG-KEY" ) ; ----- DKIM key selector for example.com
When you got content of that file, you have to add new record of type TXT
to your DNS server
<yourDKIMSelector>._domainkey.example.com. 18000 IN TXT "v=DKIM1; p=REALLY-LONG-KEY"
DMARC Record
DMARC is used to define, how you would like to treat mail that violates your SPF/DKIM records and policy. It's added as simple as that:
_dmarc.example.com. 18000 IN TXT "v=DMARC1; p=none"
DMARC Policy
Please pay attention to p=none
in your record. This is policy variable. Replace this to p=quarantine
if you want to treat all mail with invalid headers as spam. Replace this to p=reject
if you do not want to receive mail with invalid headers at all.
Performing SPF/DKIM validity and integrity tests.
SPF test
Visit SPF testing tool for SPF validation. Give there your domain name and IP address. If your record is correct, you'll see your SPF record content in green, like this:
v=spf1 a mx -all
DKIM test
Visit DKIM validation tool for DKIM integrity check. Input there your domain and DKIM selector, which we defined earlier. If everything in your record is correct, you will see your DKIM record content in green