1. Introduction

Have you ever thought about setting up your own email server, but then left it behind. However, setting up a email server is not complicated. In this article, we will build it step by step from scratch.

Here we will need the following environments:

  • Nginx - an lightweight and open-source web server to offer low memory usage and high concurrency.
  • Docker - a set of platform as a service (PaaS) products that use OS-level virtualization to deliver software in packages called containers.
  • iRedMail - The right way to build your mail server with open source softwares.

2. Installation

we will install and configure all necessary software in order. And following the steps you will almost get your own email server.

2.1 Install iRedMail

For convenience, we use docker-compose to defining and running the iRedMail applications, create the Compose file with the name iredmail.yml and it’s content below:

version: "3"

    container_name: iredmail
    image: lejmr/iredmail:mysql-latest
    restart: always
    hostname: mail.example.com
      - iredmail_mysql:/var/lib/mysql
      - iredmail_vmail:/var/vmail
      - iredmail_clamav:/var/lib/clamav
      DOMAIN: example.com
      HOSTNAME: mail
      MYSQL_ROOT_PASSWORD: password
      TIMEZONE: "Europe/London"
      IREDAPD_PLUGINS: "['reject_null_sender', 'reject_sender_login_mismatch', 'greylisting', 'throttle', 'amavisd_wblist', 'sql_alias_access_policy']"

    driver: bridge
        - subnet:


Building and running the service:

$ sudo docker-compose -f iredmail.yml up

Press Ctrl+C (or Ctrl+\ ) to detach you from the container.

If you encounter starting server(s) uwsgi failed, you should do the uwsgi checking:


Attach to the container:

$ sudo docker exec -it iredmail /bin/bash

Run uwsgi with specific iredmail.ini mannually:

$ uwsgi --ini /etc/uwsgi/apps-available/iredadmin.ini

2.2 Configuring DNS Records

Best practices for email authentication, here I recommend you always set up these email authentication methods for your domain:

  • SPF helps servers verify that messages appearing to come from a particular domain are sent from servers authorized by the domain owner.
  • DKIM adds a digital signature to every message. This lets receiving servers verify that messages aren’t forged, and weren’t changed during transit.
  • DMARC enforces SPF and DKIM authentication, and lets admins get reports about message authentication and delivery.

2.2.1 Create A record

mail.example.com  a

2.2.2 Create MX record

mail.example.com  mx

2.2.3 Create TXT record for SPF

v=spf1 ip4:<server_ip> ~all


v=spf1 mx mx:mail.example.com ~all

2.2.4 Create TXT record for DMARC

_dmarc.example.com  txt  v=DMARC1;p=reject;rua=mailto:admin@example.com; adkim=s;aspf=s

2.2.5 Create TXT record for DKIM

At frist, we need to attach to the container:

Find below setting in Amavisd config file amavisd.conf (find its location on different Linux/BSD distributions):

dkim_key('example.com', "dkim", "/var/lib/dkim/example.com.pem");

@dkim_signature_options_bysender_maps = ( {
    "example.com"  => { d => "example.com", a => 'rsa-sha256', ttl => 10*24*3600 },

And then we need to get the DKIM keys:

$ amavisd-new showkeys


Now we copy the DKIM keys and create the TXT record:

dkim._domainkey.example.com v=DKIM1; p=MIIBIjANBgkqhkiG9...8ZEqo/QIDAQAB

Subsequently, we test the txt record:

$ amavisd-new testkeys


$ dig -t txt dkim._domainkey.example.com



2.4 Nginx config

Create the nginx site config:

$ sudo vim /etc/nginx/sites-available/iredadmin

Type the following content:

# mail.example.com
server {
  listen 80;

  server_name mail.example.com;
  access_log  /var/log/nginx/mail.example.com.access.log;

  location /.well-known/ {
    root /var/www/acme/;

  location / {
    return 302 https://$host$request_uri;

server {
  listen 443;

  # using web sub domain to access
  server_name mail.example.com;
  access_log  /var/log/nginx/mail.example.com.access.log;

  ssl_certificate       /etc/nginx/ssl/mail.example.com/fullchain.cer;
  ssl_certificate_key   /etc/nginx/ssl/mail.example.com/private.key;
  ssl_protocols         TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers           HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;

  location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;


Create the nginx stream config:

$ sudo vim /etc/nginx/streams-available/iredadmin

Type the following content:

# mail server proxy
server { listen 25; proxy_pass; }     # SMTP
server { listen 587; proxy_pass; }   # SMTP(STARTTLS)
server { listen 143; proxy_pass; }   # IMAP(STARTTLS)
server { listen 993; proxy_pass; }   # IMAP
server { listen 110; proxy_pass; }   # POP3
server { listen 995; proxy_pass; }   # POP3

And then create the symbolic links:

$ ln -s /etc/nginx/sites-available/iredmail /etc/nginx/sites-enabled/iredmail
$ ln -s /etc/nginx/streams-available/iredmail /etc/nginx/streams-enabled/iredmail

Afterwards, don’t forget to restart the nginx service:

$ sudo service nginx force-reload

3. Finish

Up to this point, all the installation work has been completed, and we are almost about to get our own email server,

3.1 Login iRedAdmin

Open the iredmail Admin:


Login use default account postmaster@example.com, and then create your own email account.



3.2 Test Email Server

For better use and no spammyness, we use this free online service to test the emails for Spam, Malformed Content and Mail Server Configuration problems.

If all goes well, we will get full marks, otherwise, we will get the tips on current problems: