Grommunio Mail Server

From Alpine Linux
This material is work-in-progress ...

This is a work in progress
(Last edited by Midas on 30 Nov 2024.)


HOWTO: Install AlpineLinux Mail Server with Grommunio

This tutorial outlines the steps for setting up a mail server on Alpine Linux using Grommunio, a modern, open-source groupware solution that supports email and calendar services. The installation includes MariaDB, Nginx, PHP, Postfix, and other components necessary for a fully functioning mail server.

Prerequisites

Before proceeding with the installation, ensure you have a fresh Alpine Linux system setup. You'll need root privileges to execute these commands.

Procedure

  1. Install and configure MariaDB
  2. MariaDB performance tuning (optional)
  3. Install and configure Nginx
  4. Install and configure PHP
  5. Install and configure Postfix
  6. Install and configure Grommunio
  7. Configure Valkey (Redis replacement)
  8. Install and configure Rspamd
  9. Finalize and verify installation


1. Install and Configure MariaDB

Install MariaDB

To start, install MariaDB and necessary utilities

 apk add mariadb mariadb-client mariadb-server-utils


Define the variables used later in the setup setup and configuration.

The default datapath is /var/lib/mysql and contains the entire database. If you prefer another location define it here and create a symlink. In any case, the grommunio database will be rather small as it only contains the configuration.

 DB_DATA_PATH="/srv/mysql"
 DB_ROOT_PASS="Passw0rd1"
 DB_USER="admin"
 DB_PASS="Passw0rd2"


Setup the default system tables:

 sudo mysql_install_db --user=mysql --datadir=${DB_DATA_PATH}


Set a symlink to the standard mysql data directory for compatibility reason:

 ln -s /srv/mysql /var/lib/mysql


Restart service:

 rc-service mariadb restart


Run the built-in security script:

Set the new root password to the one defined above and answer everything with 'y'

 sudo mysql_secure_installation


Create MariaDB User for Grommunio

Create a new user for Grommunio and assign privileges:

 echo "GRANT ALL ON *.* TO ${DB_USER}@'127.0.0.1' IDENTIFIED BY '${DB_PASS}' WITH GRANT OPTION;" > /tmp/sql
 echo "GRANT ALL ON *.* TO ${DB_USER}@'localhost' IDENTIFIED BY '${DB_PASS}' WITH GRANT OPTION;" >> /tmp/sql
 echo "GRANT ALL ON *.* TO ${DB_USER}@'::1' IDENTIFIED BY '${DB_PASS}' WITH GRANT OPTION;" >> /tmp/sql
 echo "DELETE FROM mysql.user WHERE User=;" >> /tmp/sql
 echo "FLUSH PRIVILEGES;" >> /tmp/sql
 cat /tmp/sql | mysql -u root --password="${DB_ROOT_PASS}"


Configure MariaDB for Grommunio

Edit the MariaDB configuration for better performance:

 vi /etc/my.cnf.d/mariadb-server.cnf


Add the following configuration:

 [mysqld]
 #skip-networking
 
 ## Configuration for grommunio (most values are default)
 innodb_log_buffer_size=16M
 innodb_log_file_size=32M
 innodb_read_io_threads=4
 innodb_write_io_threads=4
 
 join_buffer_size=512K
 query_cache_size=0
 query_cache_type=0
 query_cache_limit=2M
 
 # Activate performance schema
 performance_schema=ON
 
 # Bind to localhost only
 bind-address = 127.0.0.1
 
 # Disable DNS lookups as we only use localhost connections
 skip-name-resolve=ON


Create a default charset configuration for MariaDB:

 cat > /etc/my.cnf.d/mariadb-server-default-charset.cnf << EOF
 [client]
 default-character-set = utf8mb4
 
 [mysqld]
 collation_server = utf8mb4_general_ci
 character_set_server = utf8mb4
 
 [mysql]
 default-character-set = utf8mb4
 EOF


Restart MariaDB and enable it to start on boot:

 rc-update add mariadb default
 rc-service mariadb restart


