✉️ Setting up a personal email server

2021/02/13 by Paulo Pereira

~/categories/Linux #Linux #Debian #Vultr #Namecheap

I’ve been using my own personal email server for the last week.

These are my notes, inspired by Luke’s Smith emailwiz script.

Requirements

To setup your own email server you need to:

Server setup

I’ll be using Vultr to setup my email server.

You can get 100$ credit by using Luke Smith’s reference link. You can find it in his video description.

I chose a Debian 10 Cloud Compute machine in New York whith a 10 GB SSD, 1 CPU, 512MB of Memory and 500GB Bandwidth, for $3.50/month. Don’t forget to enable IPv6.

Make sure the 25, 933 and 587 ports are open. In the case of Vultr you must open a ticket and ask for it, because port 25 is closed.

In Vultr you can also setup a firewall. Make sure to open the 25, 933 and 587 ports and the 22 port for ssh.

Domain name

My domain name provider is Namecheap.

I’m using a ‘mail’ sub-domain. This way my setup is using ‘mail’ as the Host in the DNS records, instead of ‘@’.

The difference is that I’ll be accessing my email server using ‘mail.mydomain.com’ instead of just ‘mydomain.com’. The reason is the fact that I’m already using ‘mydomain.com’ with another server.

Setup two A records with your server IPv4 address and two AAA records with your server IPv6 address.

Type Host Value
A Record mail 10.11.12.13
A Record www.mail 10.11.12.13
AAAA Record mail 1234:aaaa:0:12ab:1111a:bcd:ffff:4444
AAAA Record www.mail 1234:aaaa:0:12ab:1111a:bcd:ffff:4444

Also, add a MX record for your mail. Even if you are using ‘mydomain.com’ to point to the server, use ‘mail.mydomain.com’ in the MX record.

Type Host Value Priority
MX Record @ mail.mydomain.com. 10

Accessing your server

You can access your server with ssh.

ssh root@mail.mydomain.com

Copy your ssh key to the server so you don’t need to write your password every time.

ssh-copy-id root@mail.mydomain.com

Now disable password access with ssh. This way only from your computer, with your private key your can access the server.

vim /etc/ssh/sshd_config

Make sure ‘UsePAM’ and ‘PasswordAuthentication’ are set to ’no’

UsePAM no
PasswordAuthentication no

Restart ‘sshd’:

systemctl reload sshd

Server setup and install needed software

Upgrade Debian:

apt update && apt upgrade

Some ‘.bashrc’ configuration:

vim .bashrc
	# ~/.bashrc: executed by bash(1) for non-login shells.
	
	# Note: PS1 and umask are already set in /etc/profile. You should not
	# need this unless you want different defaults for root.
	PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ '
	umask 022
	
	# You may uncomment the following lines if you want `ls' to be colorized:
	# export LS_OPTIONS='--color=auto'
	# eval "`dircolors`"
	alias ls='ls $LS_OPTIONS'
	alias ll='ls $LS_OPTIONS -l'
	alias l='ls $LS_OPTIONS -lA'
	#
	# Some more alias to avoid making mistakes:
	alias rm='rm -i'
	alias cp='cp -i'
	alias mv='mv -i'
	
	set -o vi
	
	TERM=xterm

Install ’nginx’ and ‘python-certbot-nginx’:

apt install nginx python-certbot-nginx

nginx setup

Configure your ‘mail.mydomain.com’ sub-domain:

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mail

