Installing a Mailserver on Ubuntu 14.04 LTS Part 1

Introduction

Why I wrote this.

I wrote this HOWTO as record of what I did to get my own mail server up and running. I can now and in the future follow these steps again and rebuild my own mail server. I hope it is of use to others too.

For this how to I am using my test networking lab, Setup a Test Networking Lab with VirtualBox.

I am assuming you already know how to install a minimal Ubuntu server with only ssh installed.

We will run through the setup of this one step at a time, hopefully not making any huge steps. You will be able to test the parts installed as we go, no huge big bangs. All this as we move gently towards our goal of a professional quality mail server running on Ubuntu Server.

There are some holes in the security of this server. e.g No firewall.

Note: You are strongly recommended to take backup copies of your system and all files before you start and as we progress through the HOWTO.

The mail server which this HOWTO will be building is called mailserver and will be running Ubuntu Server edition. mailserver will run as a Virtual Box guest which allows for simple backups if nothing else. mailserver will be part of the dragon.lab domain.

mailserver.dragon.lab local IP 10.1.200.7

Services provided on mailserver

The server called mailserver will end up running the following servers and services. Once all the parts of this series posts are completed.

  • Postfix mail server.
    • Delivering email to one or more local users.
    • Email recipients will not have to have a local Linux account.
    • Forwarding mail to remote users, from a lookup list only
    • Relaying emails to the outside world
    • Authentication and encryption TLS/SSL
    • Encrypted passwords
  • MySQL Database

Install Ubuntu Server Edition.

We are starting from a minimal install of Ubuntu Server with no other software installed. During the installation process there will be a menu asking what other servers should be installed. I only install openssh here. ssh will allow you to ssh into your new server mailserver. This will make copy and paste operations easier and you can make the terminal bigger as well as have more than one. The bigger and more numerous terminals make editing much easier. ❗

After the install is done make sure it is all up to date with the latest patches and security updates.

sudo apt-get update
sudo apt-get dist-upgrade

Install nfs and autofs. These make transferring files simpler. I used these mappings a lot while writing this HOWTO as I installed the complete system a number of times. If at first you don’t succeed, go and have another beer.


HOWTO:Set up NFS sharing

Network Config

Network interface. Get this sorted out so mailserver has a static IP address.

sudo nano /etc/network/interfaces

It should look something like this

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
   address 10.1.200.7
   gateway 10.1.200.1
   netmask 255.255.255.0
   dns-nameservers 10.1.200.1
   dns-search dragon.lab

Make sure that the fully qualified domain name is setup and displayed correctly.

hostname --fqdn

The command above should be displaying the following for mailserver.

mailserver.dragon.lab

It is does not the problem can be solved by editing the hosts file as follows.

sudo nano /etc/hosts
10.1.200.7 mailserver.dragon.lab mailserver

Note that the FQDN is first in the list and the short name without the domain part is not.

This would be a good backup point!
You can always restore back to this point if you mess up on the way.

MySQL

How Postfix talks to MySQL

We are going to create a bunch of map files that tell Postfix how to get the information out of the MySQL database. They are fairly simple and I am sure you will work out how they do their mapping without explanation. In each file change mysqlpasswd to be the password you use for your MySQL user mail. Also, when setting the hosts value do not use localhost, Use the IP address 127.0.0.1, which although it is also localhost it will force postfix to use TCP/IP and not a local socket. This will allow you to run Postfix chrooted if you so wish and is slightly more secure.

Installing MySQL

Installing Postfix and MySQL we need Postfix and dovecot, along with the MySQL server and packages to connect to each. These will be installed with the following command.

sudo apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d \
dovecot-lmtpd dovecot-mysql mysql-server

While these packages are installing you will be asked some questions:

MySQL Password, just make one up and remember it!
Do create the self-signed certificates, we use them later.
General type of mail configuration: Internet Site
System mail name: dragon.lab

When the installation process starts you will be asked for a MySQL root password. This is the password for the root user of MySQL this is not the same as the root user on the Linux system.