Verify MariaDB Setup

Check if the MariaDB listener is running and bound to the correct interface (127.0.0.1):

 ss -tulpn

Create Grommunio Database

Define the database parameters and create the Grommunio database:

 MYSQL_HOST="localhost"
 MYSQL_USER="grommunio"
 MYSQL_PASS="Passw0rd3"
 MYSQL_DB="grommunio"
 echo "create database $MYSQL_DB character set 'utf8mb4';" > /tmp/sql
 echo "grant select, insert, update, delete, create, drop, index, alter, create temporary tables, lock tables on 
 $MYSQL_DB.* TO $MYSQL_USER@$MYSQL_HOST identified by '$MYSQL_PASS';" >> /tmp/sql
 echo "flush privileges;" >> /tmp/sql
 cat /tmp/sql | mysql -u admin --password="${DB_PASS}"


Test the database connection:

 mysql -hlocalhost -u grommunio -p${MYSQL_PASS} grommunio

2. MariaDB Performance Tuning (Optional)

Install and configure MySQLTuner to help with database performance:

 wget -v --no-check-certificate https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl -O /tmp/mysqltuner.pl
 mv /tmp/mysqltuner.pl /usr/local/bin/mysqltuner.pl
 chmod 755 /usr/local/bin/mysqltuner.pl
 apk add perl perl-doc
 /usr/local/bin/mysqltuner.pl --user admin --pass ${DB_PASS}


3. Install and Configure Nginx

Install Nginx

Install the necessary Nginx modules:

 apk add nginx nginx-mod-http-headers-more nginx-mod-http-vts nginx-mod-http-brotli


Configure Nginx

Backup the original Nginx configuration and edit it for security headers and TLS settings:

 cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
 vi /etc/nginx/nginx.conf


Add the following configuration:

 error_log syslog:server=unix:/dev/log,facility=local2,nohostname warn;
 more_set_headers "Strict-Transport-Security : max-age=2592000; includeSubDomains;";
 more_set_headers "X-Frame-Options : SAMEORIGIN";
 more_set_headers "Content-Security-Policy : default-src https: data: 'unsafe-inline' 'unsafe-eval' always";
 more_set_headers "X-Xss-Protection : 1; mode=block";
 more_set_headers "X-Content-Type-Options : nosniff";
 more_set_headers "Referrer-Policy : strict-origin-when-cross-origin";
 more_set_headers "Server : Follow the white rabbit.";
 ssl_protocols TLSv1.2 TLSv1.3;
 ssl_session_cache shared:SSL:1m;
 ssl_session_timeout 5m;
 log_format main_ssl '$remote_addr - $remote_user [$time_local] "$request" '
 '$status $body_bytes_sent "$http_referer" '
 '"$http_user_agent" "$http_x_forwarded_for" '
 'client_ciphers="$ssl_ciphers" client_curves="$ssl_curves"';
 
 access_log off;


Restart Nginx and enable it to start on boot:

 rc-update add nginx
 service nginx restart


4. Install and Configure PHP

Install PHP

Install the required PHP packages for Grommunio:

 apk add php83 php83-fpm


Harden PHP Configuration

Disable insecure PHP settings and adjust PHP limits:

 sed 's/^;\?\(allow_url_fopen\).*/\1 = Off/' -i /etc/php83/php.ini
 sed 's/^;\?\(expose_php\).*/\1 = Off/' -i /etc/php83/php.ini
 sed 's/^;\?\(display_errors\).*/\1 = Off/' -i /etc/php83/php.ini
 sed 's/^;\?\(log_errors\).*/\1 = On/' -i /etc/php83/php.ini


Configure Session Security

Configure PHP session security:

 sed 's/^;\?\(session.use_strict_mode\).*/\1 = 1/' -i /etc/php83/php.ini
 sed 's/^;\?\(session.cookie_secure\).*/\1 = 1/' -i /etc/php83/php.ini
 sed 's/^;\?\(session.cookie_httponly\).*/\1 = 1/' -i /etc/php83/php.ini


