Introduction
Since my Raspberry Pi already has Postfix + Dovecot installed and configured via a DB connection, there is a need to administer mailboxes. For the convenience of administration, it is implemented through the web interface by the PostfixAdmin service. How to install and configure this service, I will describe step by step in this post.
Requirements for PostfixAdmin
To install PostfixAdmin, I don’t need to install anything additionally, because many services were installed at the previous stage – when installing Postfix and Zabbix. However, it will not be superfluous to check already existing packages and dependencies. For the rest of this article, I will assume that we already have all dependencies installed and configured, namely:
- PHP – php php-mbstring php-intl php-imap php-curl php-mysql php-xml php-sqlite3
- Apache – apache2
- MariaDB – mariadb-client mariadb-server
- Related packages – unzip git composer
Before starting, as always, you need to update the packages:
sudo apt update && sudo apt upgrade
After checking and installing the necessary dependencies, proceed to the installation of PostfixAdmin
Installing PostfixAdmin
PostfixAdmin is downloaded via the git repository.
cd /var/www/html
sudo git clone https://github.com/postfixadmin/postfixadmin.git
sudo chown -R www-data:www-data postfixadmin
cd postfixadmin
To streamline the installation process, you can run the install.sh file, which will install composer, the PHP libraries, and the templates_c directory. This will save you from making mistakes in the future.
chmod +x install.sh
./install.sh
After installation, you can go to the database.
Creating a database for PostfixAdmin
To do this, you need to connect to an already existing or newly created database:
sudo mysql -u root -p<password>
Creating a database and a user, and providing access for this user to interact with the database:
CREATE DATABASE postfixadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'postfixuser'@'localhost' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;
After the database and the user are defined, proceed to the PostfixAdmin configuration settings
Editing the configuration
The main files are already in the directory at: /var/www/html/postfixadmin. In this directory, instead of editing the main config.inc.php file, you need to create a config.local.php file and write the main configuration parameters there. This configuration file will not be overwritten or corrupted in future updates.
sudo nano config.local.php
In it, we change or add the following lines:
$CONF['configured'] = true;
$CONF['default_language'] = 'en';
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixuser';
$CONF['database_password'] = '<Password>';
$CONF['database_name'] = 'postfixadmin';
$CONF['encrypt'] = 'dovecot:SHA512-CRYPT';
Creating an Apache virtual host
Since Apache can have many virtual hosts, you need to create another one for PostfixAdmin.
sudo nano /etc/apache2/sites-available/postfixadmin.conf
With the following parameters:
<VirtualHost *:80>
ServerAdmin admin@localhost
DocumentRoot /var/www/html/postfixadmin/public
ServerName postfixadmin.local
<Directory /var/www/postfixadmin/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/postfixadmin_error.log
CustomLog ${APACHE_LOG_DIR}/postfixadmin_access.log combined
</VirtualHost>
But if you want PostfixAdmin to be accessible only from your local network, replace the <Directory> block with your subnet with the following:
<Directory /var/www/html/postfixadmin>
Require ip 127.0.0.1
Require ip 192.168.0.0/24
</Directory>
In order for the changes to take effect, you need to activate the site:
sudo a2ensite postfixadmin.conf
sudo a2enmod rewrite
sudo systemctl reload apache2
Since no one except the server knows about the postfixadmin.local domain anymore, in order not to register this domain separately on each host, I added this entry in the settings of my UXG Lite router: Settings -> Routing -> DNS -> Create Entry -> entry type A. Such settings are applied locally almost instantly.
After restarting the Apache server, you can go to the web interface at the address: http://postfixadmin.local/setup.php
PostfixAdmin web service configuration
The first visit to http://postfixadmin.local/setup.php will prompt you to generate a hash for the password you just created. This hash must be entered in the configuration file config.local.php
$CONF['setup_password'] = '$2y$10$.tW14352cmjVC3N07u9MQOphugNCl5tIOAdwhYLs21XT7/TwR7Lo.';
In most cases, the user may also encounter errors that are fatal for further configuration. Therefore, if you did not encounter an error when generating the hash, then all the flags should be green. Unfortunately, I also encountered errors that are quite lively discussed on the Internet, namely:
- Password Hashing – attempted to use configured encrypt backend (
dovecot:SHA512-CRYPT
) triggered an error: /usr/bin/doveadm pw failed, see error log for details - You will have problems logging into PostfixAdmin.
- Check out our Dovecot documentation at https://github.com/postfixadmin/postfixadmin/blob/master/DOCUMENTS/DOVECOT.txt, specifically around ‘3. Permissions’.
This means that PostfixAdmin failed to execute /usr/bin/doveadm pw, meaning it cannot generate passwords for Dovecot. In other words, doveadm needs access to dovecot.conf/certificates, which the www-data webserver user does not have
There are many methods to solve the access problem, but I will cover only two of them:
The first method is dangerous due to the addition of the www-data group to the dovecot group:
It is necessary to create a new configuration file for SSL keys, copy only the parameters of SSL keys to this file, add a link to the auxiliary SSL file at the end of the main dovecot configuration file, change the rights and owner for this file and restart dovecot to apply the changes.
This method is probably one of the simplest, but the danger lies in the fact that, for example, if wordpress and a mail server are installed on the server, then an attacker who gains unauthorized access to the www-data user will be able to gain access to all resources belonging to the Dovecot group, for example: sockets, configs, caches, logs with usernames. I tried this option for educational purposes, but I do not recommend it, but I will share the settings:
sudo nano /etc/dovecot/conf.d/ssl-keys.conf
# add path to certificates
ssl_cert = ...
ssl_key = ...
sudo nano /etc/dovecot/conf.d/10-ssl.conf
# remove or comment out these lines
ssl_cert = ...
ssl_key = ...
sudo nano /etc/dovecot/dovecot.conf
# add a link to the new file at the end of the file
!include_try /etc/dovecot/conf.d/ssl-keys.conf
# change permissions and owner of new file add www-data to dovecot group
sudo chown root:root /etc/dovecot/conf.d/ssl-keys.conf
sudo chmod 644 /etc/dovecot/conf.d/ssl-keys.conf
sudo usermod -aG dovecot www-data
# restart services
sudo systemctl restart dovecot apache2
The second method of setting up access with reduced risk:
It provides isolation between the web server and the mail server by giving the www-data user permission to the certificates, but this method did not work for me!
sudo setfacl -R -m u:www-data:rx /etc/letsencrypt/live/ /etc/letsencrypt/archive/
sudo setfacl -R -m u:www-data:rwx /var/run/dovecot/stats-reader /var/run/dovecot/stats-writer
After making changes, reload the page and enter the superadministrator password again. The solution worked for me, so my errors disappeared.