Simple MySQL Security Measures

Run the script mysql_secure_installation to remove unnecessary users and the test database. It will also allow you to setup a password for the root MySQL user. But you already did that, didn’t you.

mysql_secure_installation

If you did not set a password when the MySQL server was installed the password will be blank, so you can press return. Otherwise enter the password you have already created. You will be asked a number of questions, the first one will be asking if you want to enter a new password. If you have not already set one enter ‘y’ and enter one now.

For the remaining questions you can press return to accept the default, which is ‘yes’.

Remove anonymous users?
Disallow root login remotely?
Reload privilege tables now?

Configuring MySQL

We will edit the system MySQL my.cnf file to check on access and get some logging to happen.

sudo nano /etc/mysql/my.cnf

We want to bind to 127.0.0.1 not localhost. This a means there can be no connections from remote machines, which means that we have a security advantage in that only users already logged in to mailserver can access the MySQL database. It should already be set, as it is the default.

bind-address = 127.0.0.1

I find it is helpful to see what the mysql DB is doing especially in the early stages. Use these options to start the logging of any queries or requests that are made to MySQL. It is probably commented out.

general_log_file = /var/log/mysql/mysql.log
general_log = 1

Then in a few weeks when all is running correctly comment those out again, as the logging slows mysql down.

Restart the MySQL daemon.

sudo service mysql restart

Creating the Database

To create a MySQL database is very simple from the command line. We will be calling our database ‘postfix’ as it is for Postfix and I like to keep things simple. 🙂 We need to login as the user root and tell the command to ask for a password. We do that with the following command:

mysqladmin -u root -p create postfix

When you run the command above you will be asked for a password. It is the MySQL password for root, it is the one you entered when you installed MySQL server or entered when securing the MySQL installation. There is no feedback in the way of text output to say the database was created. If you want to check you can login to the database using the mysql command and issue the show databases command. If all went well you will see a line with postfix.

mysql -u root -p postfix
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| postfix            | -- This is the one we are looking for
+--------------------+
4 rows in set (0.00 sec)

The other way to monitor what is going on behind the scenes with MySQL is to watch the mysql log file. Open a new terminal and use the following command to follow the end of the log file as it is written.

tail -fn90 /var/log/mysql/mysql.log

Creating our MySQL User

We will be needing a user with restricted permissions to access the tables for lookups. This user will only need to SELECT data never INSERTing or UPDATEing.

mysql -u root -p postfix

and enter this SQL command when you see the mysql> prompt:

GRANT SELECT ON postfix.* TO mail@localhost IDENTIFIED BY 'mysqlpasswd';

This will create a new user called mail who just has SELECT access to our database. To get these new permissions noticed by Mysql you need to flush them. So before you exit the mysql prompt use the following command.

flush privileges;
SELECT user, password FROM mysql.user where user = 'mail';
Query OK, 0 rows affected (0.00 sec)

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

+------+-------------------------------------------+
| user | Password                                  |
+------+-------------------------------------------+
| mail | *E18AD7C50020B1483DHD5OP0D92C2AA45DDDD123 |
+------+-------------------------------------------+
1 row in set (0.00 sec)

Creating the tables

We will be using three tables to interface between Postfix and MySQL. The way I create them it to add the SQL commands to a text file and then load them in via the mysql command. This saves a lot of typing. It also means that when you are testing and trying out different options it is easy to delete all the data and start again.

USE postfix;

DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS alias;
DROP TABLE IF EXISTS domain;