5. Install and Configure Postfix

Install Postfix

Install Postfix and related modules:

 apk add postfix postfix-mysql postfix-pcre


Configure Postfix

Backup and configure the Postfix settings. Adapt the values as necessary, such as `myhostname`, `mynetworks`, and `smtp_tls_chain_files`:

 mv /etc/postfix/main.cf /etc/postfix/main.cf.orig
 mv /etc/postfix/master.cf /etc/postfix/master.cf.orig


Run Postfix setup:

 newaliases
 postmap /etc/postfix/transport


Enable Postfix service:

 rc-update add postfix
 service postfix restart


Verify Postfix Logs

Check the Postfix logs for any errors:

tail -f /var/log/maillog


9. Finalize and Verify Installation

Step 1: Test Server Components

Ensure that all services (Postfix, MariaDB, Nginx, PHP, Grommunio) are running correctly:

 ss -tulpn


Step 2: Verify Mail Functionality

Test sending and receiving emails using a mail client and verifying server logs for any errors.


6. Install and Configure Grommunio

Enable IPv6

Since Grommunio requires IPv6 for its daemons:

1. Edit `/etc/hosts` to include IPv6 localhost:

 vi /etc/hosts
 -----
 ::1		localhost ipv6-localhost ipv6-loopback
 -----


2. Ensure IPv6 is enabled in `/etc/sysctl.conf`:

 sed -i 's/^net\.ipv6\.conf\..*\.disable_ipv6\s=\s1/#&/' /etc/sysctl.conf
 sysctl -p
 ping ::1  # Test if IPv6 is working


Configure Database Parameters

Set up your MySQL database connection details:

 MYSQL_HOST="localhost"
 MYSQL_USER="grommunio"
 MYSQL_PASS="Passw0rd3"
 MYSQL_DB="grommunio"


Specify Internal FQDN, Mail Domain, and Relayhost

Adjust the following for your specific setup:

 FQDN="mail.example.local"
 MAILDOMAIN="example.com"
 RELAYHOST="123.123.123.1"
 ADMIN_PASS="Passw0rd4"


Install Dependencies and Grommunio Packages

Install necessary dependencies:

 apk add valkey valkey-cli cyrus-sasl cyrus-sasl-login util-linux-login
 apk add grommunio-gromox grommunio-web grommunio-admin-api grommunio-admin-web grommunio-index grommunio-error-pages


Optionally, install deprecated ActiveSync if needed:

 # apk add grommunio-dav grommunio-sync


Move Mail Storage to Another Disk

Move the largest directory `/var/lib/gromox` to another disk and create a symlink:

 mv /var/lib/gromox /srv/gromox
 ln -s /srv/gromox /var/lib/gromox


Enable Required Services

Enable all necessary Grommunio services:

 rc-update add grommunio-admin-api
 rc-update add gromox-delivery
 rc-update add gromox-delivery-queue
 # Add all the other grommunio services


Configure Grommunio Files

