Postfix is a free and widely used open-source mail transfer agent. It supports MySQL, PostgreSQL, and SQLite as the database server to store and manage the virtual domains.
PostfixAdmin is a free web-based interface to manage a postfix mail server. With this tool, we can easily add/remove/edit domain names, email accounts, email quotas, email forwarding, etc.
In this tutorial, we will show you how to set up a mail server with PostfixAdmin on Debian 11 (Bullseye) OS.
Table of Contents
Prerequisites
- Debian 11 VPS
- SSH root access or a regular system user with sudo privileges
- A Fully Qualified Domain Name
Step 1. Log in via SSH and update the system
Log in to your Debian 11 VPS through SSH as a root user or as a regular user with sudo privileges
$ ssh master@IP_Address -p Port_number
Remember to replace “master” with a user that has sudo privileges, or root. Additionally, replace “IP_Address” and “Port_Number” with your server’s IP address and SSH port.
You can check whether you have the proper Debian version installed on your server with the following command:
$ lsb_release -a
You should get this output:
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye
To update the system, you can run this command:
$ sudo apt update && sudo apt upgrade
Step 2. Set Hostname
You would need to create a DNS A record for your hostname because the server hostname should be an FQDN. For example, we will create debian11.yourdomain.com as the server hostname, let’s run this command:
$ sudo hostnamectl set-hostname debian11.yourdomain.com
The above command is just an example, you would need to use your own registered domain name to create a hostname.
Step 3. Install Apache, MariaDB, and PHP
Now, let’s install the webserver, database server, and PHP
$ sudo apt install apache2 mariadb-server php-{xml,pear,imap,intl,common,json,curl,mbstring,mysql,gd,imagick,zip,opcache,sqlite3} libapache2-mod-php
You can skip this step if these are already installed on your server.
Step 4. Create a System User
Let’s run the following commands to create a system user called ‘vmail’ and create a directory and give the proper permission.
$ 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
Step 4. Create a Database
If your MySQL root user does not have a password, you can run this command to log in to the MySQL shell.
$ sudo mysql
If a password is required to log in to MySQL shell, then run this command:
$ mysql -u root -p
Once logged in, let’s run the following commands:
MariaDB [(none)]> CREATE DATABASE postfixadmin; MariaDB [(none)]> GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixadmin'@'localhost' IDENTIFIED BY '5tr0n6p455w0rd'; MariaDB [(none)]> FLUSH PRIVILEGES; MariaDB [(none)]> \q
Step 5. Install Postfix
Install Postfix mail server with this command:
$ sudo apt install postfix-mysql
Once executes, you will see the following
Choose Internet Site then hit Ok to continue
In this step, you will be asked for the system mail name, make sure the system mail name is the same as your Debian 11 hostname. We set the system hostname at the beginning of this tutorial.
Once completed we need to create several configuration files for Postfix to communicate with the database.
$ sudo mkdir -p /etc/postfix/sql
Let’s create the files, make sure to replace the password, database name, database user with the ones you created earlier.
$ sudo nano /etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfixadmin password = 5tr0n6p455w0rd hosts = localhost dbname = postfixadmin query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
$ sudo nano /etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
hosts = localhost
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
$ sudo nano /etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
hosts = localhost
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
$ sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
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'
$ sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
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'
$ sudo nano /etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
hosts = localhost
dbname = postfixadmin
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
$ sudo nano /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
user = postfixadmin
password = 5tr0n6p455w0rd
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
Let us now proceed with editing /etc/postfix/main.cf
file, we can run the following commands:
$ sudo postconf -e "myhostname = $(hostname -f)" $ sudo postconf -e "mydestination = localhost" $ sudo postconf -e "mynetworks = 127.0.0.0/8" $ sudo postconf -e "inet_protocols = ipv4" $ sudo postconf -e "inet_interfaces = all" $ sudo postconf -e "smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem" $ sudo postconf -e "smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key" $ sudo postconf -e "smtpd_use_tls = yes" $ sudo postconf -e "smtpd_tls_auth_only = yes" $ sudo postconf -e "smtpd_sasl_type = dovecot" $ sudo postconf -e "smtpd_sasl_path = private/auth" $ sudo postconf -e "smtpd_sasl_auth_enable = yes" $ sudo postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination" $ sudo postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp" $ sudo postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf" $ sudo postconf -e "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" $ sudo postconf -e "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"
Once completed, we can continue and edit /etc/postfix/master.cf
file:
$ sudo nano /etc/postfix/master.cf
Modify or add the following lines to the file.
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=$mua_client_restrictions # -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 smtpd_client_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_client_restrictions=$mua_client_restrictions # -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
Save the changes then exit.
Step 6. Install Dovecot
$ sudo apt install dovecot-mysql dovecot-imapd dovecot-pop3d dovecot-lmtpd
Once dovecot is installed, we need to edit some configuration files.
Open the /etc/dovecot/conf.d/10-auth.conf
file
$ sudo nano /etc/dovecot/conf.d/10-auth.conf
Then find this line
auth_mechanisms = plain
replace it with this line:
auth_mechanisms = plain login
Then, comment !include auth-system.conf.ext and uncomment #!include auth-sql.conf.ext
It should look like this:
#!include auth-system.conf.ext
!include auth-sql.conf.ext
In the 10-auth.conf file, we include auth-sql.conf.ext. So, let’s edit the file
$ sudo nano /etc/dovecot/dovecot-sql.conf.ext
then append these lines:
driver = mysql
connect = host=localhost dbname=postfixadmin user=postfixadmin password=5tr0n6p455w0rd
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/%u' as home, 'maildir:/var/vmail/%d/%u' as mail, 150 AS uid, 8 AS gid, concat('dirsize:storage=', quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'
The lines above contain the database credentials, make sure they match the ones you created in the previous step.
Save the file and exit
Next, open the /etc/dovecot/conf.d/10-mail.conf
file and modify the following values:
$ sudo nano /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = mail
mail_privileged_group = mail
first_valid_uid = 150
last_valid_uid = 150
By default, dovecot SSL support in Debian 11 is enabled. You can verify it by checking the file /etc/dovecot/conf.d/10-ssl.conf
, make sure it has this line:
ssl = yes
If you want to edit the postmaster email address, you can edit the file /etc/dovecot/conf.d/15-lda.conf and find the postmaster_address line. By default, the postmaster email address would be postmaster@yourdomain.com. So, if you want to receive the postmaster email at admin@yourdomain.com, then you need to add this line:
postmaster_address = admin@yourdomain.com
Now, let’s proceed with editing other dovecot configuration files.
$ sudo nano /etc/dovecot/conf.d/10-master.conf
There are several changes you need to make to this file.
- Find the service lmtp section and change it to the following:
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 } user = dovecot }
- Change the service auth-worker section to the following:
service auth-worker { user = vmail }
Do not forget to save the file then exit
Before restarting Dovecot, we need to change the permissions.
$ sudo chown -R vmail:dovecot /etc/dovecot $ sudo chmod -R o-rwx /etc/dovecot $ sudo systemctl restart postfix dovecot
Step 7. Install PostfixAdmin
In this final step, we will download PostfixAdmin from Github and store it in the /opt directory.
$ sudo apt install git $ cd /opt $ sudo git clone https://github.com/postfixadmin/postfixadmin.git $ cd /opt/postfixadmin $ sudo -u bash install.sh $ sudo chown -R www-data. /opt/postfixadmin
We are not going to use a subdomain to access PostfixAdmin through a web browser, we will use an Apache alias instead.
$ sudo nano /etc/apache2/conf-enabled/postfixadmin.conf
Paste the following into the file then reload apache.
Alias /postfixadmin /opt/postfixadmin/public <Directory "/opt/postfixadmin/public"> AllowOverride All Options +FollowSymLinks Require all granted </Directory>
$ sudo systemctl reload apache2
Create config.local.php and insert the following lines
$ sudo nano /opt/postfixadmin/config.local.php
<?php $CONF['database_type'] = 'mysqli'; $CONF['database_host'] = 'localhost'; $CONF['database_user'] = 'postfixadmin'; $CONF['database_password'] = '5tr0n6p455w0rd'; $CONF['database_name'] = 'postfixadmin'; $CONF['configured'] = true; ?>
Go to http://YOUR_SERVER_IP_ADDRESS/postfixadmin/setup.php
and create a setup password. If you already have a website on your server, you can also access postfixadmin at http://yourdomain.com/postfixadmin/setup.php
Type your setup password twice and click on the ‘Generate setup_password hash’ button.
You will see a line containing a setup password like this:
$CONF['setup_password'] = '$2y$10$xlKkztMcpu6C3//ZqPZM1.pTGjGD5oEn0KtBlbSl9VFDycxPNH1M2';
and you need to copy it to config.local.php
<?php $CONF['database_type'] = 'mysqli'; $CONF['database_host'] = 'localhost'; $CONF['database_user'] = 'postfixadmin'; $CONF['database_password'] = '5tr0n6p455w0rd'; $CONF['database_name'] = 'postfixadmin'; $CONF['configured'] = true; $CONF['setup_password'] = '$2y$10$xlKkztMcpu6C3//ZqPZM1.pTGjGD5oEn0KtBlbSl9VFDycxPNH1M2'; ?>
After adding the line to config.local.php file, you can refresh the page to log in and create a superadmin.
The setup password you created earlier is required to create a superadmin. In the admin field, it should be filled with an email address, it should look like this:
That’s it, after successfully adding a superadmin, you can use the credentials to log in to http://
to add domains, email accounts, and any other email management tasks there.YOUR_SERVER_IP_ADDRESS
/postfixadmin/login.php
Of course, you don’t have to set up a mail server with PostfixAdmin on Debian 11 if you use one of our Debian 11 VPS hosting services, in which case you can simply ask our expert Linux admins to set up a mail server with PostfixAdmin for you. They are available 24×7 and will take care of your request immediately. Setting up a mail server with PostfixAdmin is an easy task if you followed this guide carefully.
PS. If you liked this post, on how to set up a mail server with PostfixAdmin, please share it with your friends on the social networks using the buttons on the left or simply leave a reply below. Thanks.
Many thanks for this tutorial. It has been very helpful for me.
I was able to configure emails withou GUI. PostfixAdmin usage is very easy now for me :).
It would be helpful to add spamassassin and sieve configuration parts. Maybe it is available in another tutorial.
There are some missing parts in the tutorial.
You’ll have to solve Postfix permissions issues, otherwise you won’t be able to start the mail server:
Apr 20 16:26:43 mail postfix/master[31863]: fatal: open lock file /var/spool/postfix/var/lib//master.lock: cannot create file exclusively: No such file or directory
Apr 20 16:26:45 mail postfix/postfix-script[31872]: fatal: mail system startup failed
Apr 20 16:26:50 mail postfix/postfix-script[31985]: warning: unable to create missing queue directories
Apr 20 16:26:50 mail postfix/postfix-script[32005]: warning: symlink leaves directory: /etc/postfix/./makedefs.out
Apr 20 16:26:50 mail postfix/postfix-script[32017]: warning: not set-gid or not owner+group+world executable: /usr/sbin/postqueue
Apr 20 16:26:50 mail postfix/postfix-script[32018]: warning: not set-gid or not owner+group+world executable: /usr/sbin/postdrop
Apr 20 16:26:50 mail postfix/postfix-script[32043]: starting the Postfix mail system
Apr 20 16:26:50 mail postfix/master[32045]: fatal: open lock file /var/spool/postfix/var/lib//master.lock: cannot create file exclusively: No such file or directory
Apr 20 16:26:52 mail postfix/postfix-script[32054]: fatal: mail system startup failed
You can try to remove the master.lock file then starts Postfix. The .lock files are needed to ensure that there is only one Postfix “master” process active. If Postfix shuts down cleanly the .lock files will be deleted. If Postfix does not shutdown cleanly some of the .lock files will be left over which causes issues when starting Postfix.
Awesome tutorial. This worked the first time I tried it and it was well documented and explained. Saved me a ton of time. Thanks much!!!
This works great, but now my imap clients cant seem to authenticate, the mail.log I get this error “imap-login: Disconnected (auth failed, 1 attempts in 2 secs)” along with users, method and ips.. I excluded them for security. I am trying to use roundcube as my mail client.
Hi Steve — the error message indicates that your login credentials are incorret. Please double-check that the correct email/password is used to connect.
All good but the only issue is that I cannot authenticate to any account after completing the setup. I have tried to use Thunderbird, got auth failed error message on the client and on the server logs; then installed some webmail tools into my Debian, exactly same results.
Finally, I thought that somehow postfixadmin is inserting the wrong MD5-CRYPT hash into the MySQL table. To be able to generate the correct hash, back to the Dovecot page, look at documents and finally find it:
$ doveadm pw -s MD5-CRYPT -p ‘yourpassword’
when you type the above command with your password, it generates the correct MD5-CRYPT hash, then just copy and paste it into the Mysql Table, related user row in there…
SQL commands on command line or PHPMyAdmin web interface, up to you ;)
now, it’s working properly on IMAP auth but still, I have another issue on SMTP auth :)
I can get new messages into my Thunderbird but cannot send them yet.
You need to check if the SMTP ports are open on your server or on your network firewall. You should also check the mail log for more information.
Thank you for your attention, Sir,
It was an issue due to late hours and lost my focus on details after spending time on the wrong MD5 hash in the MySQL table.
SMTP issue was because of the wrong Thunderbird settings, (I changed the setting to try different auth options during the auth issue, then forget those setting on Thunderbird) it’s working properly now.
Also install SquirrelMail for web interface testing purpose, all fine.
Hello,
We have a problem : Where we put the command : “echo test | sendmail test@exemple.org” we have a “Error: net_connect_unix(/run/dovecot/stats-writer) failed: Permission den))”.
Do you have a idea of the problem ?
Try to add this to your /etc/dovecot/dovecot.conf.
service stats {
unix_listener stats-reader {
user = vmail
group = vmail
mode = 0660
}
unix_listener stats-writer {
user = vmail
group = vmail
mode = 0660
}
}
Then restart dovecot.
Thanks man !
And I have a question, maybe you have a idea :
Every authentification failed with gmail when I add my mail. (mail dovecot: imap-login: Disconnected (auth failed, 1 attempts in 11 secs)
It says : “Login or password failed” while my login and password was good.
Do you have a idea of the problem ?
Thanks again.
A great resource that worked perfectly.
Thanks so much!
There is a problem with connecting a mailbox in Mozilla Thunderbird and Roundcube, “Login or password error”. The password and login are correct. Mozilla Thunderbird finds all connection settings correctly, Roundcube does the same, but for some reason login password authentication does not work. Help me figure it out. The instruction itself is working, except for the problems described above.
Please check the server logs to make sure that the connection is reaching the server and see what is the error message in the logs.
How exactly to do this? Where to watch?