CREATE TABLE domain (
   domain VARCHAR(50) NOT NULL,
   PRIMARY KEY (domain)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 

CREATE TABLE user (
   email VARCHAR(255) NOT NULL,
   domain VARCHAR(50) NOT NULL,
   password VARCHAR(110) NOT NULL,
   PRIMARY KEY (email),
   KEY (domain),
   FOREIGN KEY (domain) REFERENCES domain(domain) 
           ON UPDATE NO ACTION ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 

CREATE TABLE alias (
   id int(11) unsigned NOT NULL AUTO_INCREMENT,
   source varchar(255) NOT NULL,
   destination varchar(255) NOT NULL,
   PRIMARY KEY (id),
   KEY source_idx (source),
   KEY dest_idx (destination)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Create a blank file called create_postfix_mysql_tables.sql, add the text above and then save it. You can then import create_postfix_mysql_tables.sql and issue the commands it contains with the following:

mysql -u root -p postfix < create_postfix_mysql_tables.sql

If you want to see that the tables have now been created use the following.

mysql -u root -p postfix
mysql> show tables;
+-------------------+
| Tables_in_postfix |
+-------------------+
| alias             |
| domain            |
| user              |
+-------------------+
3 rows in set (0.00 sec)
This would be a good backup point!

Postfix

Configuring Postfix

The configuration for postfix is controlled via two files main.cf and master.cf in this part we only need to change main.cf.

sudo nano /etc/postfix/main.cf

Amend, delete or comment out the TLS lines:

Existing lines should be as follows and should be commented out:

#smtpd_use_tls = yes
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

The new lines will want are:

# We will the client end uses STARTTLS, i.e they may use it if they want
# This allows local clients i.e. Squirellmail to connect without fuss
smtpd_tls_security_level = may

Now add the following lines to the end of the file. These are to enable SMTP authenticated users

#Enabling SMTP for authenticated users, and handing off authentication to Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth
smtpd_sasl_auth_enable = yes

smtpd_recipient_restrictions = permit_sasl_authenticated,
           permit_mynetworks,
           reject_unauth_destination

Update, comment out the mydestination value so it reads:

# mydestination = localhost

Add a new line to enable Dovercot's LMTP

virtual_transport = lmtp:unix:private/dovecot-lmtp

Save the changes and exit.

This would be a good backup point!

Create Postfix Map Files For MySQL

The Postfix map files are how we tell Postfix to talk to the MySQL database. Each file contains key = value pairs of data telling Postfix how it can connect and send a query to the database and therefore retrieve the data it requires. Once these map files are created we will add them to the Postfix configuration file /etc/postfix/main.cf using the command line tool postconf. The resulting change will automatically be written to the file and the postfix configuration can be reloaded.
Mapping valid Domains

How to find valid domains within our system. The domain table holds one row for each domain that our mailserver will be accepting mail for and that it will deliver to the end user. With an editor create the domain lookup file with the following details. You will need to change the password from mysqlpasswd to whatever you are using as the password for your MySQL user "mail".

sudo nano /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT domain FROM domain WHERE domain = '%s'

Add the line to /etc/postfix/main.cf from the command line.

sudo postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

Mapping Users

As we are intending to use our mailserver to deliver emails to users including but not limited to those that also have Linux accounts. We need to use virtual mappings. This is so Postfix will know where to deliver the email to. It will be a directory on the file system. We certainly do not want to create a user account and home directory for all our email users. We will define a top level directory /var/vmail where the email will be stored. The data held in the mappings in the virtual tables will be used to construct the lower part of the directory tree. The actual location of the mail subdirectory. For each user we will have:

/var/vmail/vhosts//user_name

The domain and user name are derived from their actual email address for fred@dragon.lab we will see this directory structure.

/var/vmail/vhosts/dragon.lab/fred
sudo nano /etc/postfix/mysql-virtual-mailbox-maps.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT email FROM user WHERE email='%s'
sudo postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

Mapping aliases to Users

This maps email aliases to real email addresses. This means for one user name or destination we can have many email addresses. In a company all the emails for support@dragon.lab and info@dragon.lab will be delivered to fred@dragon.lab. Harry is the IT administrator and therefore gets mail that is not addressed to anyone in particular. That is Harry will get mail that cannot be delivered anywhere else. Most of which will be spam so he will no doubt work out a better way to deal with it later as he gets more experience :-). This is called a 'catch all email' alias. This can also be used as an effective anti-spam system. Whenever you deal with a new company simply create a new email alias from_company@dragon.lab aliased to your own real email address. If you start getting spam on that address you know they are spamming you or they have sold your address on. Either way you know it's a company you no longer wish to deal with. You can remove the email listing and no more spam from them. If there is no catch all email setup then those spam emails get thrown away.

sudo nano /etc/postfix/mysql-virtual-alias-maps.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT destination FROM alias WHERE source = '%s'
sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf

Assuming that all worked as before we can move on to that last mapping.

This mapping table is used as part of the virtual_alias_maps mapping and saves you having to map every user back to themselves. Why would you need to do that? You ask. See below it is to do with the way catch all addresses work.

sudo nano /etc/postfix/mysql-virtual-alias-maps-self.cf
user = mail
hosts = 127.0.0.1
dbname = postfix
password = mysqlpasswd
query = SELECT email FROM user WHERE email = '%s'

The following should be all on one line with no spaces after the '='.

sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf
As these lookup table files all contain passwords and in open text. They should not be world readable. We can do that by restricting the group permissions and removing all world read and write permissions.
sudo chgrp postfix /etc/postfix/mysql-*.cf
sudo chmod 640 /etc/postfix/mysql-*.cf
-rw-r----- 1 root postfix 124 2013-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps.cf
-rw-r----- 1 root postfix 116 2013-11-12 16:46 /etc/postfix/mysql-virtual-alias-maps-self.cf
-rw-r----- 1 root postfix 135 2013-11-12 16:45 /etc/postfix/mysql-virtual-mailbox-domains.cf
-rw-r----- 1 root postfix 114 2013-11-12 16:46 /etc/postfix/mysql-virtual-mailbox-maps.cf

Aliases are the mechanism that allows mail to be delivered in a very flexible way with a very simple setup. That is the users get their mail and you don't have too much extra work. 😉

sudo service postfix restart

Creating Some Test Users

To test those MySQL tables and the interface between Postfix and MySQL we will add some test data to the database. We can then test this is working by using the postmap command to read it back.

If we put the SQL required to build up some test data into a file, we can load it again when necessary while testing is on going and also add more data if required.

USE postfix;

DELETE FROM domain;
DELETE FROM user;
DELETE FROM alias;

INSERT INTO domain (domain) VALUES ('dragon.lab');

INSERT INTO user (email, domain, password) VALUES
    ('fred@dragon.lab', 'dragon.lab',  ENCRYPT('mysqlpasswd', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)))),
    ('harry@dragon.lab', 'dragon.lab', ENCRYPT('mysqlpasswd', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16))));

