About Postadmin

Postadmin is a complete multiple domain email package. It will allow you to set up and manage any number of email domains and accounts on a single server. As I'm not an expert on Linux distributions other Redhat (RPM) distros, these instructions assume you are installing Postadmin on Redhat, CentOS, AlmaLinu, RockyLinux or any other RPM based distribution.

If you are installing on any other Linux distribution, it is very unlikely that the install and configure instructions described below will work without some work on your part. I will not be supporting installation on other distros, however, if you would like to contribute some time to making this project work on other distros you are welcome to do that, and so I will watch the repository for pull requests.

If you use SELinux then you know what there is to do to complete the installation and configuration. I don't use SELinux and so it is disabled for the installation and configuration described below.

A note about DNS

I will leave detailed instructions regarding email DNS requirements to someone else. However, I must warn that for receiving email to work at all, you must at least add a correct MX record for each email domain your new server will be supporting. Additionally, in order to send email that doesn't get rejected, it is highly recommended that you also add at least an SPF record, and even better both SPF and DKIM. You will also find that many email receivers will reject or quarantine emails from your server if you do not include DMARC.

Note that the Postadmin app can create DKIM keys and will provide a way to copy DNS records you can add to your DNS server for each email domain.

Installation

You can install all required packages at once by running the install_all.sh script found in the bin directory, or follow the instructions below. If you run the install_all script you can skip all of the required "dnf install" commands in the instructions below.

Running that script will display details about each package it is installing, including any message about already being installed.

Install git

You will need git to clone the Postadmin files, which includes the management web site, automated server configuration tools, and an artisan command to move an existing server to a new server managed by Postadmin. To do that you will need to have installed git.

dnf install git

Clone the Postadmin repo

Change directory to where the Postadmin management app will be cloned to, then run:

git clone git@gitlab.com:emmettc/postadmin.git

Once you have cloned the Postadmin repo you can access this README.md file on your new server.

Install dnf utilities

dnf install dnf-utils

Install and configure the epel repository

dnf install epel-release

The two following are no longer necessary in Redhat or other version 9 distributions

dnf config-manager --set-enabled powertools
dnf config-manager --set-disabled epel-playground

Optional: Install the remi repository:

You may need this repo because Postadmin requires at least php 8.3 and at this time CentOS or other redhat compatible distros versions 8.x come with PHP 7.2, though I expect that to change. I suggest you install the Remi repo at this time simply because you will want to keep up with PHP versions as they go EOL. 7.2 and 8.0 are EOL now.

dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm

dnf config-manager --set-enabled remi

DNF config manager is not needed for versions 9.

dnf config-manager --set-enabled remi-module

dnf module reset php only needed if PHP is already installed

if you installed remi

dnf module enable php:remi-8.3

if you did not install remi

dnf module enable php:8.3

You can install and enable later php versions if you like. I will attempt to keep Postadmin updated to support the latest PHP. This version has been tested and will only run on PHP 8.3 and up.

References

Install Remi on CentOS

Install Remi on Rocky Linux

Install php

dnf install php php-cli php-common php-fpm php-gd php-intl php-json php-mbstring php-mysqlnd php-pdo php-pecl-zip php-pgsql php-xml php-pecl-redis5 mod_ssl

Enable and start PHP-FPM

systemctl enable php-fpm --now

https://linuxize.com/post/how-to-install-php-on-centos-8/

Install npm and composer

dnf install nodejs npm

dnf install composer

Install and enable redis server

dnf install redis

systemctl enable redis --now

Install MariaDB server

dnf install mariadb-server

Unless you plan to provide external access to your mariadb database, I suggest adding the following line to /etc/my.cnf.d/mariadb-server.cnf under the [server] section:

bind-address=127.0.0.1

Enable and start the MariaDB server

systemctl enable mariadb --now

MariaDB initialization script

The following will allow you to set the root user's password. The default is no password.

mysql_secure_installation

Maria DB starts out with an empty password for the root user, so note username and password entered here..

Install cyrus imap

dnf install cyrus-imapd cyrus-imapd-utils cyrus-sasl cyrus-sasl-plain cyrus-sasl-lib

References

Installation Configuration Cyradm

Enable and start saslauthd

systemctl enable saslauthd --now

Install postfix and openDKIM

First postfix

dnf install postfix postfix-mysql postfix-pcre

You may want to install the latest postfix instead of early versions 3.x installed by all RPM distros at this time. In that case I suggest Ghetto forge:

Ghetto Forge

Install openDKIM

dnf install opendkim opendkim-tools

https://www.oreilly.com/library/view/postfix-the-definitive/0596002122/ch04s02.html

Set the opendkim keys directory permissions to allow Postadmin app to manage DKIM keys

chmod g+wsx /etc/opendkim/keys
chmod o+rx /etc/opendkim/keys

Install app vendor files

Change directory to postadmin web root, then run:

composer install

Install pam_mysql

The pam_mysql library is needed to allow authorization for both submission and imap access.

dnf install pam_mysql

pam_mysql may not be available in your server's repo, if it isn't see: https://github.com/NigelCunningham/pam-MySQL or search for another possible RPM.