vim /etc/nginx/sites-available/mail
	server {
		listen 80 ;
		listen [::]:80 ;
	
		root /var/www/mail;
	
		index index.html index.htm index.nginx-debian.html;
	
		server_name mail.mydomain.com www.mail.mydomain.com;
	
		location / {
			try_files $uri $uri/ =404;
		}

Enabling:

ln -s /etc/nginx/sites-available/mail /etc/nginx/sites-enabled/

systemctl reload nginx

Create a certificate with certbot

Easy as:

certbot --nginx
	Saving debug log to /var/log/letsencrypt/letsencrypt.log
	Plugins selected: Authenticator nginx, Installer nginx
	Enter email address (used for urgent renewal and security notices) (Enter 'c' to
	cancel): me@mydomain.com
	
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Please read the Terms of Service at
	https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
	agree in order to register with the ACME server at
	https://acme-v02.api.letsencrypt.org/directory
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	(A)gree/(C)ancel: A
	
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Would you be willing to share your email address with the Electronic Frontier
	Foundation, a founding partner of the Let's Encrypt project and the non-profit
	organization that develops Certbot? We'd like to send you email about our work
	encrypting the web, EFF news, campaigns, and ways to support digital freedom.
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	(Y)es/(N)o: Y
	
	Which names would you like to activate HTTPS for?
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	1: mail.mydomain.com
	2: www.mail.mydomain.com
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Select the appropriate numbers separated by commas and/or spaces, or leave input
	blank to select all options shown (Enter 'c' to cancel):
	Obtaining a new certificate
	Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/mail
	
	Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	1: No redirect - Make no further changes to the webserver configuration.
	2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
	new sites, or if you're confident your site works on HTTPS. You can undo this
	change by editing your web server's configuration.
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
	Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/mail
	
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Congratulations! You have successfully enabled https://mail.mydomain.com
	
	You should test your configuration at:
	https://www.ssllabs.com/ssltest/analyze.html?d=mail.mydomain.com
	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Setup the mail server

Here’s where Luke Smith’s script enters.

curl -LO lukesmith.xyz/emailwiz.sh

sh emailwiz.sh

In the end the script outputs 3 TXT record lines. You should now configure these records in your domain.

Type Host Value
TXT Record @ v=spf1 mx a:mail.mydomain.com -all
TXT Record _dmarc v=DMARC1; p=reject; rua=mailto:dmarc@mydomain.com; fo=1
TXT Record mail._domainkey v=DKIM1; k=rsa; p=XXXXXXX……

2021-06 Update: for the SPF record, I had to change it to the following to work.

Type Host Value
TXT Record @ v=spf1 a mx ~all

Create user mailboxes

Just create a user in the system:

useradd -G mail -m me
passwd me

This will create a me@mydomain.com email.

You can also create alias:

vim /etc/aliases
dmarc: me
mail: me
newaliases

This will delivery mails to dmarc@mydomain.com and mail@mydomain.com to your me@mydomain.com email.

Mail Clients

I’m using Thunderbird and K9 in Android.

Setup for a me@mydomain.com email:

Incoming Outgoing
Protocol IMAP SMTP
Server mail.mydomain.com mail.mydomain.com
Port 993 587
SSL SSL/TLS STARTTLS
Authentication Normal password Normal password
Username me me

Testing your new server

Check these sites to test if anything is wrong:

Also send an email to a gmail account to see your you’re going directly to Spam. It can happen, it’s just something you (and the people you will be sending emails) will have to live with.

Setting up backups

Check my BorgBackup posts for more info, but basically:

apt install borgbackup
ssh-keygen -o -a 100 -t ed25519
cat /root/.ssh/id_ed25519.pub

Add your key in BorgBase (Account > SSH Keys), create a new Repository and associate your SSH Key.

borg init --encryption=repokey-blake2 xxxx@xxxx.repo.borgbase.com:repo
echo "New backup"
borg create --list --progress --info --log-json --json --filter=AM -C lz4 --exclude '/root/.ssh/' xxxx@xxxx.repo.borgbase.com:repo::RepoName-{now:%Y-%m-%dT%H:%M:%S} /etc /var /root /opt /usr /boot /home/
echo "Prune"
borg prune -v --list --stats --keep-within=10d --keep-weekly=4 --keep-monthly=6 --keep-yearly=2 xxxx@xxxx.repo.borgbase.com:repo