Modify the configuration files to match your environment:

 sed -i "s/mail.example.local/${FQDN}/g" /etc/gromox/*.cfg
 sed -i "s/example.com/${MAILDOMAIN}/g" /etc/gromox/*.cfg
 # Continue modifying other configuration files (mysql_adaptor.cfg, autodiscover.ini, etc.)


Configure Postfix

Prepare Postfix for integration with Grommunio:

 cp -p /etc/postfix/grommunio-virtual-mailbox-maps.cf /etc/postfix/grommunio-virtual-mailbox-sender-maps.cf
 sed -i '/^query =/d' /etc/postfix/grommunio-virtual-mailbox-sender-maps.cf
 echo "query = SELECT username FROM users WHERE username='%s' UNION SELECT aliasname FROM aliases WHERE mainname='%s'" >> /etc/postfix/grommunio-virtual-mailbox-sender-maps.cf


Configure TLS Certificates

Link and configure your SSL certificates:

 ln -s /etc/grommunio-common/nginx/ssl_certificate.conf /etc/grommunio-admin-common/nginx-ssl.conf
 cat /etc/ssl/private/${FQDN}.key.pem /etc/ssl/certs/${FQDN}.cert.pem > /etc/ssl/private/${FQDN}.key_cert.pem
 chmod 640 /etc/ssl/private/*.key_cert.pem
 addgroup gromox ssl-cert


Configure PAM and SASL

Set up authentication services:

 # Configure PAM for SMTP
 cat > /etc/pam.d/smtp <<EOF
 #%PAM-1.0
 auth required pam_gromox.so service=smtp
 account required pam_permit.so
 EOF
 # Configure SASL authentication
 cat > /etc/conf.d/saslauthd <<EOF
 SASLAUTHD_OPTS="-a pam -r"
 EOF


Initialize the Database and Set Admin Password

Initialize the database:

 gromox-dbop -C

Set the Grommunio admin password:

 grommunio-admin passwd --password "${ADMIN_PASS}"


Configure Firewall Ports

Open the necessary firewall ports:

 # Required ports: 25, 80, 443, etc.


7. Configure Valkey (Redis Replacement)

Enable Syslog

 vi /etc/valkey/grommunio.conf
 -----
 syslog-enabled yes
 syslog-ident valkey
 syslog-facility local0
 -----


Enable Memory Overcommit

 vi /etc/sysctl.conf
 -----
 vm.overcommit_memory = 1
 -----
 sysctl -p


Start Valkey and Test

 rcctl restart valkey@grommunio
 valkey-cli ping  # Expected result: 'PONG'


8. Install and Configure Rspamd

Install Rspamd

 apk add rspamd rspamd-client


Configure Rspamd

Modify Rspamd configuration files:

 cat > /etc/rspamd/local.d/options.inc <<EOF
 dns {
   enable_dnssec = true;
   timeout = 4s;
  retransmits = 5;
 }
 EOF
 cat > /etc/rspamd/local.d/redis.conf <<EOF
 read_servers = "127.0.0.1";
 write_servers = "127.0.0.1";
 EOF
 cat > /etc/rspamd/local.d/worker-proxy.inc <<EOF
 milter = yes;
 bind_socket = "/var/run/rspamd/worker-proxy.sock mode=0660 owner=rspamd";
 timeout = 120s;
 upstream "local" {
   default = yes;
   self_scan = yes;
 }
 count = 4;
 EOF


Add Postfix to Rspamd Group

 addgroup postfix rspamd


Configure DKIM Signing

 cat > /etc/rspamd/local.d/dkim_signing.conf <<EOF
 enabled = true;
 path = "/var/lib/rspamd/dkim/\$domain-\$selector.key";
 selector = "dkim";
 sign_authenticated = true;
 sign_local = false;
 domain {
   example.com { selector = "202406"; }
 }
 EOF


Generate DKIM Key Pair

 mkdir -p /var/lib/rspamd/dkim
 rspamadm dkim_keygen -s 202406 -t ED25519 -d example.com -k /var/lib/rspamd/dkim/example.com-202406.key > 
 /var/lib/rspamd/dkim/example.com-202406.pub


Start Rspamd

 rc-update add rspamd
 rcctl start rspamd


9. Finalize and Verify Installation

Restart Services

Restart all services:

 rcctl restart postfix saslauthd rspamd valkey@grommunio nginx php-fpm83 gromox-delivery gromox-event \
   gromox-http gromox-imap gromox-midb gromox-pop3 gromox-delivery-queue gromox-timer gromox-zcore \
   grommunio-admin-api


Verify Service Status

Check the status of all services:

 rcctl status


Check Logs

Inspect logs for any errors or issues:

 find /var/log -type f | xargs tail -n50 | grep -iE '==>|fail|crit|error|alert|corrupt|warning'


Web UI Access

Admin UI: [1](https://mail.example.local:8443)


10. End User Configuration

Admin UI

Log into the Admin UI with the username `admin` and the previously created `ADMIN_PASS`.

License Configuration

If you have a license, you can configure it under Grommunio settings in the Admin UI.