Build Nigel's pam_mysql library:

First verify that your server doesn't have /usr/lib64/security/pam_mysql.so. If it doesn't you can build and install Nigel Cunningham's pam_mysql library:

Install packages you will need to build the library

dnf install gcc python3 mariadb-devel pam-devel python3.pip
pip install meson ninja

Get Nigel's repo

Create build directory (suggested) then change directories

cd /var/opt

Clone Nigel's pam_mysql repository

git clone https://github.com/NigelCunningham/pam-MySQL.git

Change directory to repo

cd pam-MySQL

Build the library

meson ../pam-MySQL-build
cd ../pam-MySQL-build
ninja

Copy the resultant pam_myslq.so file from your build location to /usr/lib64/security on your new email server. Consider doing the build on the server on which you are installing Postadmin. It is not likely that you will ever need to build it again, but you never know.

Note that Postadmin includes a pam-mysql.so binary in the repo's bin directory. I will attempt to keep the most current build in the repo, so it should be safe to use that library. To do that, first make sure /usr/lib64/security/pam_mysql.so does not already exist on your new server, then copy bin/pam_mysql.so to /usr/lib64/security. Or create a symlink to postadmin_root/bin/pam_mysql.so so that if pam_mysql.so gets updated in the repo you won't have to remember to copy it to replace the prevous version.

amavis-new, spamassassin and clam anti virus

dnf install amavisd-new amavisd-milter spamassassin clamd

Then run fresh clam. If you don't do this then the clamd service will not start, and so cause incoming mail to fail.

freshclam

Postadmin and mail server configuration

Preset all server variables

From the directory you cloned Postadmin into:

In the repo root there is a file named .env.dist. Copy that file to .env then edit that file. Note that some constant names begin with '---', those must be changed for your specific server. Be sure to remove the leading '---' from each line.

You can also edit the config/site.php. file and set the defaults. Note that in the config/site.php file the env('VARIABLE_NAME', 'something') sets the assigned object to the value assigned to VARIABLE_NAME in the .env file and if no such variable is found in the .env file, sets the object to 'something', which is set as the default value.

I intended that all pertinent objects in the config/site.php file have sensible defaults and all have variables set in the .env file.

As you might guess, setting these variables is the most important part of getting your new server fully functional using the ManageSystemConfig helper app.

Email server configuration

Once you've got the configuration variables assigned you can run the configuration app.

Change directory to the directory you cloned Postadmin into.

Run the provided server configuration app

Note that all server configuration files "changed" by the configuration app will be renamed so that you will be able to back out all changes made to the server.

Note also that these commands have to be run as root. Of course all of the above installation commands must also be run as root as well, but I suppose you found that out already.

Run app with help option to see what options are available

php artisan app:manage-config -?

After you have run both the -i and -a all, or each -a section individually (see -? output), the server should be ready to add email domains and accounts.

If you want Postadmin to be able to create and manage DKIM keys then run the following as root:

echo 'apache ALL=(root) NOPASSWD: /web/postadmin/bin/mkkey.sh *' > /etc/sudoers.d/apache

Change "/web/postadmin" (before /bin) path to the directory you cloned Postadmin into.

mkkey.sh causes openDKIM to create DKIM keys for your new email domain(s) if requested, as you create/manage each domain. It also changes the read permissions and ownership of certain openDKIM generated files so that Postadmin can read the DKIM signature you will need to add to your email domain's DNS record so that DKIM is correctly supported. That is all it does, so adding that script to sudoers.d/apache should not be any kind of security risk.

Now run the set-perms.sh script from Postadmin app directory. You will either need to run it as root or create sudoers.d file for your user.

set-perms.sh needs to be modified to set the correct user and group. I use my first name and add a group named web_prog. You need to change set-perms to your preferences.

echo 'myuser ALL = (root) NOPASSWD:/web/postadmin/set-perms.sh' > /etc/sudoers.d/myuser

Again, change the base path to the directory you cloned Postadmin into. And of course use your username instead of "myuser".

./set-perms.sh (as root)

or
sudo ./set-perms.sh

LetsEncrypt's certbot

Install certbot and it's apache plugin

dnf install certbot certbot-apache

Run certbot

certbot --apache

Because we will be using a letsencrypt cert for cyrus and postfix TLS access, we'll need to insure they are readable my the mail group.

chgrp -R mail /etc/letsencrypt

Set all directories in letsencrypt to group = rsx, 's' because we want new files to be created as mail group. Please see note about umask requirements.

