Set Up a Mail Server with PostfixAdmin

setup and configure a mail server with postfixadmin

postfixadminIn this article, we will show you how to set up and configure a mail server with Postfix, Dovecot, Spamassassin, SQLite and PostfixAdmin on an Ubuntu 16.04 VPS with Nginx and PHP 7.0. This guide should work on other Linux VPS systems as well but was tested and written for an Ubuntu 16.04 VPS. To set up a mail server with PostfixAdmin, just follow the steps below.

1. Login to your VPS via SSH

ssh my_sudo_user@my_server

2. Update the system and install necessary packages

sudo apt-get update && sudo apt-get -y upgrade
sudo apt-get -y install wget nano dbconfig-common sqlite3

3. Create a system user

For security reasons, we will create a new system user who will be the owner of all mailboxes.

sudo useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual Mail User" vmail
sudo mkdir -p /var/vmail
sudo chmod -R 770 /var/vmail
sudo chown -R vmail:mail /var/vmail

4. Install PHP 7.0 and all required PHP modules

If you don’t have PHP installed on your server you can install the latest stable version of PHP 7.0 and all necessary modules, with the following command:

sudo apt-get -y install php-fpm php-cli php7.0-mbstring php7.0-imap php7.0-sqlite3

5. Install and configure Nginx

If you don’t have a web server installed on your machine, install Nginx from the official Ubuntu repositories:

sudo apt-get -y install nginx

Create a new Nginx server block with the following content:

sudo nano /etc/nginx/sites-available/postfixadmin.your_domain.com
server {
  listen 80;
  server_name postfixadmin.your_domain.com;
  return 301 https://$server_name$request_uri;
}

server {
   listen          443 ssl;
   server_name     postfixadmin.your_domain.com;
   root            /var/www/postfixadmin-3.0;
   index           index.php;
   charset         utf-8;

   ssl_certificate           /etc/ssl/certs/ssl-cert-snakeoil.pem;
   ssl_certificate_key       /etc/ssl/private/ssl-cert-snakeoil.key;
   ssl_protocols             TLSv1.2;
   ssl_ciphers               "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4";
   ssl_prefer_server_ciphers on;
   ssl_session_cache         shared:SSL:10m;
   ssl_session_timeout       10m;
   ssl_ecdh_curve            secp521r1;

   location / {
      try_files $uri $uri/ index.php;
   }

   location ~* \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include       fastcgi_params;
        fastcgi_pass  unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
   }
}

Activate the server block by creating a symbolic link:

sudo ln -s /etc/nginx/sites-available/postfixadmin.your_domain.com /etc/nginx/sites-enabled/postfixadmin.your_domain.com

Test the Nginx configuration and restart nginx:

sudo nginx -t
sudo service nginx restart

6. PostfixAdmin

PostfixAdmin is a PHP-based web frontend that allows you to manage the database that postfix uses for virtual domains and users. The latest version of PostfixAdmin, version 3, supports MySQL PostgreSQL and SQLite databases. In this guide, we will use the latter.
Download the PostfixAdmin archive from SourceForge and extract it in the /var/www/ directory:

wget -q -O - "http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.0/postfixadmin-3.0.tar.gz" | sudo tar -xzf - -C /var/www

Open the mail configuration file and edit the following values:

sudo nano /var/www/postfixadmin-3.0/config.inc.php
$CONF['configured'] = true;
$CONF['database_type'] = 'sqlite';
$CONF['database_name'] = '/var/vmail/postfixadmin.db';
// $CONF['database_host'] = 'localhost';
// $CONF['database_user'] = 'postfix';
// $CONF['database_password'] = 'postfixadmin';
// $CONF['database_name'] = 'postfix';

$CONF['domain_path'] = 'NO';
$CONF['domain_in_mailbox'] = 'YES';
sudo chown -R www-data: /var/www/postfixadmin-3.0

Create the SQLite database:

sudo touch /var/vmail/postfixadmin.db
sudo chown vmail:mail /var/vmail/postfixadmin.db
sudo usermod -a -G mail www-data

To populate the database go to https://postfixadmin.your_domain.com/setup.php and you should see something like below:
Testing database connection - OK - sqlite://:xxxxx@//var/vmail/postfixadmin.db

Create a new admin user:

bash /var/www/postfixadmin-3.0/scripts/postfixadmin-cli admin add admin@your_domain.com --password strong_password --password2 strong_password --superadmin 1 --active 1

7. Install and configure postfix

Install postfix with the command below:

sudo apt-get install postfix

Create the following files:

 sudo nano /etc/postfix/sqlite_virtual_alias_maps.cf
dbpath = /var/vmail/postfixadmin.db
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
 sudo nano /etc/postfix/sqlite_virtual_alias_domain_maps.cf
dbpath = /var/vmail/postfixadmin.db
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = printf('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
 sudo nano /etc/postfix/sqlite_virtual_alias_domain_catchall_maps.cf
dbpath = /var/vmail/postfixadmin.db
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = printf('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
 sudo nano /etc/postfix/sqlite_virtual_domains_maps.cf
dbpath = /var/vmail/postfixadmin.db
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
 sudo nano /etc/postfix/sqlite_virtual_mailbox_maps.cf
dbpath = /var/vmail/postfixadmin.db
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
 sudo nano /etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf
dbpath = /var/vmail/postfixadmin.db
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = printf('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'

Edit the main.cf file:

postconf -e "myhostname = $(hostname -A)"
 
postconf -e "virtual_mailbox_domains = sqlite:/etc/postfix/sqlite_virtual_domains_maps.cf"
postconf -e "virtual_alias_maps =  sqlite:/etc/postfix/sqlite_virtual_alias_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_catchall_maps.cf"
postconf -e "virtual_mailbox_maps = sqlite:/etc/postfix/sqlite_virtual_mailbox_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf"
 
postconf -e "smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem"
postconf -e "smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key"
postconf -e "smtpd_use_tls = yes"
postconf -e "smtpd_tls_auth_only = yes"
 
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"
 
postconf -e "mydestination = localhost"
postconf -e "mynetworks = 127.0.0.0/8"
postconf -e "inet_protocols = ipv4"
 
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"

Open the master.cf file, find submission inet n and smtps inet n sections and edit as follows:

sudo nano /etc/postfix/master.cf
smtp      inet  n       -       y       -       -       smtpd
#smtp      inet  n       -       y       -       1       postscreen
#smtpd     pass  -       -       y       -       -       smtpd
#dnsblog   unix  -       -       y       -       0       dnsblog
#tlsproxy  unix  -       -       y       -       0       tlsproxy
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
#  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Enable and restart the postfix service

systemctl enable postfix
systemctl restart postfix

8. Install and Configure Dovecot

Install dovecot with sqlite support using the command below:

sudo apt-get install dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-sqlite

Open the /etc/dovecot/conf.d/10-mail.conf file and change the following values:

mail_location = maildir:/var/vmail/%d/%n
mail_privileged_group = mail
mail_uid = vmail
mail_gid = mail
first_valid_uid = 150
last_valid_uid = 150

Open the /etc/dovecot/conf.d/10-auth.conf file and change the following values:

auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Create a new dovecot-sql.conf.ext file:

sudo nano /etc/dovecot/dovecot-sql.conf.ext
driver = sqlite
connect = /var/vmail/postfixadmin.db
default_pass_scheme = MD5-CRYPT
password_query = \
  SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, \
  'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid \
  FROM mailbox WHERE username = '%u' AND active = '1'
user_query = \
  SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' as mail, \
  150 AS uid, 8 AS gid, printf('dirsize:storage=', quota) AS quota \
  FROM mailbox WHERE username = '%u' AND active = '1'

In the /etc/dovecot/conf.d/10-ssl.conf file enable SSL support:

ssl = yes

.

Open the /etc/dovecot/conf.d/15-lda.conf file and set the postmaster_address email address.

postmaster_address = postmaster@vps.your_domain.com

Open the /etc/dovecot/conf.d/10-master.conf file, find the service lmtp section and change it to:

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

find the service auth section and change it to:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
    #group = vmail
  }
  user = dovecot
}

Change the service auth-worker section to the following:

service auth-worker {
  user = vmail
}

Set the permissions:

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

Enable and restart the dovecot service

Need a fast and easy fix?
✔ Unlimited Managed Support
✔ Supports Your Software
✔ 2 CPU Cores
✔ 2 GB RAM
✔ 50 GB PCIe4 NVMe Disk
✔ 1854 GeekBench Score
✔ Unmetered Data Transfer
NVME 2 VPS

Now just $43 .99
/mo

GET YOUR VPS
systemctl enable dovecot 
systemctl restart dovecot 

9. SpamAssassin

SpamAssassin is an open source tool written in Perl which helps filter out unwanted messages. If you want to enable and configure SpamAssassin please continue with the following steps.
To install SpamAssassin, run:

sudo apt-get install spamassassin
sudo adduser spamd --disabled-login

Open the /etc/default/spamassassin file and make the following changes:

ENABLED=1
OPTIONS="--create-prefs --max-children 5 -d 127.0.0.1 --username spamd --helper-home-dir /home/spamd/ -s /home/spamd/spamd.log"
PIDFILE="/home/spamd/spamd.pid"
CRON=1

To integrate SpamAssassin with Postfix, append the following at the end of the /etc/postfix/master.cf file:

smtp      inet  n       -       -       -       -       smtpd
    -o content_filter=spamassassin
 
spamassassin unix  -       n       n       -       -       pipe
   user=nobody argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Enable and restart the SpamAssassin service

systemctl enable spamassassin
systemctl restart spamassassin
systemctl restart postfix

If everything is set up correctly now you should be able to login to your PostfixAdmin back-end by going to https://postfixadmin.your_domain.com/ and create your first virtual domain and mailbox.


install postfixadminOf course, you don’t have to set up and configure a mail server with PostfixAdmin yourself if you use one of our Mail Server Hosting services, in which case you can simply ask our expert Linux admins to set up and configure a mail server with PostfixAdmin for you. They are available 24×7 and will take care of your request immediately.

PS. If you liked this post on how to install postfixadmin, please share it with your friends on the social networks using the buttons on the left or simply leave a reply below. Thanks.

19 thoughts on “Set Up a Mail Server with PostfixAdmin”

  1. Your guide is missing SSL certificate configuration:
    # nginx -t
    nginx: [emerg] BIO_new_file(“/etc/ssl/certs/ssl-cert-snakeoil.pem”) failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen(‘/etc/ssl/certs/ssl-cert-snakeoil.pem’,’r’) error:2006D080:BIO routines:BIO_new_file:no such file)
    nginx: configuration file /etc/nginx/nginx.conf test failed

    Reply
    • Hi,
      I have configured postfix with backend MySQL and postfixadmin, server relay is working fine with all multiple virtual domains.. now I have an requirement for particular domain , where split delivery needs to be enabled to our old postfix server.. so that we can migrate it here easily.. could you please help me the configurations?

      Reply
  2. Also your postfixadmin setttings won’t work. I don’t have a solution.

    Warning: config.local.php – NOT FOUND
    It’s Recommended to store your own settings in config.local.php instead of editing config.inc.php
    Create the file, and edit as appropriate (e.g. select database type etc)
    Depends on: SQLite – OK
    Error: Can’t connect to database
    Please edit the $CONF[‘database_*’] parameters in config.local.php.

    DEBUG INFORMATION
    Connect: given database path does not exist, is not writable, or $CONF[‘database_name’] is empty.

    Reply
  3. Hi, Thanks for the confirmation.
    The postfixadmin issue was solved by setting the /var/mail directory to 777. sqlite3 needs write permission to both the directory and the file.
    The SSL browser issues were solved by commenting out your ssl_ciphers in nginx site config. The restriction blocked Safari 11 and Chrome. Chrome and Safari blocked the SSL self-signed cert . Firefox was fine.

    Reply
  4. You enable SSL in dovecot but did not uncomment the certificates (snakeoil) nor did you create a certificate.

    You installed Postfix but omitted the site config from the post-install scripts. Setting this to “no configuration” will break your guide.

    Tested, and email does not work. Accounts cannot authenticate with Dovecot ( with/without SSL). No data is created in /var/vmail for any accounts.

    Tested on Debian 9.1

    Reply
  5. Now working with a few tweaks except rspamd

    Self-signed cert one liner:
    openssl req -x509 -newkey rsa:4096 -keyout webmail.example.com-key.pem -out webmail.example.com-cert.pem -days 36500 -nodes -sha256 -subj “/C=BE/ST=LUIK/O=example/CN=webmail.example.com”

    Reply
  6. Hi,

    On the first hand, thank you for your efforts helping us…

    I am having troubles at the step of testing sqlite conection:
    https://postfixadmin.your_domain.com/setup.php

    I repeat all previous steps, and I only get 502 bad getaway, and seeing the log nginx only report:
    connect() to unix:/run/php/php7.0-fpm.sock failed (2: No such file or directory)

    Could you help me?

    Best regards.

    Reply
    • The PHP-FPM socket your are using doesn’t exist on your server. Make sure you are using the correct path to your PHP-FPM socket in your Nginx configuration.

      Reply

Leave a Comment