Build Own Email Server With Linux Server
Build Own Email Server With Linux Server
If you would like to have your own email server, this is the right place for a tutorial,
based on the steps below I managed to create a working Email Server and learn a lot
of how it works in the backend.
A list with all the points that need to be touched in order for the server
to be operational.
In this post I will exaplain the first step from this list.
Postfix History:
Firstly, it facilitates the transfer of email messages from a mail client or mail user
agent (MUA) to a remote SMTP server.
Developed by Unix and security expert Wietse Venema, Postfix is not only user-
friendly but also meticulously crafted with a focus on security and modularity. Each
module operates at the minimum privilege level necessary to fulfill its function.
Postfix seamlessly integrates with Unix/Linux systems, abstaining from duplicating
functionalities already present in Unix/Linux. It exhibits reliability under various
conditions, whether simple or challenging.
This tutorial is dedicated to guiding you through the configuration of Postfix for a
single domain.
Discovering a suitable VPS (Virtual Private Server) provider for email hosting can be a
challenging task. Numerous hosting companies, often impose restrictions such as
blocking port 25. Consequently, users resort to setting up SMTP relays to circumvent
this block, incurring additional costs.
You can use Kamatera VPS, as a standout choice for hosting mail servers due to
several key advantages:
1. Unrestricted Port 25: Kamatera doesn't block port 25, eliminating the need for
complex workarounds.
2. Clean IP Address: Kamatera's IP addresses are not listed on any email blacklist,
providing assurance against potential deliverability issues.
3. PTR Record Editing: Users can edit PTR records, enhancing email deliverability
and avoiding potential blacklistings.
5. Multiple IP Addresses: Users can order multiple IP addresses for a single server,
facilitating the distribution of email traffic across multiple IPs for improved
deliverability.
To make Postfix perform better and get the most out of Postfix, you need to properly
set up your Ubuntu server.
In its default configuration, Postfix employs your server's hostname to establish its
identity during interactions with other Message Transfer Agents (MTAs). Hostnames
come in two forms: a single word and a Fully Qualified Domain Name (FQDN).
The single-word form is prevalent on personal computers, often naming Linux home
computers as "linux", "debian", "ubuntu", and the like. On Internet-facing servers,
it is recommended to utilize FQDN on mail servers. FQDN comprises two
components: a node name and a domain name. For example:
mail.yourdomain.com
mail is the nodename, yourdomain.com is the domain name. FQDNs will appear in
the smtpd banner. Some MTAs reject messages if your Postfix does not provide
FQDN in smtpd banner. Some MTAs even query DNS to see if FQDN in the smtpd
banner resolves to the IP of your mail server.
Enter the following command to see the FQDN form of your hostname.
hostname -f
If your Ubuntu server doesn’t have an FQDN yet, you can use "hostnamectl" to set
one.
You will need to go to your DNS hosting service (usually your domain register like
NameCheap, GoDaddy, AWS Route53) to set up DNS records
MX record
MX record @ mail.yourdomain.com
Again a common name for the MX host is mail.yourdomain.com. You can specify
more than one MX record and set priority for your mail servers. A lower number
means higher priority. Here we only use one MX record and set 0 as the priority
value. (values can range from 0 – 65535)
Note that when you create the MX record, you should enter @ or your apex domain
name in the name field. An apex domain name is a domain name without any sub-
domain.
A record
PTR record
To examine the PTR record associated with an IP address, utilize the following
command:
or
host enter_ip_here
The PTR record is not under the purview of your domain registrar; rather, it is
overseen by the entity that assigns your IP address. IP addresses are allocated by
your hosting provider, not your domain registrar. Consequently, it becomes
imperative to configure the PTR record for your IP address within your hosting
provider's control panel. The designated value for this PTR record should align with
your mail server's hostname, typically formatted as mail.your-domain.com.
Once the aforementioned steps are completed, we can proceed to configure Postfix.
Installing Postfix
You will be asked to select a type for mail configuration. Normally, you will want to
select the second type: Internet Site.
No configuration: means the installation process will not configure any parameters.
Internet Site: means using Postfix for sending emails to other MTAs and receiving
email from other MTAs.
Internet with smarthost: means using postfix to receive email from other MTAs, but
using another smart host to relay emails to the recipient.
Satellite system: means using smart host for sending and receiving email.
Local only: means emails are transmitted only between local user accounts.
Next, enter your domain name for the system mail name, i.e. the domain name after
@ symbol. For example, my email address is [email protected], so I entered
szkcorp.cloudns.ph for the system mail name. You should enter - yourdomain.com
(this is an example). This domain name will be appended to addresses that don’t
have a domain name specified.
Note: that if you enter a sub-domain like mail.your-domain.com, you will be able to
receive emails destined for @mail.your-domain.com addresses, but not be able to
receive emails destined for @your-domain.com addresses so be carefull.
Once installed, Postfix will be automatically started and a /etc/postfix/main.cf file will
be generated. Now we can check Postfix version with this command:
postconf mail_version
On Ubuntu 22.04, the Postfix version is 3.6.4, and Ubuntu 20.04 ships with version
3.4.10.
mail_version = 3.6.4
The ss (Socket Statistics) utility tells us that the Postfix master process is listening on
TCP port 25.
Postfix ships with many binaries under the /usr/sbin/ directory, as can be seen with
the following command.
Output:
/usr/sbin/postalias
/usr/sbin/postcat
/usr/sbin/postconf
/usr/sbin/postdrop
/usr/sbin/postfix
/usr/sbin/postfix-add-filter
/usr/sbin/postfix-add-policy
/usr/sbin/postkick
/usr/sbin/postlock
/usr/sbin/postlog
/usr/sbin/postmap
/usr/sbin/postmulti
/usr/sbin/postqueue
/usr/sbin/postsuper
/usr/sbin/posttls-finger
/usr/sbin/qmqp-sink
/usr/sbin/qmqp-source
/usr/sbin/qshape
/usr/sbin/rmail
/usr/sbin/sendmail
/usr/sbin/smtp-sink
/usr/sbin/smtp-source
The inbound TCP port 25 needs to be open, so Postfix can receive emails from other
SMTP servers. Ubuntu doesn’t enable a firewall by default. If you have enabled the
UFW firewall, you need to open port 25 (inbound) with the following command.
Then we can scan open ports on the mail server with an online port scanner. Enter
your mail server’s public IP address and select scan all common ports.
You can see from the above screenshot that TCP port 25 is open on my mail server.
The outbound TCP port 25 needs to be open, so Postfix can send emails to other
SMTP servers. The outbound TCP port 25 is controlled by your hosting provider, we
can install the telnet utility to check if it’s open or blocked.
telnet gmail-smtp-in.l.google.com 25
If it’s not blocked, you would see messages like below, which indicates a connection
is successfully established. (Hint: Type in quit and press Enter to close the
connection.)
Trying 74.125.68.26...
Connected to gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP y22si1641751pll.208 - gsmtp
In such a scenario, your Postfix faces a limitation in sending emails to other SMTP
servers. It becomes necessary to liaise with your Internet Service Provider (ISP) or
hosting provider and request the opening of the outbound port 25. Should your
request be denied, you have alternative options: either establish an SMTP relay to
circumvent the port 25 block or opt for a VPS solution, which does not impose
restrictions on port 25. ( I went with the SMTP relay in the end)
A common question will arise: "Can I change port 25 to another port to bypass
blocking?" The answer is no. Port changes are effective only when you have control
over both the server-side and client-side. In the context of Postfix sending emails, it
functions as the SMTP client, while the recipient's mail server operates as the SMTP
server. Since you lack control over the recipient's SMTP server, altering the port is not
a feasible solution. SMTP servers are designed to listen on port 25 for email
reception, and this standard expectation cannot be altered. Failure to connect to port
25 of the recipient's SMTP server will impede your ability to send emails.
As a matter of fact, we can now send and receive email from the command line. If
your Ubuntu server has a user account called user1, then the email address for this
user is [email protected]. You can send an email to root user
[email protected]. You can also send emails to Gmail, yahoo mail or any other
email service.
In this simple command, sendmail reads a message from standard input and make
“test email” as the message body, then send this message to your Gmail account.
You should be able to receive this test email in your Gmail inbox (or spam folder).
You can see that although we didn’t specify the from address, Postfix automatically
append a domain name for the from address. That’s because we added our domain
name in system mail name when installing Postfix.
Note: The From: domain name is determined by the myorigin parameter in Postfix,
not by the myhostname parameter.
You can try to reply to this test email to see if Postfix can receive email messages. It’s
likely that emails sent from your domain are labeled as spam. Don’t worry about it
now. We will solve this problem in later parts of this tutorial series.
postconf mail_spool_directory
If port 25 (outbound) is not blocked, but you still can’t send emails from your own
mail server to your other email address like Gmail, then you should open the mail log
(/var/log/mail.log) with a command-line text editor, such as Nano.
For example, some folks might see the following lines in the file.
This means your mail server is using IPv6 to send the email, but you didn’t set up
IPv6 records. You should go to your DNS manager, set AAAA record for mail.your-
domain.com, then you should also set PTR record for your IPv6 address. (PTR record
is managed by the organization that gives you an IP address.)
To save a file in Nano text editor, press Ctrl+O, then press Enter to confirm. To exit,
press Ctrl+X.
Enter the subject line and the body text. To tell mail that you have finished writing,
press Ctrl+D and mail will send this email message for you.
To read the first email message, type 1. If only parts of the message is displayed,
press Enter to show the remaining part of the message.
To display message headers starting from message 1, type h.
To show the last screenful of messages, type h$ or z.
To read the next email message, type n.
To delete message 1, type d 1.
To delete message 1, 2 and 3, type d 1 2 3.
To delete messages from 1 to 10, type d 1-10.
To replay to message 1, type reply 1.
To exit out of mail, type q.
By default, the attachment cannot be larger than 10MB, which is indicated by the
message_size_limit parameter.
Output:
message_size_limit = 10240000
This parameter defines the size limit for emails originating from your own mail server
and for emails coming to your mail server.
Note that the message_size_limit should not be larger than the mailbox_size_limit,
otherwise Postfix might not be able to receive emails. The default value of
mailbox_size_limit is 51200000 bytes (about 48MB) in the upstream Postfix package.
On Ubuntu, the default value is set to 0, as can be seen with
Output:
mailbox_size_limit = 0
This means that the mailbox has no size limit, which is great.
When sending an email with large attachments from your mail server, you should
also beware of the receiving server’s attachment size limit. For example, You will not
be able to send an attachment larger than 25MB to a Gmail address.
By default, Postfix SMTP server uses the OS’s hostname. However, the OS hostname
might change, so it’s a good practice to set the hostname directly in Postfix
configuration file. Open the Postfix main configuration file with a command-line text
editor, such as Nano.
Find the myhostname parameter and set mail.yourdomain.com as the value. It’s not
recommended to use the apex domain yourdomain.com as myhostname. Technically
you can use the apex domain, but it will create problems in later parts of this tutorial
series.
myhostname = mail.yourdomain.com
Save and close the file. (To save a file in Nano text editor, press Ctrl+O, then press
Enter to confirm. To exit, press Ctrl+X.) Restart Postfix for the change to take effect.
There are certain required aliases that you should configure when operating your
mail server in a production environment. You can add email alias in the /etc/aliases
file, which is a special Postfix lookup table file using a Sendmail-compatible format.
The first line is a comment. The second line is the only definition of an alias in this
file. The left-hand side is the alias name. The right-hand side is the final destination
of the email message. So emails for [email protected] will be delivered
to [email protected]. The postmaster email address is required by RFC 2142.
Normally we don’t use the root email address. Instead, the postmaster can use a
normal login name to access emails. So you can add the following line. Replace
username with your real username.
root: username
sudo newaliases
By default, Postfix uses both IPv4 and IPv6 protocols, as can been seen with:
postconf inet_protocols
Output:
inet_protocols = all
If your mail server doesn’t have a public IPv6 address, it’s better to disable IPv6 in
Postfix to prevent unnecessary IPv6 connections. Simply run the following command
to disable IPv6 in Postfix.
Upgrading Postfix
If you run sudo apt update, then sudo apt upgrade, and the system is going to
upgrade Postfix, you might be prompted to choose a configuration type for Postfix
again. This time you should choose No configuration to leave your current
configuration file untouched.
Congrats if you followed all steps until now. Now you have a basic Postfix email
server up and running. You can send plain text emails and read incoming emails
using the command line.
In the next part of this tutorial series, we will learn how to install Dovecot IMAP server
and enable TLS encryption, which will allow us to use a desktop mail client like
Mozilla Thunderbird to send and receive emails.
Welcome to part 2 of our tutorial series on building a secure email server from
scratch on Ubuntu. In part 1, we guided you through the setup of a fundamental
Postfix SMTP server. In this installment, our focus shifts to configuring the email
server for seamless sending and receiving through desktop email clients like Mozilla
Thunderbird or Microsoft Outlook.
Enabling the ability to send emails via a desktop client involves activating the
submission service in Postfix. On the receiving end, we'll install Dovecot, an open-
source IMAP server, on your Ubuntu server to facilitate the retrieval of emails using
a desktop email client. Ensuring the security of our communications, we'll also delve
into the installation of a TLS certificate. Let's dive in!
Ubuntu doesn’t enable firewall by default. If you have enabled the UFW firewall, then
you need to run the following command to open email related ports in firewall.
If you use POP3 to fetch emails (I personally don’t), then also open port 110 and 995
When we configure our desktop email clients, It’s always a good idea to enable TLS
encryption to prevent hackers from snooping on our emails. We can easily obtain a
free TLS certificate from Let’s Encrypt. Issue the following commands to install Let’s
Encrypt client (certbot) on Ubuntu server from the default software repository.
If you don’t have a web server running yet, I recommend you install one (Apache or
Nginx), because it’s easier to obtain and install TLS certificate with a web server than
using other methods. And in a later tutorial, I will show you how to set up webmail,
which requires running a web server.
If you use Nginx web server, then install the Nginx plugin. (The following command
will install Nginx web server if it’s not already installed on your system.)
You need to have an Nginx virtual host for mail.your-domain.com before obtaining
Let’s Encrypt TLS certificate. Create the virtual host file:
server {
listen 80;
listen [::]:80;
server_name mail.your-domain.com;
root /usr/share/nginx/html/;
location ~ /.well-known/acme-challenge {
allow all;
}
}
Save and close the file. Make sure the /usr/share/nginx/html/ directory exists on your
server.
Once the virtual host is created and enabled, run the following command to obtain
Let’s Encrypt certificate with Nginx plugin.
Where:
To send emails from a desktop email client, we need to enable the submission
service of Postfix so that the email client can submit emails to Postfix SMTP server.
Edit the master.cf file.
In submission section, uncomment or add the following lines. Please allow at least
one whitespace (tab or spacebar) before -o. In postfix configurations, a preceding
whitespace character means that this line is continuation of the previous line. (By
default the submission section is commented out. You can copy the following lines
and paste them into the file, so you don’t have to manually uncomment or add new
text.)
Microsoft Outlook mail client only supports submission over port 465. If you are
going to use Microsoft Outlook, then you also need to enable submission service on
port 465 by adding the following lines in the file.
Hint: The SMTP protocol is used when an email client submits emails to an SMTP
server.
Next, we need to specify the location of TLS certificate and private key in Postfix
configuration file. Edit main.cf file
Your Let’s Encrypt certificate and private key are stored under
/etc/letsencrypt/live/mail.your-domain.com/ directory.
Save and close the file. Then restart Postfix.
If you run the following command, you will see Postfix is now listening on port 587
and 465.
Enter the following command to install Dovecot core package and the IMAP daemon
package on Ubuntu server.
If you use POP3 to fetch emails, then also install the dovecot-pop3d package.
dovecot –version
Sample output:
2.3.16 (7e2e900c1a)
protocols = imap
If you use POP3 to fetch emails, then also add POP3 protocol.
By default, Postfix and Dovecot use mbox format to store emails. Each user’s emails
are stored in a single file /var/mail/username. You can run the following command to
find the mail spool directory.
postconf mail_spool_directory
Sample output:
mail_spool_directory = /var/mail
However, nowadays it’s almost always you want to use the Maildir format to store
email messages. The config file for mailbox location is /etc/dovecot/conf.d/10-
mail.conf.
mail_location = mbox:~/mail:INBOX=/var/mail/%u
Change it to the following to make Dovecot use the Maildir format. Email messages
will be stored under the Maildir directory under each user’s home directory.
mail_location = maildir:~/Maildir
We need to add the following line in the file. (On Ubuntu 18.04 and 20.04, this line is
already in the file.)
mail_privileged_group = mail
Save and close the file. Then add dovecot to the mail group so that Dovecot can read
the INBOX.
We need to configure Postfix to pass incoming emails to Dovecot, via the LMTP
protocol, which is a simplified version of SMTP, so incoming emails will saved in
Maildir format by Dovecot. LMTP allows for a highly scalable and reliable mail
system. It also allows us to use the sieve plugin to filter inbound messages to
different folders.
Save and close the file. Then edit the Dovecot 10-master.conf file.
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
disable_plaintext_auth = yes
It will disable plaintext authentication when there’s no SSL/TLS encryption. Then find
the following line,
#auth_username_format = %Lu
auth_username_format = %n
By default, when Dovecot tries to find or deliver emails for a user, it uses the full
email address. Since in this part, we only set up canonical mailbox users (using OS
users as mailbox users), Dovecot can’t find the mailbox user in full domain format
([email protected]), so we need to set auth_username_format = %n to
drop the domain part, then Dovecot should be able to find the mailbox user. This
also allows us to use the full email address ([email protected]) to log in.
auth_mechanisms = plain
This line only enables the PLAIN authentication mechanism. LOGIN is another
authentication mechanism you probably want to add to support older email clients.
ssl = required
ssl_cert = </etc/dovecot/private/dovecot.pem
ssl_key = </etc/dovecot/private/dovecot.key
By default, Dovecot uses a self-signed TLS certificate. Replace them with the
following values, which specify the location of your Let’s Encrypt TLS certificate and
private key. Don’t leave out the < character. It’s necessary.
ssl_cert = </etc/letsencrypt/live/mail.your-domain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.your-domain.com/privkey.pem
#ssl_prefer_server_ciphers = no
It’s a good practice to prefer the server’s order of ciphers over client’s. So
uncomment this line and change the value to yes.
ssl_prefer_server_ciphers = yes
If you use Ubuntu 20.04 or Ubuntu 22.04, disable insecure SSLv3, TLSv1 and TLSv1.1 by adding the
following line.
ssl_min_protocol = TLSv1.2
If you are using Dovecot version 2.2.x (as in Ubuntu 18.04), you should add the
following line to disable insecure TLS.
ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1
Ubuntu 22.04 ships with OpenSSL 3.0, which features a FIPS provider. However, it
won’t work with Dovecot. We need to diable the FIPS provider.
providers = provider_sect
#providers = provider_sect
If you don’t disable the FIPS provider in OpenSSL, Dovecot would produce the
following error.
imap-login: Error: Failed to initialize SSL server context: Can't load SSL certificate:
error:25066067:DSO support routines:dlfcn_load:could not load the shared library:
filename(libproviders.so)
To auto-create a folder, simply add the following line in the mailbox section.
auto = create
Example:
mailbox Trash {
auto = create
special_use = \Trash
}
Some common folders you will want to create includes: Drafts, Junk, Trash and
Sent. The Sent folder will be created under the user’s home directory when the user
send the first email. The Trash folder will be created when the user deletes an email
for the first time, etc. After you save and close all above config files, restart Postfix
and Dovecot.
Dovecot will be listening on port 143 (IMAP) and 993 (IMAPS), as can be seen
with:
If there’s a configuration error, dovecot will fail to restart, so it’s a good idea to check
if Dovecot is running with the following command.
Now open up your desktop email client such as Mozilla Thunderbird. Go to Edit ->
Account Settings -> Account Actions -> Add Mail Account to add a mail account.
You should now be able to connect to your own email server and also send and
receive emails with your desktop email client!
We use local Unix accounts as email addresses, as we did in part 1. For example, if
you have a user called user1 on your Ubuntu server, then you have an email address:
[email protected], and the password for the email address is the same
password for the user1 user. To create a local Unix account, run
It’s recommended to restart Dovecot after adding users, so Dovecot can recognize
new mailbox users.
Troubleshooting Tips
As a rule of thumb, you should always check the mail log (/var/log/mail.log) on
your mail server when an error happens. The following is a list of specific errors and
troubleshooting tips.
If you can’t log into your mail server from a desktop mail client, scan your mail server
to find if the ports (TCP 587, 465, 143, and 993) are open. Note that you should run
the following command from another Linux computer or server. If you run it on your
mail server, then the ports will always appear to be open.
You can also check the mail log (/var/log/mail.log), which may give you some clues. If
Dovecot fails to start, the error might not be logged to the /var/log/mail.log file, you
can run the following command to see what’s wrong.
For example, some folks may have the following error in the journal.
Most of the time, it’s a simple syntax error, like a missing curly bracket. Open the
configuration file, go to the specified line and fix the error.
If you find the following error message in the mail log
imap-login: Error: Failed to initialize SSL server context: Can't load DH parameters:
error:1408518A:SSL routines:ssl3_ctx_ctrl:dh key too small
ssl_dh = </etc/dovecot/dh.pem
Save and close the file. Then generate the DH parameter file with:
You can create Cron job to automatically renew TLS certificate. Simply open root
user’s crontab file.
sudo crontab -e
If you are using Nginx web server, then add the following line.
@daily certbot renew --quiet && systemctl reload postfix dovecot nginx
Reloading Postfix, Dovecot and the web server is necessary to make these programs
pick up the new certificate and private key.
If for any reason your Dovecot process is killed, you need to run the following
command to restart it.
Add the following lines in the file, which will make Dovecot automatically restart 5
seconds after a failure is detected.
[Service]
Restart=always
RestartSec=5s
Save and close the file. Then reload systemd for the changes to take effect.
Then check Dovecot status. You will find Dovecot automatically restarted.
In previous articles, we discussed how to set up your own mail server on Ubuntu
from scratch. In part 1 and part 2 of this tutorial series, we learned how to set up
Postfix SMTP server and Dovecot IMAP server, but so far we can only have email
addresses for users with local Unix accounts. This tutorial is going to show you how
to create virtual mailboxes on Ubuntu mail server with PostfixAdmin, which is an
open-source web-based interface to configure and manage a Postfix-based email
server for many domains and users.
With virtual mailboxes, we don’t need to create a local Unix account for each email
address. If you are going to set up a mail server for a company or organization, it’s
always better to have an easy way to create virtual mailboxes in a web-based
interface, which also allows users to change their passwords. That’s where
PostfixAdmin comes in.
PostfixAdmin Features
web interface 😉
Note
This tutorial works on Ubuntu 22.04, Ubuntu 20.04, and Ubuntu 18.04.
This tutorial uses MariaDB/MySQL database server.
Once you finish part 3, you can no longer use local Unix accounts as email addresses.
You must create email addresses from the PostfixAdmin web interface.
Prerequisites
It’s required that you have followed part 1 and part 2 of this tutorial series before
continuing to read this article.
Once the above requirements are met, let’s install and configure PostfixAdmin.
Hint: If you prefer to use MySQL, you can install it with: sudo apt install mysql-
server-8.0.
After it’s installed, MariaDB server should be automatically started. Use systemctl to
check its status.
Output:
sudo mysql_secure_installation
When it asks you to enter MariaDB root password, press Enter key as the root
password isn’t set yet. Then enter y to set the root password for MariaDB server.
Next, you can press Enter to answer all remaining questions, which will remove
anonymous user, disable remote root login and remove test database. This step is a
basic requirement for MariaDB database security. (Notice that Y is capitalized, which
means it is the default answer. )
Step 2: Download PostfixAdmin on Ubuntu Server
It can create problems when you upgrade the Ubuntu system to a new version,
resulting in upgrade failure.
If you use Nginx, the postfixadmin package might automatically install Apache on
your system.
If you use MySQL, this package might remove MySQL from your system.
The default postfixadmin package has a login loop issue from time to time. You will
also sometimes encounter the Invalid token! (CSRF check failed) error.
wget https://github.com/postfixadmin/postfixadmin/archive/postfixadmin-3.3.11.tar.gz
Once downloaded, extract the archive to the /var/www/ directory and rename it to
postfixadmin.
PostfixAdmin requires a templates_c directory, and the web server needs read and
write access to this directory, so run the following commands.
Starting with Dovecot 2.3.11, the web server user needs permission to read Let’s
Encrypt TLS certificate in order to do password hashing. Run the following two
commands to grant permissions.
Once you are logged in, create a database for PostfixAdmin using the following
command. I named it postfixadmin, but you can use whatever name you like. (Don’t
leave out the semicolon.)
Flush the privileges table for the changes to take effect and then get out of MariaDB
shell.
flush privileges;
exit;
Add the following lines in the file, so PostfixAdmin can connect to MySQL/MariaDB
database. Replace postfixadmin_password with the real PostfixAdmin password
created in step 4.
<?php
$CONF['configured'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_port'] = '3306';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'postfixadmin_password';
$CONF['database_name'] = 'postfixadmin';
$CONF['encrypt'] = 'dovecot:ARGON2I';
$CONF['dovecotpw'] = "/usr/bin/doveadm pw -r 5";
if(@file_exists('/usr/bin/doveadm')) { // @ to silence openbase_dir stuff; see
https://github.com/postfixadmin/postfixadmin/issues/171
$CONF['dovecotpw'] = "/usr/bin/doveadm pw -r 5"; # debian
}
Save and close the file. Note that we will use the ARGON2I password scheme. By
default, PostfixAdmin and Dovecot use MD5-CRYPT, which is a weak password
scheme. You can list available password schemes in Dovecot with the following
command.
sudo doveadm pw -l
Sample output:
SHA1 SSHA512 BLF-CRYPT PLAIN HMAC-MD5 OTP SHA512 SHA RPA DES-CRYPT
CRYPT SSHA MD5-CRYPT SKEY PLAIN-MD4 PLAIN-MD5 SCRAM-SHA-1
LANMAN SHA512-CRYPT CLEAR CLEARTEXT ARGON2I ARGON2ID SSHA256
NTLM MD5 PBKDF2 SHA256 CRAM-MD5 PLAIN-TRUNC SHA256-CRYPT SMD5
DIGEST-MD5 LDAP-MD5
If you are using Ubuntu 22.04/20.4, you already have Dovecot 2.3. If you use Ubuntu
18.04, you need to install Dovecot 2.3 from the official upstream repository, so you
will be able to use ARGON2I password scheme.
Save and close the file. Because this repository is using https, so we need to install
the apt-transport-https package.
Then we need to import the Dovecot PGP key with the following two commands, so
that packages downloaded from this repository can be verified.
If you see a question like below in the upgrade process, it’s always a good idea to
keep the local version and examine what needs to change later.
Once the upgrade is finished, check Dovecot version again.
dovecot --version
Output:
2.3.9.2 (cf2918cac)
Nginx
If you use Nginx web server, create a virtual host for PostfixAdmin.
Put the following text into the file. Replace postfixadmin.example.com with your real
domain name and don’t forget to set DNS A record for it.
server {
listen 80;
listen [::]:80;
server_name postfixadmin.example.com;
root /var/www/postfixadmin/public/;
index index.php index.html;
access_log /var/log/nginx/postfixadmin_access.log;
error_log /var/log/nginx/postfixadmin_error.log;
location / {
try_files $uri $uri/ /index.php;
}
location ~ ^/(.+\.php)$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
The above configuration uses php8.1-fpm, which is the default for Ubuntu 22.04.
If you use Ubuntu 20.04, replace php8.1-fpm with php7.4-fpm.
If you use Ubuntu 18.04, replace php8.1-fpm with php7.2-fpm.
sudo nginx -t
If the test is successful, reload Nginx for the changes to take effect.
Now you should be able to see the PostfixAdmin web-based install wizard at
http://postfixadmin.example.com/setup.php.
Ubuntu 22.04
To encrypt the HTTP traffic, we can enable HTTPS by installing a free TLS certificate
issued from Let’s Encrypt. Run the following command to install Let’s Encrypt client
(certbot) on Ubuntu server.
sudo apt install certbot
If you use Nginx, then you also need to install the Certbot Nginx plugin.
Next, run the following command to obtain and install TLS certificate.
Where
The certificate should now be obtained and automatically installed, which is indicated
by a message.
PostfixAdmin needs to read Dovecot statistics. Edit the Dovecot configuration file.
service stats {
unix_listener stats-reader {
user = www-data
group = www-data
mode = 0660
}
unix_listener stats-writer {
user = www-data
group = www-data
mode = 0660
}
}
Save and close the file. Then add the web server to the dovecot group.
sudo gpasswd -a www-data dovecot
Restart Dovecot.
After creating the password hash, PostfixAdmin will display a line like below.
$CONF['setup_password'] =
'$2y$10$58fIawuOb5y538RMBol/DOoqv2bJ7zhPRzRO.4Xq7MLeQJHmaFwF2';
Add the line displayed on PostfixAdmin setup page to the end of the file like below.
After saving the file, you need to refresh the PostfixAdmin setup page and enter the
setup password again, then create the admin account. Please don’t use a Gmail,
Yahoo Mail, or Microsoft email address for the admin account, or you might not be
able to log in later. Use an email address on your own domain. You can create the
email address later in PostfixAdmin.
If you encounter the following error when trying to create a superadmin account,
or
can’t encrypt password with dovecotpw, see error log for details
It’s because the www-data user doesn’t have permission to read Let’s Encrypt TLS
certificate. To fix it, run the following command to grant permissions.
Sometimes, you might also need to run the following command to fix this error.
sudo setfacl -R -m u:www-data:rwx /var/run/dovecot/stats-reader /var/run/dovecot/stats-
writer
Once the superadmin account is created, you can log into PostfixAdmin at
postfixadmin.example.com/login.php.
The PostfixAdmin setup process populates the postfixadmin database with some
default tables. It’s helpful for us to know the names and structure of the tables. Log
in to MySQL/MariaDB console.
USE postfixadmin;
SHOW TABLES;
Output:
+------------------------+
| Tables_in_postfixadmin |
+------------------------+
| admin |
| alias |
| alias_domain |
| config |
| domain |
| domain_admins |
| fetchmail |
| log |
| mailbox |
| quota |
| quota2 |
| vacation |
| vacation_notification |
+------------------------+
13 rows in set (0.001 sec)
domain: contains information on the domains that are using your mail server to send
and receive email.
mailbox: contains information on every email address, including hashed password and
the location of mail files.
alias: contains the alias of each email address.
If you are interested, you can check what columns each table contains. For example,
the following command will show us the columns in the domain table.
DESCRIBE domain;
Output:
+-------------+--------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------------------+-------+
| domain | varchar(255) | NO | PRI | NULL | |
| description | varchar(255) | NO | | NULL | |
| aliases | int(10) | NO | | 0 | |
| mailboxes | int(10) | NO | | 0 | |
| maxquota | bigint(20) | NO | | 0 | |
| quota | bigint(20) | NO | | 0 | |
| transport | varchar(255) | NO | | NULL | |
| backupmx | tinyint(1) | NO | | 0 | |
| created | datetime | NO | | 2000-01-01 00:00:00 | |
| modified | datetime | NO | | 2000-01-01 00:00:00 | |
| active | tinyint(1) | NO | | 1 | |
+-------------+--------------+------+-----+---------------------+-------+
EXIT;
First, we need to add MySQL map support for Postfix by installing the postfix-mysql
package.
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf
virtual_mailbox_maps =
proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf,
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
virtual_alias_maps =
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf,
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf,
proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
Where:
virtual_mailbox_domains points to a file that will tell Postfix how to look up domain
information from the database.
virtual_mailbox_maps points to files that will tell Postfix how to look up email
addresses from the database.
virtual_alias_maps points to files that will tell Postfix how to look up aliases from the
database.
We want to use dovecot to deliver incoming emails to the virtual users’ message
store, so also add the following line at the end of this file.
virtual_transport = lmtp:unix:private/dovecot-lmtp
Save and close the file. Next, we need to create the .cf files one by one. Create the sql
directory.
Add the following content. Replace password with the postfixadmin password you
set in Step 2.
user = postfixadmin
password = password
hosts = localhost
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND
active = '1'
#expansion_limit = 100
user = postfixadmin
password = password
hosts = localhost
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
#expansion_limit = 100
user = postfixadmin
password = password
hosts = localhost
dbname = postfixadmin
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain
= '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND
mailbox.active = 1 AND alias_domain.active='1'
user = postfixadmin
password = password
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#expansion_limit = 100
user = postfixadmin
password = password
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d'
and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1
AND alias_domain.active='1'
Next, we need to change the value of the mydestination parameter in Postfix. Display
the current value:
postconf mydestination
Sample output:
The mydestination parameter contains a list of domain names that will receive emails
delivered to local Unix accounts. In part 1, we added the apex domain name (like
example.com) to mydestination. Since we are going to use virtual mailbox, we need
to remove the apex domain name from the list by issuing the following command.
virtual_mailbox_base = /var/vmail
virtual_minimum_uid = 2000
virtual_uid_maps = static:2000
virtual_gid_maps = static:2000
The first line defines the base location of mail files. The remaining 3 lines define
which user ID and group ID Postfix will use when delivering incoming emails to the
mailbox. We use the user ID 2000 and group ID 2000.
Save and close the file. Restart Postfix for the changes to take effect.
Next, we need to create a user named vmail with ID 2000 and a group with ID 2000.
We also need to configure the Dovecot IMAP server to query user information from
the database. First, run the following command to add MySQL support for Dovecot.
In part 2, we used the following mail_location. Email messages are stored under the
Maildir directory under each user’s home directory.
mail_location = maildir:~/Maildir
Since we are using virtual mailbox domain now, we need to enable mail_home for
the virtual users by adding the following line in the file, because virtual users don’t
have home directories by default.
mail_home = /var/vmail/%d/%n/
Save and close the file. Then edit the 10-auth.conf file.
auth_username_format = %n
The %n would drop the domain if it was given. Because in part 2 we were using local
Unix account for the username of every email address, we must use %n to drop the
domain, so users were able to login with the full email address.
Now we are using virtual mailbox domains, which means the username of every
email address includes the domain part, so we need to change the
auth_username_format as follows. %u won’t drop away the domain. This allows users
to login with the full email address.
auth_username_format = %u
#auth_default_realm =
Change it to
auth_default_realm = example.com
This is to ensure users who didn’t enter the @example.com part in the username field
can still log in. Dovecot will append the @example.com part if it’s not given by users.
Next, uncomment the following line at the end of this file, so Dovecot can query user
information from MySQL/MariaDB database.
!include auth-sql.conf.ext
Now you probably don’t want local Unix users to send emails without registering
email addresses in PostfixAdmin, then comment out the following line by adding the
# character at the beginning, so Dovecot won’t query the local /etc/passwd or
/etc/shadow file.
#!include auth-system.conf.ext
It can be helpful to add the following two lines in this file to debug login issues. The
login errors would be logged into /var/log/mail.log file. (Once users can login
without problems, you can comment out the following two lines.)
auth_debug = yes
auth_debug_passwords = yes
Save and close the file.
Here is the content that you should have in this file. By default, all lines in this file are
commented out, so you can simply copy and paste them at the bottom. Replace
password with the postfixadmin password you set in Step 2.
driver = mysql
default_pass_scheme = ARGON2I
user_query = SELECT maildir, 2000 AS uid, 2000 AS gid FROM mailbox WHERE
username = '%u' AND active='1'
Restart Dovecot.
When a user tries to log in, Dovecot would use the Argon2 algorithm to generate a
password hash from the password entered by the user, then compare it with the
password hash stored in the database.
Then click Virtual List tab and select Add Mailbox to add a new email address for
your domain.
Next, you can open your desktop email client such as Mozilla Thunderbird and add a
mail account.
In the incoming server section, select IMAP protocol, enter mail.your-domain.com as
the server name, choose port 143 and STARTTLS. Choose normal password as the
authentication method.
In the outgoing section, select SMTP protocol, enter mail.your-domain.com as the
server name, choose port 587 and STARTTLS. Choose normal password as the
authentication method.
Hint 1: You can also use port 993 with SSL/TLS encryption for IMAP, and use port
465 with SSL/TLS encryption for SMTP. You should not use port 25 as the SMTP port
in mail clients to submit outgoing emails.
Hint 2: If you use Microsoft 365 Outlook email client, then you shouldn’t enable
Secure Password Authentication (SPA), which is a proprietary Microsoft protocol.
Your password is already encrypted by TLS.
You should now be able to connect to your own email server and also send and
receive emails with your desktop email client!
Note that you cannot use local Unix accounts to login now. You must log in with the
virtual user created from PostfixAdmin web interface.