find /etc/letsencrypt -type d -exec chmod -R g+rsx {} +
chmod g+r /etc/letsencrypt/archive/*

You will want to add a line to the root's crontab so that your certificates get renewed automatically.

0 0 1,11,22 * * /usr/bin/certbot renew >/dev/null 2>&1

These certs cannot be renewed until they are near expiration, so we try a few times a month. They wouldn't mind if you attempted even a few times each day, but let's be good citizens.

You will also need to set your UMASK to 0002. You can do that in the /etc/bashrc file. This will cause all files created to have group read and write permission, and new directories to allow entry by its group.

This, by the way, is why we needed to set all directories to "g+rsx" to insure all files created include the group of the parent.

We need to set the umask for apache as well. To do that add UMask=002 under the [Service] section in the /usr/lib/systemd/system/php-fpm.service file.

If you have multiple versions of PHP running you will want to do the same for each of their systemd service files. Also add it to the /user/lib/systemd/system/httpd file. Then run systemctl daemon-reload.

Creating the Postadmin database

Postadmin assumes the database server will have a user named root that has all privileges. If yours is not root then set "DB_ROOT_USERNAME" in the .env file to the correct superuser name.

After populating all database authentication variables in the .env file, including "DB_ROOT_PASSWORD" you can create the database by running this from the Postadmin site's web root:

php artisan db:create

Run the database migration and seeders *

php artisan migrate --seed

This creates the tables and sets some initial content. This will create a Postadmin web app super user login, so please be sure to edit the database/seeders/UserTableSeder.php file to set that users credentials as needed.

You will probably want to remove DB_ROOT_PASSWORD and DB_ROOT_USERNAME from the .env file once you have created the database.

Note that you can refresh the database by running:

php artisan db:create --drop
php artisan db:create
php artisan migrate --seed

Dropping the database will not be allowed if the APP_ENV variable in the .env file is set to "production".

Upgrade from previous and no longer supported Web-cyradm installation

From the Postadmin workspace run the following:

php artisan app:manage-upgrade -?

Hopefully how to use the upgrade command will be clear :-)

But just in case:

You must first allow remote access to tha database on the "old" Web-cryadm email server. I did that by allowing remote access on the old machine in mysql/mariadb with bind-address=0.0.0.0 then adding a rule to that machine's firewall allowing only my new server's IP address to access port 3306.

Run: php artisan app:manage-upgrade -c

Then collect the passwords for each email account on the old server and add them to the storage/app/sys_config/account.lst file. Add each password on the same line in the account.lst file after the appropriate account user name.

If you do not have a password for any account then either make one up for that account and change it on the old server, or leave it blank. If you leave it blank then that account's password will be changed to "ChangeMe" on both the old server and the new if you include the -P option, and so will have to be changed by you or the account owner to enable that account to send or receive email.

Once you have populated the account.lst file you can run:

php artisan app:manage-upgrade -s

That command will read the old server DB and copy all domains, accounts, aliases, forward rules and catchall rules from the old server to the new. Then attempt to sync all IMAP data from the old server to the new.

Once complete, your new server should be fully functional. You can do the upgrade one domain at a time or all at once.

Note again, if you include the -P option, any accounts with a blank password in the account.lst file will have its password changed to "ChangeMe". I suggest that you first run the upgrade process against an unused domain and account that you create on the old server for this sanity check. That domain does not need to be accessible on the internet, as only the upgrade process will see it, but it may be useful to prove the upgrade process is safe.

Without the -P option the IMAP sync will not be run for any account that doesn't have a password assigned in account.lst.

This is the process I used:

php artisan app:manage-upgrade -opractice.tld -s

Don't forget that changing the IP address will cause any open SSH session to lose its connection, so if you only have remote access, make sure the process you use to change the IP address is atomic, and so will not be prevented from completing by a lost connection. I know, you knew that already. You will never guess how I found that out.

Not an old web-cyradm server?

This process should work to move any postfix/cyrus-imad email server to Postadmin. You will need to check all accesses to the $old database connection calls in the artisan command in app/Console/Commands/ManageUpgrade.php, and adjust the table and field names accordingly.

Open source

Note that I would appreciate pull requests that add functionality to this upgrade process, or any other functionality of the Postadmin app. Contact me at emmett@webengineer.com if you would like to contribute.

Optional: Install phpMyAdmin

phpMyadmin is a good tool for managing MariaDB/MySQL databases. Here is how you can install it on your new server:

dnf install phpMyAdmin

If this doesn't work, then do the following: but first go look at the site shown below, so you get the latest version. Then change the version number from 4.9.2 to whatever is the latest version.

Installing phpMyAdmin on CentOS

wget https://files.phpmyadmin.net/phpMyAdmin/4.9.2/phpMyAdmin-4.9.2-all-languages.zip

unzip phpMyAdmin-4.9.2-all-languages.zip

mv phpMyAdmin-4.9.2-all-languages /usr/share/phpMyAdmin

cd /usr/share/phpMyAdmin; mv config.sample.inc.php config.inc.php

Change the following line in the config.inc.php with a new secret: $cfg['blowfish_secret'] = 'your-secret-phrase';

mkdir /usr/share/phpmyadmin/tmp
chown -R apache:apache /usr/share/phpmyadmin/tmp
chmod 777 /usr/share/phpmyadmin/tmp

The above assumes you will be allowing only local access to phpMyAdmin. Otherwise, set permissions accordingly.

Security Vulnerabilities

If you discover a security vulnerability within Postadmin, please send an email to Emmett Culley via emmett@webengineer.com. All security vulnerabilities will be promptly addressed.

License

The Postadmin is open-source software licensed under the MIT license.