INSERT INTO alias (source, destination) VALUES
    ('root', 'fred@dragon.lab'),
    ('bert@dragon.lab', 'fred@dragon.lab'),
    ('postmaster@dragon.lab', 'fred@dragon.lab'),
    ('@dragon.lab', 'harry@dragon.lab');

You can then rebuild your data base with test data with the following command.

mysql -u root -p postfix < insert_test_data.sql

To check that the data was inserted correctly run the following queries.

mysql> SELECT * FROM domain;
+-------------+
| domain      |
+-------------+
| dragon.lab |
+-------------+
1 rows in set (0.00 sec)

mysql> SELECT * FROM user;
+------------------+------------+------------------------------------------------------------------------------------------------------------+
| email            | domain     | password                                                                                                   |
+------------------+------------+------------------------------------------------------------------------------------------------------------+
| fred@dragon.lab  | dragon.lab | $6$8a024ade09ec4b2e$70PtLJbZ.S316xiyhSnqm2EzMcbsb68NzFiJPhNTpSZP7dRyDkdRMyZ9cMAw0JODNNTXFtZjP2Eu4.2HPlN8u. |
| harry@dragon.lab | dragon.lab | $6$67b5d001ed54ba85$9nTBNbwr3wMgC677PfrLmB7OtEHiyAaXLmYEGjtpI5DO/ZhcYsA520/tupLt.ij191gGlYmokGCQj6seRJtN7. |
+------------------+------------+------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> SELECT * FROM alias;
+----+------------------+-------------------+
| id | source | destination |
+----+------------------+-------------------+
| 1 | root | fred@dragon.lab |
| 2 | bert@dragon.lab | fred@dragon.lab |
| 3 | postmaster@dragon.lab | fred@dragon.lab |
| 4 | @dragon.lab | harry@dragon.lab |
+----+------------------+-------------------+
3 rows in set (0.00 sec)