Let’s move on, namely the creation of a superuser! To do this, you need to fill out a form with 4 fields:
- Setup password – enter the current password
- Admin – email for super administrator login
- Password – complex password
- Password (again) – repeat a complex password
After that, click on the Add Admin button.

The successful creation will be indicated by the line:
Super admins – The following ‘super-admin‘ accounts have already been added to the database.
After the superuser is created, you can log in and continue with the settings. To do this, go to the login page http://postfixadmin.local/login.php

We enter the data of the super administrator that was created in the previous step and continue the settings.
This is what the dashboard looks like

Add a domain
On the dashboard, click the Overview button, and a window opens where you need to create a domain. Click the Add Domain button
In the Add a new domain window, there will be several fields that need to be filled in:
- Domain – my domain for mail as on this site – ostrich.kyiv.ua
- Description – the usual description, the field is not mandatory, but I filled it – Ostrich mail domain
- Forwards – is the number of forwarding mailboxes, I entered 15, I think it’s enough
- Mailboxes – is the total number of mailboxes that can be created in this mail server, I entered 15, I think it’s enough
- Mail server – is backup MX – there should not be a checkmark, because this is the main server and not a secondary one
- Active – the check mark must be there for the domain to be active
- Add default mail aliases – if checked, 4 aliases will be created: abuse, hostmaster, postmaster, webmaster

Add a mailbox
On the dashboard, click the Add Mailboxes button, and the Create a new mailbox for your domain window opens. where you need to fill out a form for a new user.
- Username – username (mailbox) for the ostrich.kyiv.ua domain
- Password – complex password
- Password (again) – repeat a complex password
- Name – the full name of the user
- Quota – for the test user, I set a quota of 10 megabytes, but if the field is empty, then the quota is not applied
- Active – ticked to activate this email
- Send Welcome mail – check the box to receive a welcome mail from the server when testing the mail client
- Other e-mail – mailbox for password recovery
After filling out the form, click Add Mailbox and the mail is instantly created

Postfix and Dovecot configuration
I previously created three configuration files, they need to be changed, namely to replace the username, password and name of the database for connection, the SQL query remains unchanged. I have these files at the base address: /etc/postfix/
- mysql-virtual-mailbox-domains.cf
user = postfixuser
password = <password>
hosts = 127.0.0.1m
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = 1
- mysql-virtual-mailbox-maps.cf
user = postfixuser
password = <password>
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = 1
- mysql-virtual-alias-maps.cf
user = postfixuser
password = <password>
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = 1
The database connection configuration must also be written in the dovecot-sql.conf.ext file
driver = mysql
connect = host=127.0.0.1 dbname=postfixadmin user=postfixuser password=<password>
default_pass_scheme = SHA512-CRYPT
password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active = 1
No more changes to the configuration should be made, so you can reload the services and check the mail
sudo systemctl restart postfix
sudo systemctl restart dovecot
Checking mail
If thunderbird was previously configured, it will continue to work in normal mode, provided that the mailbox password has not been changed. The same thing happened to me, when I opened the mail client, I received a welcome letter from the server, which indicates that the settings are correct.

Conclusions
Using services or applications greatly facilitates administration. If you are considering a Postfix mail server in a large organization, then PostfixAdmin will be a fairly simple and convenient tool for managing mail user accounts.