We can now do some very simple tests to check the Postfix-MySQL interface it working. The first test will lookup dragon.lab to see if it is valid domain for our system. If it is it will return dragon.lab. Also try this with a domain name that is not valid.

sudo postmap -q dragon.lab mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf

We can lookup a user to see if they are a real use. This test should return fred@dragon.lab as he is valid.

sudo postmap -q fred@dragon.lab mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

This final test checks that aliases are working bert@dragon.lab is an alias for fred@dragon.lab. So we should see Fred's email address.

sudo postmap -q bert@dragon.lab mysql:/etc/postfix/mysql-virtual-alias-maps.cf
This would be a good backup point!

Dovecot

Installing Dovecot

To get POP3 and IMAP features from your mail server we will need Dovecot. It should have been installed above.

Creating a vmail user

We are using virtual users on this mailserver. Which means not all users will have a HOME directory in which we can store incoming emails. So we will store all mail in one directory structure as explained above. Look for a silver text box.

The email and directory structure need to be secure. We use a non privileged user vmail let's create that user and group now.

sudo groupadd -g 6004 vmail
sudo useradd -g vmail -u 6004 vmail -d /var/vmail -m -s /sbin/nologin

To check these have been created okay, we can look in the passwd and group files.

grep vmail /etc/passwd /etc/group
/etc/passwd:vmail:x:6004:6004::/var/vmail:/sbin/nologin
/etc/group:vmail:x:6004:

Create the top level directory where emails will be stored. The remaining structure will be created as required. We also need to change the owner and group.

sudo mkdir -p /var/vmail/vhosts/dragon.lab
sudo chown -R vmail:vmail /var/vmail

ls -dl /var/vmail/vhosts
drwxr-xr-x 3 vmail vmail 4096 Nov 30 09:52 /var/vmail/vhosts/

Configuring Dovecot

Make a copy of all the dovecot config files files before we start.

cd /etc/dovecot
sudo mkdir backup
sudo cp -a [cdR]* backup
sudo nano /etc/dovecot/dovecot.conf

Towards the top you should see the line

!include_try /usr/share/dovecot/protocols.d/*.protocol

Add the following line right after it

protocols = imap pop3 lmtp

Towards the end of the file look for a line like this, add it if necessary

!include conf.d/*.conf

Save the changes and exit.

sudo nano /etc/dovecot/conf.d/10-mail.conf

Add the fiollowing lines, you should be able to find the right place by searching for the variable name. I needed to comment it out and then replaced it with the following.

mail_location = maildir:/var/vmail/vhosts/%d/%n
mail_privileged_group = vmail

Save the changes and exit.

Again, add the following lines, you should be able to find the right place by searching for the variable name. It will most likely be commented out in the file.

sudo nano /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Save the changes and exit.

Update the authentication file

sudo nano /etc/dovecot/conf.d/auth-sql.conf.ext

The file auth-sql.conf.ext should contain only the following, update what is there by removing and adding comments as required.

passdb {
   driver = sql
   args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
   driver = static
   # The home value should be the same as the mail_location from 10-mail.conf
   args = uid=vmail gid=vmail home=/var/vmail/vhosts/%d/%n
}

Save the changes and exit.

sudo nano /etc/dovecot/dovecot-sql.conf.ext

Now change the following lines after finding them in the original file. There is a password in this one change it as necessary.

    driver = mysql
    connect = host=127.0.0.1 dbname=postfix user=mail password=mysqlpasswd
    default_pass_scheme = SHA512-CRYPT
    password_query = SELECT email as user, password FROM user WHERE email='%u';

Save the changes and exit.

sudo nano /etc/dovecot/conf.d/10-master.conf

Disable the protocols for unencrypted IMAP and POP3 by setting the ports to 0.

service imap-login {
       inet_listener imap {
       port = 0
    }
...
}

service pop3-login {
     inet_listener pop3 {
     port = 0
  }
  ...
}

Add the following to turn on LMTP. replace the existing text block with this:

service lmtp {
   unix_listener /var/spool/postfix/private/dovecot-lmtp {
     mode = 0600
     user = postfix
     group = postfix
   }
   # Create inet listener only if you can't use the above UNIX socket
   #inet_listener lmtp {
      # Avoid making LMTP visible for the entire internet
      #address =
      #port =
   #}
}

Update the service auth block to like like this:

service auth {
    # auth_socket_path points to this userdb socket by default. It's typically
    # used by dovecot-lda, doveadm, possibly imap process, etc. Its default
    # permissions make it readable only by root, but you may need to relax these
    # permissions. Users that have access to this socket are able to get a list
    # of all usernames and get results of everyone's userdb lookups.
    unix_listener /var/spool/postfix/private/dovecot-auth {
       mode = 0666
       user = postfix
       group = postfix
    }

    unix_listener auth-userdb {
       mode = 0600
       user = vmail
       #group =
    }

    # Postfix smtp-auth
    #unix_listener /var/spool/postfix/private/dovecot-auth {
       # mode = 0666
    #}

    # Auth process is run as this user.
    user = dovecot
}

set the user to vmail in the service auth-worker block

user = vmail

Save the changes and exit.

Take the SSL cert and key file into use:

sudo nano /etc/dovecot/conf.d/10-ssl.conf
ssl = required

Save the changes and exit.

Add a default email address for errors and warnings about our mailserver. We created an alias for postmaster@dragon.lab to fred@dragon.lab, fred is our SysAdmin email address so he gets spammed with these 🙂

sudo nano /etc/dovecot/conf.d/15-lda.conf
postmaster_address = postmaster@dragon.lab

Save the changes and exit.

Update the permissions as one of the files contains a password in the open. Restart dovecot to take the changes into use.

cd /etc/dovecot
sudo chown -R vmail:dovecot /etc/dovecot/*
sudo chmod 640 *conf *ext conf.d/*
sudo chmod 750 conf.d

sudo service dovecot restart

Sending Your First Email

Now it's time to send our first email 🙂 Are you sitting down, this is a momentous occasion after all!

Setting up Evolution

At this point we can set up Thunderbird or Evolution or any other email client. Using Evolution it is easy to create a new account that points at our new server. I'm sure you can work this out but here is a very quick and dirty description. You will only need one of the IMAP+ or POP3 configurations.

  • Server Type: IMAP+
    • Email address: fred@dragon.lab.
    • Server Type: IMAP+
    • Server: mailserver.dragon.lab
    • Port: 993
    • Username: fred@dragon.lab
    • Encryption method: SSL on Dedicated port
    • Authentication: Password
    • Server Type: POP3
      • Email address: fred@dragon.lab.
      • Server Type: POP3
      • Server: mailserver.dragon.lab
      • Port: 995
      • Username: fred@dragon.lab
      • Encryption method: SSL on Dedicated port
      • Authentication: Password
      • Server Type: SMTP
        • Server: mailserver.dragon.lab
        • Port: 25
        • TICK, Server requires authentication
        • Encryption Mathod: start TLS after connecting
        • Username: fred@dragon.lab
        • Auth Type: Login

      You should now be able to send and receive emails for fred@dragon.lab and harry@dragon.lab YAY! Emails sent to bert@dragon.lab will be collected by fred when he logs in an downloads his email.

      When your own live mailserver is setup you can employ a simple email spam reduction process. Whenever you start dealing with a company, acme, create a unique email address for Acme to use and forward it to your login account. You can use something like from_acme@dragon.lab. If you ever get any spam on that email you know that Acme was hacked and gave out your email or simply sold it on. You can stop dealing with them and stop the spam by deleting the forwarding email from_acme@dragon.lab.

      It also helps your email client sort email into folders when it is delivered.

      If All is working. Now would be a good time to make a full backup of your new server
      

      Testing from the real world

      This test cannot be performed when running inside the test network lab!

      Once that is all in place you can test it out with a real world test site. This will test your mail server is configured correctly and is not an open-relay that spammers can use. The site connects to your mail server repeatedly with different parameters and takes about a minute to finish.

      To do this test you need to know the IP address of your router on the internet side. It will not start with 10.1.200... You will also need to pass any connections to that IP adress on ports 993, 995 and 25 through to the machine you just configured. Use a startpage search to find out how.

      sudo telnet relay-test.mail-abuse.org
      

      You should see a message

      System appeared to reject relay attempts
      

      In Part 2

      In part 2 of this series we will be adding In this part we will be building on this server and adding anti-virus and anti-spam software and a tool to greylist emails to cut down on the work our server has to do. This will be added to postfix via amavis-new.

26 thoughts on “Installing a Mailserver on Ubuntu 14.04 LTS Part 1

  1. Brent

    Thank you for a fantastic walkthru to getting an email server up and rolling. Is there a web interface you recommend for adding users?

    Reply
    1. Richard Post author

      Thank you for the kind words. I use Squirrelmail for webmail to my own postfix server. Roundcube is another one that is used by many and I have set that up where I work. As for a web front end for adding users I’ve never found a need for one. 🙂 A quick search found this link that has a bunch of GUI’s for postfix https://www.debianhelp.co.uk/postfixweb.htm I hope that helps.

      Reply
  2. Tony

    Thanks for an excellent guide.
    As a real noobie it was just what I needed – thankyou. I followed your instructions slowly and implicitly and after correcting my own typos was left with only 3 changes to make things work:
    1) ‘sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf’ seemed to conflict with ‘sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-virtual-alias-maps-self.cf’ and it generated warning messages when postfix restarted. I just removed the first one and it worked fine.
    2) I had to include ‘queue_directory = /var/spool/postfix’ in main.cf
    3) I had to edit /etc/dovecot/conf.d/10-mail.conf to add ‘mail_privileged_group = mail’ or else the user folder directories and files were not auto-generated.
    I have no idea whether the above is right, or whether I’ve compromised anything, but it works fine on Mint Qiana (which is based on Ubuntu 14.04).
    You’ve given us a brilliant template so thank-you from one happy bunny.
    I’m now moving on to your later guides.

    Reply
    1. Richard Post author

      Hi sorry for the delay, life got a little pressing and I needed to sort that out first.

      You need both of the lookup files below for the virtual users to work as explained in the text

      /etc/postfix/mysql-virtual-alias-maps.cf,mysql
      /etc/postfix/mysql-virtual-alias-maps-self.cf

      Reply
  3. theo theunissen

    In file /etc/postfix/main.cf, there is a line
    myhostname = UNKNOWN

    I couldn’t deliver mail to some mailservers because of the UNKNOWN.

    You have to modify the line into
    myhostname = dragon.lab

    Reply
    1. Richard Post author

      It looks like you forgot to set the hostname correctly in the file /etc/hosts. It’s explained at the top before installing any new software. Also the postfix variable myhostname you mention should be the same as the actual machine name not the domain name, it makes life simpler.

      Reply
  4. Vladimir

    Hello, articel seemd very good, and I tried it.
    And droped into problems.
    I can send e-mail, and receive them, but:
    – mails are delivered into /var/mail/ not in /var/vmail/vhosts//
    – mails can receive only users who have account on server.
    (This is not place for a question, but i haven’t seen faq)
    Thank Youa and best regards,
    vladimir

    Reply
    1. Richard Post author

      I did not work because you missed off some steps. The steps that set postfix to use /var/vmail/vhosts/ as the mail repository and the postfix to mysql map files to lookup users that are not Linux system users.

      There is no FAQ as all you need to do is follow the following steps:

      • You need to read the tutorial.
      • Following all the steps.
      • In the order they were written.
      • Including those you missed off last time.
      • Do not skip over text, read it.
      Reply
  5. deni

    Hallo,

    thank you very much for such a nice “How to”. Almost everything is fine. I have a one issue. What is the password for user “fred”. If i am configuring the thunderbird. It`s ask a password. Is it a “mypassword” or something else?

    Reply
    1. Richard Post author

      I hope you found it useful. If you look at the section “Creating Some Test Users” in the SQL where you insert the two users fred and harry, the password you need is the first string after ENCRYPT(. In the example it is ‘mypasswd’

      Reply
  6. Onur

    Sorry for commenting twice, here is my dovecot log ( /var/log/mail.log file )

    email dovecot: imap-login: Disconnected (auth failed, 3 attempts in 7 secs): user=, method=PLAIN, rip=someip, lip=someip, TLS, session=

    Thanks.

    Reply
    1. Richard Post author

      You have either misspelled the user name /password or you have configured the mail server as TLS only and from the log you are using plain authentication

      Reply
  7. Bogdan

    Can this configuration be used with Rainloop or Roundcube ? Even better, would you consider posting a detailed tutorial on configuring a webmail on Ubuntu 14.04, with postfix/dovecot?

    Appreciate it
    Bogdan

    Reply
  8. Yannick-Céphas

    Hello !
    Thank you very much for your tutorial, it really helped me a lot.
    I wanted to know how I could create two virtual domains on the same server with user@domain and user@virtual_domain pointing on the same mail box? Is it enough to create the user@virtual_domain as an alias of user@domain in the table alias, or do I need something else?

    Reply
    1. Richard Post author

      If I remember correctly, use need to add both domains to the domain table and then as you said just a simple alias back to user@domain which show be a user in the user table. I used to run through all that its still there is the Server set up for 12.04. I will put it back when 16.04 comes out. 🙂

      Reply
  9. Pierre

    Will you update this entire post for Ubuntu 16.04, and if yes, when do you believe you will have it done by.
    Just been searching hi and low for doing it in 16.04, but cannot find any. I did follow (not yours) other 14.04 examples for 16.04 server, but all failed, however they had succeeded on 14.04, hence I believe it is due to the new configuration files in Postfix and dovecot programs.

    Also, if you could provide a way to flush the postfix and dovecot files when you realize, that you spent enough time trying, and you would like to start over fresh, without re-installing the server.

    Reply
    1. Richard Post author

      Ubuntu 16.04 has not been released as yet, that is due next month. I will eventually get round to doing a blog post but probably not until June/July 2016 once it has settled done. For performing installs I have a PXE server and use a lot of preseed scripts that give me a way to automatically install servers and desktops for various uses. While I’m playing around I find it is quicker and simpler just to reinstall. For example it only takes about 15 minutes to do a clean install of the server version, I then know it is a clean install with nothing added or removed but some known changes I always add.

      Reply
  10. Luis Múzquiz

    Hello, im going to try your tutorial on 14.04 but i would love to see the 16.04 update. Thanks a lot.

    Reply
    1. Richard Post author

      I will be doing an update when I get round to updating my own mailserver to 16.04. But the weather here in the UK has just got warmer and the sun has finally come out. My choice is to stay inside playing with Ubuntu software or sit outside in the warm sunshine with a beer. 🙂

      Reply
  11. Emil

    After:
    GRANT SELECT ON postfix.* TO mail@localhost IDENTIFIED BY ‘mysqlpasswd’;

    I am getting that command has been done successfuly, but 0 rows were changed and 1 error occured, but don’t know which one. Any help please?

    Reply
    1. Richard Post author

      Turn the MySQL logging back on in /etc/mysql/my.cnf. Run a tail on /var/log/mysql/mysql.log and run the command again. It should help you find the error.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *