This comprehensive guide covers the installation and configuration of open-source alternatives to Microsoft Exchange Server. While Microsoft Exchange is a proprietary messaging and collaboration platform, several excellent free and open-source software (FOSS) alternatives provide similar functionality for email, calendaring, contacts, and collaboration.
Primary Open-Source Alternatives to Microsoft Exchange:
This guide prioritizes production-ready, enterprise-grade solutions that can serve as direct replacements for Microsoft Exchange Server in business environments.
1. Prerequisites
Operating System Requirements
RHEL-based Systems (Recommended):
# RHEL 8/9, CentOS Stream, Rocky Linux, AlmaLinux
sudo dnf update -y
sudo dnf install -y epel-release
Debian-based Systems:
# Debian 11/12, Ubuntu 20.04/22.04/24.04 LTS
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 software-properties-common
Arch-based Systems:
# Arch Linux, Manjaro, EndeavourOS
sudo pacman -Syu
sudo pacman -S base-devel curl wget
Alpine Linux:
# Alpine 3.18+
apk update && apk upgrade
apk add --no-cache curl wget bash
SUSE-based Systems:
# openSUSE Leap/Tumbleweed, SLES
sudo zypper refresh && sudo zypper update
sudo zypper install -y curl wget
Hardware Requirements
Minimum Production Requirements:
Recommended Enterprise Configuration:
Network Requirements
Required Ports:
DNS Requirements
# Required DNS records for mail.example.com
# MX record
example.com. IN MX 10 mail.example.com.
# A/AAAA records
mail.example.com. IN A 192.168.1.10
mail.example.com. IN AAAA 2001:db8::10
# Additional records
autodiscover.example.com. IN A 192.168.1.10
webmail.example.com. IN A 192.168.1.10
# SPF, DKIM, and DMARC records (configured during setup)
SSL Certificate Requirements
# Obtain SSL certificates before installation
# Using Let's Encrypt (recommended for most deployments)
sudo apt install -y certbot # Debian/Ubuntu
sudo dnf install -y certbot # RHEL/Fedora
sudo pacman -S certbot # Arch
apk add --no-cache certbot # Alpine
# Generate certificates
sudo certbot certonly --standalone -d mail.example.com -d webmail.example.com -d autodiscover.example.com
2. Installation
Zimbra Collaboration Suite Installation
RHEL/CentOS/Rocky/AlmaLinux:
# Download Zimbra Open Source Edition
cd /tmp
wget https://files.zimbra.com/downloads/8.8.15_GA/zcs-8.8.15_GA_3869.RHEL8_64.20190918004220.tgz
tar -xzf zcs-8.8.15_GA_3869.RHEL8_64.20190918004220.tgz
cd zcs-8.8.15_GA_3869.RHEL8_64.20190918004220
# Install prerequisites
sudo dnf install -y perl perl-core libaio unzip nc sysstat sqlite rsync
# Disable conflicting services
sudo systemctl stop postfix sendmail
sudo systemctl disable postfix sendmail
# Run installer
sudo ./install.sh
# Follow interactive prompts:
# - Accept license agreement
# - Install all default packages
# - Configure domain name and admin password
# - Set timezone and enable services
Debian/Ubuntu:
# Download Zimbra for Ubuntu
cd /tmp
wget https://files.zimbra.com/downloads/8.8.15_GA/zcs-8.8.15_GA_3869.UBUNTU20_64.20190918004220.tgz
tar -xzf zcs-8.8.15_GA_3869.UBUNTU20_64.20190918004220.tgz
cd zcs-8.8.15_GA_3869.UBUNTU20_64.20190918004220
# Install prerequisites
sudo apt install -y libidn11 libpcre3 libgmp10 libexpat1 libstdc++6 libperl5.32 unzip pax sysstat sqlite3
# Stop conflicting services
sudo systemctl stop postfix exim4
sudo systemctl disable postfix exim4
# Run installer
sudo ./install.sh
Kopano Installation
RHEL/CentOS/Rocky/AlmaLinux:
# Add Kopano repository
sudo dnf install -y https://download.kopano.io/community/rhel:/kopano-core:/el8/x86_64/kopano-core-el8-release-1-1.noarch.rpm
# Install Kopano Core
sudo dnf install -y kopano-server kopano-gateway kopano-dagent kopano-spooler kopano-monitor kopano-search kopano-webapp
# Install MariaDB for backend
sudo dnf install -y mariadb-server
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
Debian/Ubuntu:
# Add Kopano repository
curl -s https://download.kopano.io/community/debian:/kopano-core:/debian10/Release.key | sudo apt-key add -
echo "deb https://download.kopano.io/community/debian:/kopano-core:/debian10/ ./" | sudo tee /etc/apt/sources.list.d/kopano.list
# Update package list and install
sudo apt update
sudo apt install -y kopano-server kopano-gateway kopano-dagent kopano-spooler kopano-monitor kopano-search kopano-webapp
# Install MariaDB
sudo apt install -y mariadb-server
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
SOGo Installation
RHEL/CentOS/Rocky/AlmaLinux:
# Add SOGo repository
sudo dnf install -y https://packages.inverse.ca/SOGo/nightly/5/rhel/8/x86_64/sogo-release-5-1.noarch.rpm
# Install SOGo and dependencies
sudo dnf install -y sogo sogo-tool postgresql-server postgresql-contrib nginx
sudo dnf install -y memcached gnustep-base gnustep-make
# Initialize PostgreSQL
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql memcached
Debian/Ubuntu:
# Add SOGo repository
sudo apt-key adv --keyserver keys.gnupg.net --recv-key 0x810273C4
echo "deb https://packages.inverse.ca/SOGo/nightly/5/ubuntu/ $(lsb_release -cs) $(lsb_release -cs)" | sudo tee /etc/apt/sources.list.d/sogo.list
# Install SOGo and dependencies
sudo apt update
sudo apt install -y sogo postgresql postgresql-contrib nginx memcached
sudo systemctl enable --now postgresql memcached
Citadel Installation
RHEL/CentOS/Rocky/AlmaLinux:
# Install from EPEL repository
sudo dnf install -y epel-release
sudo dnf install -y citadel-server citadel-webcit
# For manual installation from source
cd /tmp
wget http://www.citadel.org/doku.php/installation:source
tar -xzf citadel.tar.gz
cd citadel-*
./configure --prefix=/usr/local/citadel
make && sudo make install
Debian/Ubuntu:
# Install from Ubuntu repositories
sudo apt install -y citadel-server citadel-webcit citadel-dbg
# Configure during installation:
# - Select authentication method
# - Configure LDAP if needed
# - Set admin password
Arch Linux:
# Install from AUR
yay -S citadel-server citadel-webcit
# Or manual installation
sudo pacman -S base-devel git
git clone https://aur.archlinux.org/citadel-server.git
cd citadel-server
makepkg -si
Carbonio Installation
RHEL/CentOS/Rocky/AlmaLinux:
# Add Carbonio repository
sudo dnf install -y https://download.zextras.com/carbonio-release/rpm/x86_64/carbonio-release-1.0-1.x86_64.rpm
# Install Carbonio
sudo dnf install -y carbonio-directory-server carbonio-proxy carbonio-webui carbonio-mta carbonio-appserver
# Install PostgreSQL for database backend
sudo dnf install -y postgresql-server postgresql-contrib
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
Debian/Ubuntu:
# Add Carbonio repository
wget -O - https://download.zextras.com/carbonio-release/gpg/carbonio-release.gpg.key | sudo apt-key add -
echo "deb https://download.zextras.com/carbonio-release/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/carbonio.list
# Install Carbonio
sudo apt update
sudo apt install -y carbonio-directory-server carbonio-proxy carbonio-webui carbonio-mta carbonio-appserver
# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql
iRedMail Installation (Quick Deploy Option)
All Supported Operating Systems:
# Download iRedMail installer
cd /tmp
wget https://github.com/iredmail/iRedMail/archive/1.6.3.tar.gz
tar -xzf 1.6.3.tar.gz
cd iRedMail-1.6.3
# Run interactive installer
sudo bash iRedMail.sh
# Select options during installation:
# - Web server: Nginx (recommended)
# - Backend: MariaDB or PostgreSQL
# - Mail domain name
# - Admin password
# - Optional components (SOGo, Roundcube, etc.)
Mailcow Installation (Docker-based)
All Supported Operating Systems:
# Install Docker and Docker Compose
curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Clone Mailcow repository
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
# Generate configuration
./generate_config.sh
# Edit mailcow.conf with your domain and settings
sudo nano mailcow.conf
# Deploy Mailcow
docker-compose pull
docker-compose up -d
3. Configuration
Production Zimbra Configuration
#### Complete Zimbra Server Configuration
# Switch to zimbra user
su - zimbra
# Create production configuration script
cat > /tmp/zimbra-production-config.sh << 'EOF'
#!/bin/bash
# Zimbra Production Configuration Script
# Set global configuration parameters
zmprov mcf zimbraMailMode https
zmprov mcf zimbraMailPort 443
zmprov mcf zimbraMailSSLPort 443
zmprov mcf zimbraReverseProxyMailMode https
zmprov mcf zimbraReverseProxyHttpEnabled FALSE
zmprov mcf zimbraReverseProxyMailEnabled TRUE
# Configure security settings
zmprov mcf zimbraPasswordMinLength 12
zmprov mcf zimbraPasswordMinUpperCaseChars 1
zmprov mcf zimbraPasswordMinLowerCaseChars 1
zmprov mcf zimbraPasswordMinDigitsOrPuncs 2
zmprov mcf zimbraPasswordEnforceHistory 12
zmprov mcf zimbraPasswordMaxAge 90
zmprov mcf zimbraPasswordLockoutEnabled TRUE
zmprov mcf zimbraPasswordLockoutDuration 30m
zmprov mcf zimbraPasswordLockoutMaxFailures 5
zmprov mcf zimbraPasswordLockoutFailureLifetime 1h
# Configure authentication
zmprov mcf zimbraAuthMech zimbra ldap
zmprov mcf zimbraAuthFallbackToLocal FALSE
zmprov mcf zimbraForceClearCookies TRUE
# Configure session settings
zmprov mcf zimbraMailIdleSessionTimeout 30m
zmprov mcf zimbraAdminAuthTokenLifetime 12h
zmprov mcf zimbraAuthTokenLifetime 2d
zmprov mcf zimbraMailTrustedSenderList admin@example.com postmaster@example.com
# Configure anti-spam settings
zmprov mcf zimbraSpamKillPercent 75
zmprov mcf zimbraSpamTagPercent 20
zmprov mcf zimbraSpamSubjectTag "***SPAM***"
zmprov mcf zimbraAmavisDSPAMEnabled TRUE
zmprov mcf zimbraAmavisSAEnabled TRUE
# Configure attachment settings
zmprov mcf zimbraMtaBlockedExtension exe com bat cmd scr pif lnk dll vbs js
zmprov mcf zimbraAttachmentsBlocked TRUE
zmprov mcf zimbraMailContentMaxSize 52428800
zmprov mcf zimbraFileUploadMaxSize 52428800
zmprov mcf zimbraMtaMaxMessageSize 52428800
# Configure backup settings
zmprov mcf zimbraBackupMode Standard
zmprov mcf zimbraBackupTarget /opt/zimbra/backup
zmprov mcf zimbraBackupAutoGroupedMode TRUE
zmprov mcf zimbraBackupReportEmailRecipients admin@example.com
zmprov mcf zimbraBackupReportEmailSender backup@example.com
# Configure logging
zmprov mcf zimbraLogHostname mail.example.com
zmprov mcf zimbraLogLevel INFO
zmprov mcf zimbraLogToSyslog TRUE
zmprov mcf zimbraMailboxLogSize 100MB
# Configure performance settings
zmprov mcf zimbraHttpNumThreads 500
zmprov mcf zimbraImapNumThreads 300
zmprov mcf zimbraLmtpNumThreads 20
zmprov mcf zimbraMessageCacheSize 10000
zmprov mcf zimbraMailboxCacheSize 5000
# Configure SSL/TLS
zmprov mcf zimbraSSLExcludeCipherSuites SSL_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_EXPORT_WITH_RC4_40_MD5 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
zmprov mcf +zimbraSSLExcludeCipherSuites SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA256
zmprov mcf zimbraMtaTlsSecurityLevel may
zmprov mcf zimbraMtaTlsAuthOnly TRUE
echo "Zimbra production configuration completed"
EOF
chmod +x /tmp/zimbra-production-config.sh
/tmp/zimbra-production-config.sh
# Configure domains
zmprov cd example.com zimbraGalMode both
zmprov md example.com zimbraAuthMech zimbra
zmprov md example.com zimbraAutoProvNotificationSubject "Welcome to Zimbra Mail"
zmprov md example.com zimbraFeatureBriefcasesEnabled TRUE
zmprov md example.com zimbraFeatureTasksEnabled TRUE
zmprov md example.com zimbraFeatureCalendarEnabled TRUE
zmprov md example.com zimbraFeatureContactsEnabled TRUE
# Create admin account with strong password
zmprov ca admin@example.com 'Admin#Pass2024$Complex!' zimbraIsAdminAccount TRUE
zmprov ma admin@example.com zimbraFeatureCalendarEnabled TRUE
zmprov ma admin@example.com zimbraFeatureTasksEnabled TRUE
zmprov ma admin@example.com zimbraPrefTimeZoneId "America/New_York"
# Configure distribution lists
zmprov cdl all@example.com
zmprov adlm all@example.com admin@example.com
# Configure COS (Class of Service)
zmprov cc production zimbraFeatureCalendarEnabled TRUE zimbraFeatureTasksEnabled TRUE
zmprov mc production zimbraMailQuota 10737418240
zmprov mc production zimbraMailTrashLifetime 30d
zmprov mc production zimbraMailSpamLifetime 7d
#### SSL Certificate Configuration
# Deploy Let's Encrypt certificate
/opt/zimbra/bin/zmcertmgr verifycrt comm /etc/letsencrypt/live/mail.example.com/privkey.pem /etc/letsencrypt/live/mail.example.com/cert.pem /etc/letsencrypt/live/mail.example.com/chain.pem
# Deploy certificate
/opt/zimbra/bin/zmcertmgr deploycrt comm /etc/letsencrypt/live/mail.example.com/cert.pem /etc/letsencrypt/live/mail.example.com/chain.pem
# Restart proxy
zmproxyctl restart
Production Kopano Configuration
#### Complete Kopano Server Configuration
# Create comprehensive Kopano configuration
sudo tee /etc/kopano/server.cfg << 'EOF'
##############################################################
# KOPANO SERVER PRODUCTION CONFIGURATION
##############################################################
# Server settings
server_bind = 0.0.0.0
server_tcp_port = 236
server_pipe_enabled = yes
server_pipe_name = /var/run/kopano/server.sock
server_pipe_priority = /var/run/kopano/prio.sock
server_name = Kopano Server
server_hostname = mail.example.com
# Database Configuration
database_engine = mysql
mysql_host = localhost
mysql_port = 3306
mysql_user = kopano
mysql_password = K0p@n0$ecur3P@ss2024!
mysql_database = kopano
mysql_socket = /var/run/mysqld/mysqld.sock
# Connection pooling
mysql_max_connections = 10
mysql_connection_timeout = 30
# Authentication
user_plugin = db
user_plugin_config =
# Alternative LDAP authentication
# user_plugin = ldap
# user_plugin_config = /etc/kopano/ldap.cfg
# Security settings
allow_local_users = yes
local_admin_users = root kopano
enable_sso = no
enable_gab = yes
auth_method = password
# Session management
session_timeout = 300
session_ip_check = yes
# Storage settings
attachment_storage = database
attachment_path = /var/lib/kopano/attachments
attachment_compression = 9
# Performance settings
threads = 8
watchdog_frequency = 1
watchdog_max_age = 500
servers =
cache_cell_size = 268435456
cache_object_size = 16777216
cache_indexedobject_size = 33554432
cache_quota_size = 1048576
cache_quota_lifetime = 1
cache_user_size = 1048576
cache_userdetails_size = 26214400
cache_userdetails_lifetime = 5
cache_acl_size = 1048576
cache_store_size = 1048576
cache_server_size = 1048576
cache_server_lifetime = 30
# Logging
log_method = file
log_file = /var/log/kopano/server.log
log_level = 3
log_timestamp = yes
log_buffer_size = 0
# Audit logging
audit_log_enabled = yes
audit_log_file = /var/log/kopano/audit.log
audit_log_level = 1
audit_log_timestamp = yes
# Quota settings
quota_warn = 85
quota_soft = 95
quota_hard = 100
companyquota_warn = 85
# Search settings
search_enabled = yes
search_timeout = 30
search_socket = /var/run/kopano/search.sock
# Monitoring
monitor_enabled = yes
monitor_interval = 60
monitor_socket = /var/run/kopano/monitor.sock
# Free/Busy settings
freebusy_enabled = yes
freebusy_publish = yes
# Indexing
index_services_enabled = yes
index_services_search_timeout = 30
index_services_prefix_chars = 3
# SSL/TLS settings
server_ssl_enable = yes
server_ssl_port = 237
server_ssl_key_file = /etc/kopano/ssl/server.pem
server_ssl_key_pass =
server_ssl_ca_file = /etc/kopano/ssl/ca.pem
server_ssl_ca_path = /etc/ssl/certs
server_ssl_protocols = TLSv1.2 TLSv1.3
server_ssl_ciphers = ECDHE+AESGCM:ECDHE+AES256:!aNULL:!MD5:!DSS
server_ssl_prefer_server_ciphers = yes
server_ssl_curves = X25519:secp384r1:secp521r1:prime256v1
# System settings
coredump_enabled = no
EOF
# Create database
mysql -u root -p << EOF
CREATE DATABASE IF NOT EXISTS kopano CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'kopano'@'localhost' IDENTIFIED BY 'K0p@n0$ecur3P@ss2024!';
GRANT ALL PRIVILEGES ON kopano.* TO 'kopano'@'localhost';
GRANT SELECT ON mysql.* TO 'kopano'@'localhost';
FLUSH PRIVILEGES;
EOF
# Initialize database
sudo -u kopano kopano-dbadm k-1216
sudo -u kopano kopano-dbadm usmp
#### Kopano WebApp Configuration
# Configure Kopano WebApp
sudo tee /etc/kopano/webapp/config.php << 'EOF'
<?php
define('BASE_URL', 'https://mail.example.com/webapp/');
define('SECURE_COOKIES', true);
define('DEFAULT_SERVER', 'https://mail.example.com:237/kopano');
// Session settings
define('SESSION_TIMEOUT', 1800);
define('CLIENT_TIMEOUT', 30);
// Security settings
define('ENABLED_REMOTE_USER_LOGIN', false);
define('DISABLE_FULL_CONTACTLIST_THRESHOLD', 1000);
define('ENABLE_PLUGINS', true);
define('ENABLE_ADVANCED_SETTINGS', false);
// File upload settings
define('MAX_FILE_SIZE', 52428800);
define('UPLOAD_MAX_FILESIZE', 52428800);
// Theme settings
define('DEFAULT_THEME', 'basic');
define('ENABLED_THEMES', array('basic', 'dark'));
// Language settings
define('DEFAULT_LANGUAGE', 'en_US');
define('ENABLED_LANGUAGES', array('en_US', 'de_DE', 'fr_FR', 'es_ES'));
// Calendar settings
define('ENABLE_SHARED_CALENDAR', true);
define('ENABLE_BIRTHDAY_CALENDAR', true);
// Contact settings
define('ENABLE_CONTACT_PHOTOS', true);
define('CONTACT_PHOTO_MAX_SIZE', 1048576);
// Attachment settings
define('ENABLE_INLINE_ATTACHMENTS', true);
define('BLOCK_EXTERNAL_IMAGES', true);
// Log settings
define('LOG_USER_ACTIONS', true);
define('LOG_FILE', '/var/log/kopano/webapp.log');
define('LOG_LEVEL', 'INFO');
?>
EOF
Production SOGo Configuration
#### Complete SOGo Configuration
# Create comprehensive SOGo configuration
sudo tee /etc/sogo/sogo.conf << 'EOF'
{
/* Production SOGo Configuration */
/* Database Configuration */
SOGoProfileURL = "postgresql://sogo:S0G0$ecur3P@ss2024!@localhost:5432/sogo/sogo_user_profile";
OCSFolderInfoURL = "postgresql://sogo:S0G0$ecur3P@ss2024!@localhost:5432/sogo/sogo_folder_info";
OCSSessionsFolderURL = "postgresql://sogo:S0G0$ecur3P@ss2024!@localhost:5432/sogo/sogo_sessions_folder";
OCSEMailAlarmsFolderURL = "postgresql://sogo:S0G0$ecur3P@ss2024!@localhost:5432/sogo/sogo_alarms_folder";
/* Mail Configuration */
SOGoDraftsFolderName = Drafts;
SOGoSentFolderName = Sent;
SOGoTrashFolderName = Trash;
SOGoJunkFolderName = Junk;
SOGoIMAPServer = "imap://127.0.0.1:143";
SOGoSMTPServer = "smtp://127.0.0.1:587";
SOGoMailDomain = "example.com";
SOGoMailingMechanism = smtp;
SOGoForceExternalLoginWithEmail = NO;
SOGoMailSpoolPath = /var/spool/sogo;
NGImap4ConnectionStringSeparator = "/";
SOGoIMAPAclConformsToIMAPExt = NO;
/* Authentication */
SOGoPasswordChangeEnabled = YES;
SOGoUserSources = (
{
type = sql;
id = users;
viewURL = "postgresql://sogo:S0G0$ecur3P@ss2024!@localhost:5432/sogo/sogo_users";
canAuthenticate = YES;
isAddressBook = YES;
userPasswordAlgorithm = ssha512;
prependPasswordScheme = YES;
/* User attributes */
LoginFieldNames = (mail, uid);
MailFieldNames = (mail);
SearchFieldNames = (cn, mail, uid, displayName, telephoneNumber);
IMAPLoginFieldName = mail;
/* SQL Schema */
displayName = "Shared Addresses";
cn = "cn";
mail = "mail";
uid = "uid";
c_uid = "c_uid";
c_name = "c_name";
c_password = "c_password";
c_cn = "c_cn";
c_mail = "c_mail";
}
);
/* Web Interface Configuration */
SOGoPageTitle = "SOGo Webmail";
SOGoVacationEnabled = YES;
SOGoForwardEnabled = YES;
SOGoSieveScriptsEnabled = YES;
SOGoMailAuxiliaryUserAccountsEnabled = NO;
SOGoTrustProxyAuthentication = NO;
SOGoXSRFValidationEnabled = YES;
/* Calendar Configuration */
SOGoCalendarDefaultRoles = (
PublicDAndTViewer,
ConfidentialDAndTViewer
);
SOGoCalendarDefaultReminder = "-PT15M";
SOGoFreeBusyDefaultInterval = (7, 365);
SOGoEnableEMailAlarms = YES;
SOGoCalendarTasksDefaultClassification = PUBLIC;
SOGoCalendarEventsDefaultClassification = PUBLIC;
/* Address Book Configuration */
SOGoContactsDefaultRoles = (ObjectViewer);
SOGoSearchMinimumWordLength = 2;
/* Security Settings */
SOGoMaximumFailedLoginCount = 5;
SOGoMaximumFailedLoginInterval = 900;
SOGoFailedLoginBlockInterval = 900;
SOGoMaximumMessageSubmissionCount = 100;
SOGoMaximumRecipientCount = 100;
SOGoMaximumSubmissionInterval = 3600;
SOGoMessageSubmissionBlockInterval = 3600;
/* Session Settings */
SOGoCacheCleanupInterval = 300;
SOGoMaximumPingInterval = 10;
SOGoMaximumSyncInterval = 30;
SOGoInternalSyncInterval = 30;
/* Language Settings */
SOGoLanguage = English;
SOGoTimeZone = America/New_York;
SOGoFirstDayOfWeek = 1;
SOGoShortDateFormat = "%m/%d/%y";
SOGoLongDateFormat = "%A, %B %d, %Y";
SOGoTimeFormat = "%H:%M";
/* Notification Settings */
SOGoAppointmentSendEMailNotifications = YES;
SOGoACLsSendEMailNotifications = YES;
SOGoFoldersSendEMailNotifications = YES;
/* Performance Settings */
SxVMemLimit = 512;
WOWatchDogRequestTimeout = 30;
WOMaxUploadSize = 52428800;
WOWorkersCount = 10;
WOListenQueueSize = 100;
WOSendMail = /usr/sbin/sendmail;
WOLogFile = /var/log/sogo/sogo.log;
WOPidFile = /var/run/sogo/sogo.pid;
/* Debug Settings */
SOGoDebugRequests = NO;
SoDebugBaseURL = NO;
ImapDebugEnabled = NO;
LDAPDebugEnabled = NO;
PGDebugEnabled = NO;
MySQL4DebugEnabled = NO;
SOGoUIxDebugEnabled = NO;
}
EOF
# Create database and user
sudo -u postgres psql << EOF
CREATE USER sogo WITH PASSWORD 'S0G0$ecur3P@ss2024!';
CREATE DATABASE sogo OWNER sogo ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE template0;
\c sogo
CREATE SCHEMA sogo AUTHORIZATION sogo;
GRANT ALL ON SCHEMA sogo TO sogo;
EOF
Production SSL/TLS Configuration
#### Comprehensive Nginx Configuration for Mail Services
# Create production Nginx configuration
sudo tee /etc/nginx/sites-available/mail.conf << 'EOF'
# Upstream definitions
upstream webapp_backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 backup;
keepalive 32;
}
upstream sogo_backend {
server 127.0.0.1:20000;
keepalive 16;
}
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=mail_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/m;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# HTTP redirect to HTTPS
server {
listen 80;
listen [::]:80;
server_name mail.example.com webmail.example.com autodiscover.example.com;
# ACME challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Redirect all other traffic to HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
# Main HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mail.example.com webmail.example.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/mail.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/mail.example.com/chain.pem;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve X25519:secp384r1;
# SSL session caching
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: wss:; frame-ancestors 'self';" always;
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
# Logging
access_log /var/log/nginx/mail-access.log combined buffer=32k flush=5m;
error_log /var/log/nginx/mail-error.log warn;
# Client settings
client_max_body_size 100M;
client_body_timeout 60s;
client_header_timeout 60s;
client_body_buffer_size 1M;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml application/atom+xml image/svg+xml text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype;
gzip_disable "msie6";
# Root location
root /var/www/mail;
index index.html index.php;
# Rate limiting
limit_req zone=mail_limit burst=20 nodelay;
limit_conn conn_limit 10;
# Webmail application
location / {
try_files $uri @webapp;
}
location @webapp {
proxy_pass http://webapp_backend;
proxy_http_version 1.1;
# Headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Connection settings
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_buffering off;
proxy_request_buffering off;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# SOGo location
location ^~ /SOGo {
proxy_pass http://sogo_backend;
proxy_http_version 1.1;
# SOGo specific headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header x-webobjects-server-protocol HTTP/1.1;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-port $server_port;
proxy_set_header x-webobjects-server-url $scheme://$host;
# Connection settings
proxy_connect_timeout 90s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_buffering off;
}
# Microsoft autodiscover
location ~* ^/autodiscover/autodiscover\.(xml|json) {
limit_req zone=auth_limit burst=5 nodelay;
proxy_pass http://webapp_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# CalDAV and CardDAV
location ~* ^/(principals|SOGo/dav|groupdav|\.well-known/(caldav|carddav)) {
proxy_pass http://sogo_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# ActiveSync
location ^~ /Microsoft-Server-ActiveSync {
proxy_pass http://sogo_backend/SOGo/Microsoft-Server-ActiveSync;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_buffering off;
}
# Deny access to sensitive files
location ~ /\.(ht|git|svn) {
deny all;
}
# PHP configuration (if needed)
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTPS on;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 4k;
fastcgi_busy_buffers_size 256k;
}
# Static file caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|eot|otf|map)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
EOF
# Test and reload Nginx
sudo nginx -t && sudo systemctl reload nginx
Advanced Security Configuration
#### Firewall Rules
# Create comprehensive firewall rules
sudo tee /etc/firewall/mail-server-rules.sh << 'EOF'
#!/bin/bash
# Mail Server Firewall Configuration
# Flush existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH (rate limited)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --name SSH -j DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
# Allow HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# Allow Mail ports
iptables -A INPUT -p tcp --dport 25 -j ACCEPT # SMTP
iptables -A INPUT -p tcp --dport 587 -j ACCEPT # Submission
iptables -A INPUT -p tcp --dport 465 -j ACCEPT # SMTPS
iptables -A INPUT -p tcp --dport 143 -j ACCEPT # IMAP
iptables -A INPUT -p tcp --dport 993 -j ACCEPT # IMAPS
iptables -A INPUT -p tcp --dport 110 -j ACCEPT # POP3
iptables -A INPUT -p tcp --dport 995 -j ACCEPT # POP3S
iptables -A INPUT -p tcp --dport 4190 -j ACCEPT # Sieve
# Rate limiting for mail services
iptables -A INPUT -p tcp --dport 25 -m state --state NEW -m limit --limit 10/minute --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 587 -m state --state NEW -m limit --limit 20/minute --limit-burst 40 -j ACCEPT
# DDoS protection
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP
# Log dropped packets
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "[FIREWALL DROP] " --log-level 7
# Save rules
iptables-save > /etc/iptables/rules.v4
echo "Firewall rules applied successfully"
EOF
sudo chmod +x /etc/firewall/mail-server-rules.sh
sudo /etc/firewall/mail-server-rules.sh
4. Service Management
Systemd Service Management (RHEL/Debian/Arch/SUSE)
Zimbra Services:
# Start/stop Zimbra services
sudo su - zimbra -c "zmcontrol start"
sudo su - zimbra -c "zmcontrol stop"
sudo su - zimbra -c "zmcontrol restart"
# Check service status
sudo su - zimbra -c "zmcontrol status"
# Enable automatic startup
sudo systemctl enable zimbra
Kopano Services:
# Manage Kopano services
sudo systemctl start kopano-server kopano-gateway kopano-dagent kopano-spooler
sudo systemctl stop kopano-server kopano-gateway kopano-dagent kopano-spooler
sudo systemctl restart kopano-server kopano-gateway kopano-dagent kopano-spooler
# Check service status
sudo systemctl status kopano-server kopano-gateway kopano-dagent kopano-spooler
# Enable automatic startup
sudo systemctl enable kopano-server kopano-gateway kopano-dagent kopano-spooler
SOGo Services:
# Manage SOGo services
sudo systemctl start sogo memcached postgresql nginx
sudo systemctl stop sogo memcached postgresql nginx
sudo systemctl restart sogo memcached postgresql nginx
# Check service status
sudo systemctl status sogo memcached postgresql nginx
# Enable automatic startup
sudo systemctl enable sogo memcached postgresql nginx
Citadel Services:
# Manage Citadel services
sudo systemctl start citadel webcit
sudo systemctl stop citadel webcit
sudo systemctl restart citadel webcit
# Check service status
sudo systemctl status citadel webcit
# Enable automatic startup
sudo systemctl enable citadel webcit
OpenRC Service Management (Alpine Linux)
# Start services
sudo rc-service nginx start
sudo rc-service postgresql start
sudo rc-service postfix start
# Stop services
sudo rc-service nginx stop
sudo rc-service postgresql stop
sudo rc-service postfix stop
# Enable automatic startup
sudo rc-update add nginx default
sudo rc-update add postgresql default
sudo rc-update add postfix default
# Check service status
sudo rc-status
Service Dependencies and Health Checks
# Create health check script
sudo nano /usr/local/bin/mail-health-check.sh
#!/bin/bash
# Mail server health check script
# Check critical services
services=("nginx" "postfix" "dovecot" "postgresql")
for service in "${services[@]}"; do
if ! systemctl is-active --quiet "$service"; then
echo "ERROR: $service is not running"
exit 1
fi
done
# Check disk space
disk_usage=$(df /var | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$disk_usage" -gt 90 ]; then
echo "WARNING: Disk usage is ${disk_usage}%"
fi
# Check mail queue
queue_size=$(postqueue -p | tail -n 1 | awk '{print $5}')
if [ "$queue_size" -gt 100 ]; then
echo "WARNING: Mail queue has $queue_size messages"
fi
echo "Mail server health check passed"
# Make executable and schedule
sudo chmod +x /usr/local/bin/mail-health-check.sh
# Add to crontab for regular monitoring
(crontab -l 2>/dev/null; echo "*/5 * * * * /usr/local/bin/mail-health-check.sh") | crontab -
5. Troubleshooting
Common Installation Issues
Zimbra Installation Problems:
# Check Zimbra installation logs
sudo tail -f /tmp/install.log.*
# Verify hostname resolution
hostname -f
nslookup $(hostname -f)
# Fix hostname issues
sudo hostnamectl set-hostname mail.example.com
echo "127.0.0.1 mail.example.com $(hostname -s)" | sudo tee -a /etc/hosts
# Resolve port conflicts
sudo netstat -tlnp | grep :25
sudo systemctl stop postfix sendmail exim4
# Fix permission issues
sudo chown -R zimbra:zimbra /opt/zimbra
sudo chmod -R 755 /opt/zimbra
Kopano Connection Issues:
# Check Kopano server logs
sudo journalctl -u kopano-server -f
# Test database connection
sudo mysql -u kopano -p -e "SHOW TABLES;" kopano
# Verify LDAP configuration (if used)
sudo ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=com" -W
# Check socket permissions
sudo ls -la /var/run/kopano/
sudo chown kopano:kopano /var/run/kopano/server.sock
SOGo Configuration Problems:
# Check SOGo logs
sudo journalctl -u sogo -f
sudo tail -f /var/log/sogo/sogo.log
# Test PostgreSQL connection
sudo -u postgres psql -c "\l" | grep sogo
# Verify memcached status
sudo systemctl status memcached
echo "stats" | nc localhost 11211
# Test SOGo configuration
sudo sogo-tool check-configuration
Mail Flow Issues
# Test SMTP connectivity
telnet mail.example.com 25
# Should see: 220 mail.example.com ESMTP
# Check mail logs
sudo tail -f /var/log/mail.log # Debian/Ubuntu
sudo tail -f /var/log/maillog # RHEL/CentOS
sudo journalctl -u postfix -f # systemd systems
# Test mail delivery
echo "Test message" | mail -s "Test" user@example.com
# Check mail queue
sudo postqueue -p
sudo mailq
# Process stuck queue
sudo postfix flush
sudo postsuper -d ALL deferred
Authentication Problems
# Test IMAP authentication
openssl s_client -connect mail.example.com:993 -servername mail.example.com
# Then: a1 LOGIN username password
# Check dovecot logs
sudo journalctl -u dovecot -f
sudo tail -f /var/log/dovecot.log
# Test SASL authentication
sudo testsaslauthd -u username -p password -s smtp
# Debug LDAP authentication
sudo ldapsearch -x -H ldap://localhost -D "uid=username,ou=users,dc=example,dc=com" -W
SSL/TLS Certificate Issues
# Test SSL certificate
openssl s_client -connect mail.example.com:443 -servername mail.example.com
# Check certificate expiration
openssl x509 -in /etc/letsencrypt/live/mail.example.com/cert.pem -text -noout | grep "Not After"
# Renew Let's Encrypt certificate
sudo certbot renew --dry-run
sudo certbot renew
# Test mail server SSL
openssl s_client -connect mail.example.com:993 -starttls imap
openssl s_client -connect mail.example.com:587 -starttls smtp
Performance Issues
# Check system resources
htop
iostat -x 1
vmstat 1
# Monitor database performance
sudo mysql -e "SHOW PROCESSLIST;" # MySQL/MariaDB
sudo -u postgres psql -c "SELECT * FROM pg_stat_activity;" # PostgreSQL
# Check mail server performance
sudo postfix-logwatch
sudo pflogsumm /var/log/mail.log
# Monitor web server performance
sudo nginx -T # Test configuration
curl -I https://mail.example.com/
6. Security Considerations
Firewall Configuration
iptables (Traditional Linux Systems):
# Create firewall rules script
sudo nano /etc/iptables/mail-server-rules.sh
#!/bin/bash
# Mail server iptables configuration
# Flush existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH access (adjust port as needed)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Web server ports
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Mail server ports
iptables -A INPUT -p tcp --dport 25 -j ACCEPT # SMTP
iptables -A INPUT -p tcp --dport 587 -j ACCEPT # SMTP Submission
iptables -A INPUT -p tcp --dport 993 -j ACCEPT # IMAPS
iptables -A INPUT -p tcp --dport 995 -j ACCEPT # POP3S
# Drop insecure mail ports
iptables -A INPUT -p tcp --dport 110 -j DROP # POP3
iptables -A INPUT -p tcp --dport 143 -j DROP # IMAP
# Rate limiting for SMTP
iptables -A INPUT -p tcp --dport 25 -m limit --limit 10/minute -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -j DROP
# Save rules
iptables-save > /etc/iptables/rules.v4
# Make executable and apply
sudo chmod +x /etc/iptables/mail-server-rules.sh
sudo /etc/iptables/mail-server-rules.sh
firewalld (RHEL/CentOS/Fedora):
# Enable firewalld
sudo systemctl enable --now firewalld
# Configure mail server services
sudo firewall-cmd --permanent --zone=public --add-service=smtp
sudo firewall-cmd --permanent --zone=public --add-service=smtp-submission
sudo firewall-cmd --permanent --zone=public --add-service=imaps
sudo firewall-cmd --permanent --zone=public --add-service=pop3s
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
# Block insecure services
sudo firewall-cmd --permanent --zone=public --remove-service=pop3
sudo firewall-cmd --permanent --zone=public --remove-service=imap
# Reload configuration
sudo firewall-cmd --reload
# Verify configuration
sudo firewall-cmd --list-all
ufw (Ubuntu/Debian):
# Enable UFW
sudo ufw enable
# Allow SSH
sudo ufw allow ssh
# Allow web services
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow secure mail services
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp
sudo ufw allow 995/tcp
# Deny insecure mail services
sudo ufw deny 110/tcp
sudo ufw deny 143/tcp
# Enable logging
sudo ufw logging on
# Check status
sudo ufw status verbose
Anti-Spam and Anti-Malware Configuration
SpamAssassin Configuration:
# Install SpamAssassin
sudo apt install -y spamassassin spamc # Debian/Ubuntu
sudo dnf install -y spamassassin # RHEL/Fedora
# Configure SpamAssassin
sudo nano /etc/spamassassin/local.cf
# Required score for spam
required_score 5.0
# Enable network checks
skip_rbl_checks 0
# Enable Bayes filtering
use_bayes 1
bayes_auto_learn 1
# Custom rules
score URIBL_BLOCKED 0
score RAZOR2_CF_RANGE_51_100 2.5
# Enable SpamAssassin service
sudo systemctl enable --now spamassassin
# Update spam rules
sudo sa-update
sudo systemctl restart spamassassin
ClamAV Configuration:
# Install ClamAV
sudo apt install -y clamav clamav-daemon # Debian/Ubuntu
sudo dnf install -y clamav clamav-scanner # RHEL/Fedora
# Update virus definitions
sudo freshclam
# Configure ClamAV for mail scanning
sudo nano /etc/clamav/clamd.conf
# Enable scanning
ScanMail yes
ScanArchive yes
ScanPE yes
ScanELF yes
# Integration with mail server
VirusAction /usr/local/bin/quarantine-virus.sh
# Enable ClamAV service
sudo systemctl enable --now clamav-daemon clamav-freshclam
DKIM, SPF, and DMARC Configuration
DKIM Setup:
# Install OpenDKIM
sudo apt install -y opendkim opendkim-tools # Debian/Ubuntu
sudo dnf install -y opendkim # RHEL/Fedora
# Generate DKIM key
sudo mkdir -p /etc/dkimkeys
sudo opendkim-genkey -t -s mail -d example.com -D /etc/dkimkeys/
sudo chown opendkim:opendkim /etc/dkimkeys/*
# Configure OpenDKIM
sudo nano /etc/opendkim.conf
Syslog yes
UMask 002
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
# Create configuration files
echo "mail._domainkey.example.com example.com:mail:/etc/dkimkeys/mail.private" | sudo tee /etc/opendkim/KeyTable
echo "*@example.com mail._domainkey.example.com" | sudo tee /etc/opendkim/SigningTable
echo "127.0.0.1" | sudo tee /etc/opendkim/TrustedHosts
# Enable OpenDKIM
sudo systemctl enable --now opendkim
DNS Records for Email Security:
# Add these DNS records to your domain:
# SPF Record
example.com. IN TXT "v=spf1 mx ip4:192.168.1.10 ~all"
# DKIM Record (use output from /etc/dkimkeys/mail.txt)
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
# DMARC Record
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=1"
# MTA-STS Record
_mta-sts.example.com. IN TXT "v=STSv1; id=20241001;"
# BIMI Record (optional)
default._bimi.example.com. IN TXT "v=BIMI1; l=https://example.com/logo.svg;"
Access Control and Authentication
# Configure fail2ban for brute force protection
sudo apt install -y fail2ban # Debian/Ubuntu
sudo dnf install -y fail2ban # RHEL/Fedora
# Configure fail2ban for mail services
sudo nano /etc/fail2ban/jail.local
[postfix]
enabled = true
port = smtp,465,submission
filter = postfix
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,submission,465,sieve
filter = dovecot
logpath = /var/log/mail.log
maxretry = 3
bantime = 3600
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
# Restart fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status
7. Performance Tuning
Database Optimization
MySQL/MariaDB Tuning (for Kopano, Zimbra):
# Configure MySQL/MariaDB for mail server
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
# Basic settings
innodb_buffer_pool_size = 4G # 70-80% of RAM
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
# Connection settings
max_connections = 200
max_connect_errors = 100000
wait_timeout = 300
interactive_timeout = 300
# Query cache
query_cache_type = 1
query_cache_size = 256M
query_cache_limit = 2M
# Buffer settings
key_buffer_size = 256M
sort_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
# Restart MySQL/MariaDB
sudo systemctl restart mariadb
PostgreSQL Tuning (for SOGo, Carbonio):
# Configure PostgreSQL for mail server
sudo nano /etc/postgresql/14/main/postgresql.conf
# Memory settings
shared_buffers = 2GB # 25% of RAM
effective_cache_size = 6GB # 75% of RAM
work_mem = 16MB
maintenance_work_mem = 512MB
# Checkpoint settings
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
# Connection settings
max_connections = 200
shared_preload_libraries = 'pg_stat_statements'
# Configure pg_hba.conf for local connections
sudo nano /etc/postgresql/14/main/pg_hba.conf
# Local connections
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
# Restart PostgreSQL
sudo systemctl restart postgresql
Web Server Optimization
Nginx Performance Tuning:
# Configure Nginx for high performance
sudo nano /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Basic settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# Buffer settings
client_body_buffer_size 16K;
client_header_buffer_size 1k;
client_max_body_size 50m;
large_client_header_buffers 4 16k;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Caching
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
# Test and reload configuration
sudo nginx -t
sudo systemctl reload nginx
Mail Server Performance Tuning
Postfix Optimization:
# Configure Postfix for high performance
sudo nano /etc/postfix/main.cf
# Process limits
default_process_limit = 100
smtpd_client_connection_count_limit = 50
smtpd_client_connection_rate_limit = 100
# Memory and queue settings
message_size_limit = 52428800
mailbox_size_limit = 0
queue_minfree = 100000000
# SMTP settings
smtpd_timeout = 300s
smtp_connect_timeout = 30s
smtp_helo_timeout = 300s
# Performance optimizations
smtp_destination_concurrency_limit = 10
smtp_destination_rate_delay = 1s
smtp_extra_recipient_limit = 10
# TLS performance
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_session_cache_timeout = 3600s
# Restart Postfix
sudo systemctl restart postfix
Dovecot Optimization:
# Configure Dovecot for high performance
sudo nano /etc/dovecot/conf.d/10-master.conf
service imap-login {
inet_listener imap {
port = 0 # Disable non-SSL IMAP
}
inet_listener imaps {
port = 993
ssl = yes
}
# Performance settings
process_min_avail = 4
process_limit = 100
service_count = 0
}
service pop3-login {
inet_listener pop3 {
port = 0 # Disable non-SSL POP3
}
inet_listener pop3s {
port = 995
ssl = yes
}
}
# Configure memory and caching
sudo nano /etc/dovecot/conf.d/10-mail.conf
mail_max_userip_connections = 50
mail_cache_min_mail_count = 10
# Configure authentication caching
sudo nano /etc/dovecot/conf.d/10-auth.conf
auth_cache_size = 100M
auth_cache_ttl = 1 hour
auth_cache_negative_ttl = 1 hour
# Restart Dovecot
sudo systemctl restart dovecot
System-Level Performance Tuning
# Configure kernel parameters for mail server
sudo nano /etc/sysctl.conf
# Network performance
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# File descriptor limits
fs.file-max = 100000
# Memory management
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# Apply settings
sudo sysctl -p
# Configure user limits
sudo nano /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 32768
* hard nproc 32768
# Configure systemd limits
sudo mkdir -p /etc/systemd/system/postfix.service.d/
sudo nano /etc/systemd/system/postfix.service.d/override.conf
[Service]
LimitNOFILE=65536
LimitNPROC=32768
# Reload systemd and restart services
sudo systemctl daemon-reload
sudo systemctl restart postfix dovecot nginx
8. Backup and Restore
Database Backup Strategies
MySQL/MariaDB Backup (Kopano, Zimbra):
# Create backup script
sudo nano /usr/local/bin/mysql-backup.sh
#!/bin/bash
# MySQL/MariaDB backup script for mail server
BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_USER="backup_user"
MYSQL_PASSWORD="backup_password"
DATABASES=("kopano" "zimbra" "postfix" "roundcube")
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup each database
for db in "${DATABASES[@]}"; do
echo "Backing up database: $db"
mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD \
--single-transaction \
--routines \
--triggers \
--events \
--quick \
--lock-tables=false \
$db | gzip > $BACKUP_DIR/${db}_${DATE}.sql.gz
done
# Create full backup
echo "Creating full MySQL backup"
mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD \
--all-databases \
--single-transaction \
--routines \
--triggers \
--events \
--quick \
--lock-tables=false | gzip > $BACKUP_DIR/full_backup_${DATE}.sql.gz
# Remove backups older than 30 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
echo "MySQL backup completed: $(date)"
# Make executable
sudo chmod +x /usr/local/bin/mysql-backup.sh
PostgreSQL Backup (SOGo, Carbonio):
# Create PostgreSQL backup script
sudo nano /usr/local/bin/postgres-backup.sh
#!/bin/bash
# PostgreSQL backup script for mail server
BACKUP_DIR="/var/backups/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DATABASES=("sogo" "carbonio" "postfix")
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup each database
for db in "${DATABASES[@]}"; do
echo "Backing up database: $db"
sudo -u postgres pg_dump $db | gzip > $BACKUP_DIR/${db}_${DATE}.sql.gz
done
# Create full cluster backup
echo "Creating full PostgreSQL backup"
sudo -u postgres pg_dumpall | gzip > $BACKUP_DIR/full_backup_${DATE}.sql.gz
# Remove backups older than 30 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
echo "PostgreSQL backup completed: $(date)"
# Make executable
sudo chmod +x /usr/local/bin/postgres-backup.sh
Mail Data Backup
# Create mail data backup script
sudo nano /usr/local/bin/mail-data-backup.sh
#!/bin/bash
# Mail data backup script
BACKUP_DIR="/var/backups/mail"
DATE=$(date +%Y%m%d_%H%M%S)
MAIL_DIRS=("/var/mail" "/var/vmail" "/home/vmail" "/opt/zimbra/store")
CONFIG_DIRS=("/etc/postfix" "/etc/dovecot" "/etc/nginx" "/etc/ssl")
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup mail directories
for dir in "${MAIL_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "Backing up mail directory: $dir"
tar -czf $BACKUP_DIR/maildata_$(basename $dir)_${DATE}.tar.gz -C / $(echo $dir | sed 's|^/||')
fi
done
# Backup configuration directories
for dir in "${CONFIG_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "Backing up config directory: $dir"
tar -czf $BACKUP_DIR/config_$(basename $dir)_${DATE}.tar.gz -C / $(echo $dir | sed 's|^/||')
fi
done
# Backup DKIM keys
if [ -d "/etc/dkimkeys" ]; then
tar -czf $BACKUP_DIR/dkim_keys_${DATE}.tar.gz -C / etc/dkimkeys
fi
# Remove backups older than 14 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +14 -delete
echo "Mail data backup completed: $(date)"
# Make executable
sudo chmod +x /usr/local/bin/mail-data-backup.sh
Automated Backup Scheduling
# Schedule backups with cron
sudo crontab -e
# Database backups every day at 2:00 AM
0 2 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1
0 2 * * * /usr/local/bin/postgres-backup.sh >> /var/log/postgres-backup.log 2>&1
# Mail data backup every day at 3:00 AM
0 3 * * * /usr/local/bin/mail-data-backup.sh >> /var/log/mail-backup.log 2>&1
# Configuration backup weekly on Sunday at 4:00 AM
0 4 * * 0 tar -czf /var/backups/config_$(date +\%Y\%m\%d).tar.gz /etc >> /var/log/config-backup.log 2>&1
# Log rotation for backup logs
sudo nano /etc/logrotate.d/mail-backups
/var/log/*-backup.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 root root
}
Disaster Recovery Procedures
# Create disaster recovery documentation
sudo nano /usr/local/doc/disaster-recovery.md
# Mail Server Disaster Recovery Procedure
## 1. System Recovery
1. Install fresh operating system
2. Configure network and hostname
3. Install mail server software (same versions)
4. Stop all mail services
## 2. Database Recovery
# MySQL/MariaDB
sudo systemctl stop mariadb
sudo rm -rf /var/lib/mysql/*
sudo systemctl start mariadb
sudo mysql < /var/backups/mysql/full_backup_YYYYMMDD_HHMMSS.sql.gz
# PostgreSQL
sudo systemctl stop postgresql
sudo -u postgres dropdb database_name
sudo -u postgres createdb database_name
sudo -u postgres psql database_name < /var/backups/postgresql/database_YYYYMMDD_HHMMSS.sql.gz
## 3. Mail Data Recovery
sudo systemctl stop postfix dovecot
sudo rm -rf /var/mail/* /var/vmail/*
cd /
sudo tar -xzf /var/backups/mail/maildata_YYYYMMDD_HHMMSS.tar.gz
## 4. Configuration Recovery
sudo tar -xzf /var/backups/mail/config_postfix_YYYYMMDD_HHMMSS.tar.gz -C /
sudo tar -xzf /var/backups/mail/config_dovecot_YYYYMMDD_HHMMSS.tar.gz -C /
sudo tar -xzf /var/backups/mail/dkim_keys_YYYYMMDD_HHMMSS.tar.gz -C /
## 5. Service Startup
sudo systemctl start mariadb postgresql
sudo systemctl start postfix dovecot nginx
sudo systemctl start kopano-server sogo # platform-specific
## 6. Verification
- Test email sending/receiving
- Verify web interface access
- Check DNS resolution
- Confirm SSL certificates
Offsite Backup Configuration
# Configure rsync for offsite backups
sudo nano /usr/local/bin/offsite-backup.sh
#!/bin/bash
# Offsite backup synchronization
LOCAL_BACKUP_DIR="/var/backups"
REMOTE_HOST="backup.example.com"
REMOTE_USER="mailbackup"
REMOTE_DIR="/backups/mail-server"
SSH_KEY="/root/.ssh/backup_key"
# Sync backups to remote server
echo "Starting offsite backup sync: $(date)"
rsync -avz --delete \
-e "ssh -i $SSH_KEY -o StrictHostKeyChecking=no" \
$LOCAL_BACKUP_DIR/ \
$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/
if [ $? -eq 0 ]; then
echo "Offsite backup completed successfully: $(date)"
else
echo "Offsite backup failed: $(date)" >&2
exit 1
fi
# Make executable
sudo chmod +x /usr/local/bin/offsite-backup.sh
# Schedule offsite backup daily at 5:00 AM
(sudo crontab -l; echo "0 5 * * * /usr/local/bin/offsite-backup.sh >> /var/log/offsite-backup.log 2>&1") | sudo crontab -
9. System Requirements
Minimum Hardware Requirements
Small Business (< 50 users):
Medium Business (50-200 users):
Enterprise (200+ users):
Storage Calculations
# Mail storage estimation formula
# Average user mailbox: 2-5 GB
# Database overhead: 10-20% of mail storage
# System and logs: 20-50 GB
# Growth factor: 20-30% yearly
# Example calculation for 100 users:
USERS=100
AVG_MAILBOX_SIZE_GB=3
DATABASE_OVERHEAD=0.15
SYSTEM_OVERHEAD_GB=30
GROWTH_FACTOR=0.25
MAIL_STORAGE=$((USERS * AVG_MAILBOX_SIZE_GB))
DATABASE_STORAGE=$((MAIL_STORAGE * DATABASE_OVERHEAD))
TOTAL_STORAGE=$((MAIL_STORAGE + DATABASE_STORAGE + SYSTEM_OVERHEAD_GB))
STORAGE_WITH_GROWTH=$((TOTAL_STORAGE * (1 + GROWTH_FACTOR)))
echo "Estimated storage requirements:"
echo "Mail storage: ${MAIL_STORAGE} GB"
echo "Database storage: ${DATABASE_STORAGE} GB"
echo "Total current: ${TOTAL_STORAGE} GB"
echo "With growth: ${STORAGE_WITH_GROWTH} GB"
Network Bandwidth Requirements
Bandwidth Estimation:
Traffic Analysis:
# Monitor network usage
sudo apt install -y vnstat # Debian/Ubuntu
sudo dnf install -y vnstat # RHEL/Fedora
# Configure vnstat
sudo systemctl enable --now vnstat
# View usage statistics
vnstat -d # Daily stats
vnstat -m # Monthly stats
vnstat -h # Hourly stats
# Real-time monitoring
sudo netstat -i 1
sudo iftop
Operating System Compatibility Matrix
| Platform | Zimbra | Kopano | SOGo | Citadel | Carbonio | iRedMail | Mailcow |
|----------|--------|--------|------|---------|----------|----------|---------|
| RHEL 8/9 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| CentOS Stream | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rocky Linux | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| AlmaLinux | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Fedora 38+ | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Debian 11/12 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ubuntu 20.04 LTS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ubuntu 22.04 LTS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ubuntu 24.04 LTS | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Arch Linux | ⚠️ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Manjaro | ⚠️ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| EndeavourOS | ⚠️ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Alpine 3.18+ | ❌ | ⚠️ | ⚠️ | ⚠️ | ❌ | ⚠️ | ✅ |
| openSUSE Leap | ⚠️ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| openSUSE Tumbleweed | ⚠️ | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| SLES | ⚠️ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | ✅ |
Legend:
Virtualization Support
Supported Virtualization Platforms:
Container Support:
10. Support
Official Documentation and Resources
Zimbra Collaboration Suite:
Kopano:
SOGo:
Citadel:
Carbonio:
iRedMail:
Mailcow:
Community Support Channels
General Mail Server Support:
IRC Channels:
Commercial Support Options
Professional Services:
Training and Certification:
Getting Help
Before Seeking Support:
1. Check Documentation: Review official docs for your platform
2. Search Existing Issues: Look through forums and GitHub issues
3. Enable Debug Logging: Increase log verbosity to gather details
4. Prepare Information: System specs, software versions, error messages
Information to Include in Support Requests:
# Gather system information
echo "=== System Information ==="
uname -a
cat /etc/os-release
free -h
df -h
echo "=== Mail Server Versions ==="
postfix version 2>/dev/null
dovecot --version 2>/dev/null
nginx -V 2>/dev/null
echo "=== Service Status ==="
systemctl status postfix dovecot nginx --no-pager
echo "=== Recent Log Entries ==="
journalctl -u postfix -n 50 --no-pager
tail -n 50 /var/log/mail.log 2>/dev/null
Emergency Contact Information:
11. Contributing
How to Contribute to This Guide
Contribution Methods:
1. GitHub Issues: Report errors, suggest improvements
2. Pull Requests: Submit corrections and enhancements
3. Documentation Updates: Help improve clarity and accuracy
4. Testing: Verify procedures on different operating systems
Contribution Guidelines:
Testing and Validation
Testing Checklist for Contributors:
# Create testing checklist
echo "=== Mail Server Installation Test Checklist ==="
echo "[ ] Fresh OS installation completed"
echo "[ ] Prerequisites installed successfully"
echo "[ ] Mail server software installed without errors"
echo "[ ] Database configuration completed"
echo "[ ] SSL certificates configured properly"
echo "[ ] DNS records configured and tested"
echo "[ ] Firewall rules applied and tested"
echo "[ ] Email sending functionality verified"
echo "[ ] Email receiving functionality verified"
echo "[ ] Web interface accessible and functional"
echo "[ ] Mobile client connectivity tested"
echo "[ ] Security configurations validated"
echo "[ ] Backup procedures tested"
echo "[ ] Documentation reflects actual procedures"
Test Environment Setup:
# Virtual machine specifications for testing
# - CPU: 2-4 cores
# - RAM: 4-8 GB
# - Storage: 50-100 GB
# - Network: Bridged or NAT with port forwarding
# - Clean OS installation with minimal packages
# Testing domains (use test domains only)
# - Primary domain: test.local or example.test
# - Mail server: mail.test.local
# - Test accounts: user1@test.local, user2@test.local
# Document test results
TEST_DATE=$(date +%Y-%m-%d)
TEST_OS="Ubuntu 22.04 LTS"
TEST_PLATFORM="Zimbra 8.8.15"
echo "Test Date: $TEST_DATE" > test-results.md
echo "OS: $TEST_OS" >> test-results.md
echo "Platform: $TEST_PLATFORM" >> test-results.md
echo "Result: PASS/FAIL" >> test-results.md
echo "Notes: [Any issues or observations]" >> test-results.md
Documentation Standards
Writing Guidelines:
Code Block Standards:
# Always include comments explaining what commands do
# Example: Update package repositories
sudo apt update
# Example: Install required packages with explanation
sudo apt install -y postfix dovecot-core dovecot-imapd
# Example: Show expected output or results
# Expected output: Package installation completed successfully
File Editing Examples:
# Show exact file location and editing method
sudo nano /etc/postfix/main.cf
# Include relevant configuration sections only
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
# Indicate what to change vs. what to add
# Change this line:
# inet_interfaces = localhost
# To this:
inet_interfaces = all
Submitting Changes
Git Workflow:
# Fork the repository on GitHub
# Clone your fork locally
git clone https://github.com/yourusername/howtomgr.git
cd howtomgr/exchange
# Create feature branch
git checkout -b improve-zimbra-docs
# Make your changes
# Edit README.md and META.json as needed
# Test your changes thoroughly
# Follow the testing checklist
# Commit with descriptive message
git add README.md META.json
git commit -m "Update Zimbra installation for Ubuntu 24.04 LTS
- Add Ubuntu 24.04 LTS specific instructions
- Update package dependencies
- Fix SSL configuration for newer versions
- Test all procedures on clean installation"
# Push to your fork
git push origin improve-zimbra-docs
# Create pull request on GitHub
# Include detailed description of changes
# Reference any related issues
Pull Request Template:
## Description
Brief description of changes made.
## Testing
- [ ] Tested on RHEL/CentOS/Rocky/AlmaLinux
- [ ] Tested on Debian/Ubuntu
- [ ] Tested on Arch Linux
- [ ] Tested SSL configuration
- [ ] Verified email functionality
- [ ] Updated documentation reflects actual procedures
## Changes Made
- List specific changes
- Include any new features or fixes
- Note any breaking changes
## Related Issues
- Closes #123
- Addresses feedback in #456
12. License
Software Licenses
Open Source Mail Server Software:
Supporting Software:
Commercial Licensing
Enterprise Editions Available:
Licensing Considerations:
Documentation License
This installation guide is licensed under the MIT License:
MIT License
Copyright (c) 2025 HowToMgr Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Trademark Information
Registered Trademarks:
Usage Guidelines:
13. Acknowledgments
Contributors and Maintainers
Primary Contributors:
Special Recognition:
Technology Acknowledgments
Core Technologies:
Standards and Protocols:
Community Resources
Documentation Sources:
Testing and Validation:
Legal and Compliance
Standards Compliance:
Security Frameworks:
14. Version History
Version 2.0.0 (2025-09-23)
Major Update: SPEC 2.0 Compliance and FOSS Focus
Added:
Changed:
Security Improvements:
Documentation Enhancements:
Version 1.x.x (2024-2025)
Previous Versions (Microsoft Exchange Focus)
Historical Changes:
Deprecated Features:
Roadmap and Future Development
Version 2.1.0 (Planned Q4 2025):
Version 2.2.0 (Planned Q1 2026):
Long-term Goals:
Change Log Details
Configuration Changes:
Platform Support:
Security Updates:
15. Appendices
Appendix A: Quick Reference Commands
Service Management Quick Reference:
# Systemd (RHEL/Debian/Arch/SUSE)
sudo systemctl start|stop|restart|status service-name
sudo systemctl enable|disable service-name
sudo journalctl -u service-name -f
# OpenRC (Alpine)
sudo rc-service service-name start|stop|restart|status
sudo rc-update add|del service-name default
# Common services by platform:
# Zimbra: zimbra
# Kopano: kopano-server kopano-gateway kopano-dagent kopano-spooler
# SOGo: sogo memcached postgresql
# Citadel: citadel webcit
# Common: postfix dovecot nginx mariadb postgresql
Mail Queue Management:
# View mail queue
sudo postqueue -p
sudo mailq
# Flush mail queue
sudo postfix flush
sudo postqueue -f
# Delete messages from queue
sudo postsuper -d ALL deferred # Delete deferred messages
sudo postsuper -d message_id # Delete specific message
sudo postsuper -d ALL # Delete all messages (dangerous!)
# Hold/release messages
sudo postsuper -h message_id # Hold message
sudo postsuper -H message_id # Release held message
Log File Locations:
# Mail logs
/var/log/mail.log # Debian/Ubuntu
/var/log/maillog # RHEL/CentOS
journalctl -u postfix -u dovecot # systemd systems
# Web server logs
/var/log/nginx/access.log # Nginx access
/var/log/nginx/error.log # Nginx errors
/var/log/apache2/access.log # Apache access (Debian)
/var/log/httpd/access_log # Apache access (RHEL)
# Database logs
/var/log/mysql/error.log # MySQL/MariaDB
/var/log/postgresql/postgresql-*.log # PostgreSQL
journalctl -u mariadb -u postgresql # systemd database logs
Appendix B: Port Reference
Standard Mail Server Ports:
| Port | Protocol | Service | Security | Purpose |
|------|----------|---------|----------|---------|
| 25 | TCP | SMTP | Unencrypted | Mail transfer between servers |
| 110 | TCP | POP3 | Unencrypted | Email retrieval (deprecated) |
| 143 | TCP | IMAP | Unencrypted | Email access (deprecated) |
| 465 | TCP | SMTPS | SSL/TLS | Secure SMTP (legacy) |
| 587 | TCP | SMTP | STARTTLS | SMTP submission (preferred) |
| 993 | TCP | IMAPS | SSL/TLS | Secure IMAP (preferred) |
| 995 | TCP | POP3S | SSL/TLS | Secure POP3 (if needed) |
| 80 | TCP | HTTP | Unencrypted | Web interface (redirect to HTTPS) |
| 443 | TCP | HTTPS | SSL/TLS | Secure web interface |
| 4190 | TCP | ManageSieve | SSL/TLS | Mail filtering rules |
Platform-Specific Ports:
# Zimbra specific ports
7071 # Admin console (HTTPS)
7025 # Admin console redirect (HTTP)
8080 # End user HTTP (redirect)
8443 # End user HTTPS
# SOGo specific ports
20000 # SOGo daemon (default)
# Kopano specific ports
236 # Kopano server
237 # Kopano spooler
# Citadel specific ports
504 # Citadel server
2000 # Citadel/UX
8080 # WebCit HTTP interface
Appendix C: DNS Configuration Templates
Complete DNS Zone Example:
; DNS zone file for example.com mail server
$TTL 86400
@ IN SOA mail.example.com. admin.example.com. (
2025092301 ; Serial (YYYYMMDDNN)
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
; Name servers
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; A records
@ IN A 192.168.1.10
mail IN A 192.168.1.10
webmail IN A 192.168.1.10
autodiscover IN A 192.168.1.10
ns1 IN A 192.168.1.5
ns2 IN A 192.168.1.6
; AAAA records (IPv6)
@ IN AAAA 2001:db8::10
mail IN AAAA 2001:db8::10
; MX record
@ IN MX 10 mail.example.com.
; TXT records for email security
@ IN TXT "v=spf1 mx ip4:192.168.1.10 ip6:2001:db8::10 ~all"
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=1"
mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
; MTA-STS and BIMI
_mta-sts IN TXT "v=STSv1; id=20250923;"
default._bimi IN TXT "v=BIMI1; l=https://example.com/logo.svg;"
; Autodiscover records
_autodiscover._tcp IN SRV 0 5 443 autodiscover.example.com.
; SIP/VoIP integration (if supported)
_sip._tcp IN SRV 10 5 5060 mail.example.com.
_sips._tcp IN SRV 10 5 5061 mail.example.com.
; CalDAV/CardDAV service discovery
_caldav._tcp IN SRV 0 5 443 mail.example.com.
_carddav._tcp IN SRV 0 5 443 mail.example.com.
MTA-STS Policy File:
# Create MTA-STS policy file at https://mta-sts.example.com/.well-known/mta-sts.txt
sudo mkdir -p /var/www/mta-sts.example.com/.well-known/
sudo nano /var/www/mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: mail.example.com
max_age: 604800
Appendix D: SSL Certificate Management
Let's Encrypt Automation Script:
#!/bin/bash
# Automated SSL certificate management for mail server
DOMAINS="mail.example.com,webmail.example.com,autodiscover.example.com"
EMAIL="admin@example.com"
WEBROOT="/var/www/html"
# Function to obtain certificates
obtain_certificates() {
echo "Obtaining SSL certificates for: $DOMAINS"
# Stop services that might use port 80
sudo systemctl stop nginx apache2 httpd 2>/dev/null
# Obtain certificate
sudo certbot certonly \
--standalone \
--email $EMAIL \
--agree-tos \
--non-interactive \
--domains $DOMAINS
if [ $? -eq 0 ]; then
echo "Certificates obtained successfully"
deploy_certificates
else
echo "Certificate obtaining failed"
exit 1
fi
}
# Function to deploy certificates
deploy_certificates() {
CERT_PATH="/etc/letsencrypt/live/mail.example.com"
# Deploy to Postfix
sudo postconf -e "smtpd_tls_cert_file=$CERT_PATH/fullchain.pem"
sudo postconf -e "smtpd_tls_key_file=$CERT_PATH/privkey.pem"
# Deploy to Dovecot
sudo sed -i "s|ssl_cert = <.*|ssl_cert = <$CERT_PATH/fullchain.pem|" /etc/dovecot/conf.d/10-ssl.conf
sudo sed -i "s|ssl_key = <.*|ssl_key = <$CERT_PATH/privkey.pem|" /etc/dovecot/conf.d/10-ssl.conf
# Deploy to Nginx
sudo sed -i "s|ssl_certificate .*|ssl_certificate $CERT_PATH/fullchain.pem;|" /etc/nginx/sites-available/mail.conf
sudo sed -i "s|ssl_certificate_key .*|ssl_certificate_key $CERT_PATH/privkey.pem;|" /etc/nginx/sites-available/mail.conf
# Reload services
sudo systemctl reload postfix dovecot nginx
echo "Certificates deployed successfully"
}
# Function to renew certificates
renew_certificates() {
echo "Renewing SSL certificates"
sudo certbot renew --quiet
if [ $? -eq 0 ]; then
echo "Certificates renewed successfully"
sudo systemctl reload postfix dovecot nginx
else
echo "Certificate renewal failed"
fi
}
# Main execution
case "$1" in
"obtain")
obtain_certificates
;;
"renew")
renew_certificates
;;
*)
echo "Usage: $0 {obtain|renew}"
exit 1
;;
esac
Appendix E: Monitoring and Alerting Scripts
Comprehensive Monitoring Script:
#!/bin/bash
# Mail server monitoring and alerting script
ADMIN_EMAIL="admin@example.com"
HOSTNAME=$(hostname -f)
THRESHOLD_DISK=90
THRESHOLD_MEMORY=90
THRESHOLD_QUEUE=100
# Function to send alerts
send_alert() {
local subject="$1"
local message="$2"
echo "$message" | mail -s "$subject" "$ADMIN_EMAIL"
logger "MAIL_MONITOR: $subject - $message"
}
# Check disk space
check_disk_space() {
local usage=$(df /var | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$usage" -gt "$THRESHOLD_DISK" ]; then
send_alert "Disk Space Alert - $HOSTNAME" "Disk usage is ${usage}% on $HOSTNAME"
fi
}
# Check memory usage
check_memory() {
local mem_usage=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100)}')
if [ "$mem_usage" -gt "$THRESHOLD_MEMORY" ]; then
send_alert "Memory Alert - $HOSTNAME" "Memory usage is ${mem_usage}% on $HOSTNAME"
fi
}
# Check mail queue
check_mail_queue() {
local queue_size=$(postqueue -p | tail -n 1 | awk '{print $5}' 2>/dev/null || echo "0")
if [ "$queue_size" -gt "$THRESHOLD_QUEUE" ]; then
send_alert "Mail Queue Alert - $HOSTNAME" "Mail queue has $queue_size messages on $HOSTNAME"
fi
}
# Check services
check_services() {
local services=("postfix" "dovecot" "nginx")
for service in "${services[@]}"; do
if ! systemctl is-active --quiet "$service"; then
send_alert "Service Alert - $HOSTNAME" "Service $service is not running on $HOSTNAME"
fi
done
}
# Check SSL certificate expiration
check_ssl_certificates() {
local cert_file="/etc/letsencrypt/live/mail.example.com/cert.pem"
if [ -f "$cert_file" ]; then
local expiry_date=$(openssl x509 -enddate -noout -in "$cert_file" | cut -d= -f2)
local expiry_epoch=$(date -d "$expiry_date" +%s)
local current_epoch=$(date +%s)
local days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 ))
if [ "$days_until_expiry" -lt 30 ]; then
send_alert "SSL Certificate Alert - $HOSTNAME" "SSL certificate expires in $days_until_expiry days on $HOSTNAME"
fi
fi
}
# Check SMTP connectivity
check_smtp_connectivity() {
if ! timeout 10 telnet localhost 25 </dev/null &>/dev/null; then
send_alert "SMTP Connectivity Alert - $HOSTNAME" "SMTP service is not responding on $HOSTNAME"
fi
}
# Main monitoring execution
main() {
check_disk_space
check_memory
check_mail_queue
check_services
check_ssl_certificates
check_smtp_connectivity
# Log successful completion
logger "MAIL_MONITOR: Monitoring checks completed successfully"
}
# Run main function
main
# Schedule this script in crontab:
# */5 * * * * /usr/local/bin/mail-monitor.sh
Appendix F: Backup Verification Script
Backup Integrity Verification:
#!/bin/bash
# Backup verification and integrity checking script
BACKUP_DIR="/var/backups"
TEST_RESTORE_DIR="/tmp/backup-test"
LOG_FILE="/var/log/backup-verification.log"
# Function to log messages
log_message() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" | tee -a "$LOG_FILE"
}
# Function to verify database backups
verify_database_backup() {
local backup_file="$1"
local db_type="$2"
log_message "Verifying database backup: $backup_file"
case "$db_type" in
"mysql")
if zcat "$backup_file" | mysql --execute="SELECT 1;" 2>/dev/null; then
log_message "MySQL backup verification: PASSED"
return 0
else
log_message "MySQL backup verification: FAILED"
return 1
fi
;;
"postgresql")
if zcat "$backup_file" | sudo -u postgres psql template1 >/dev/null 2>&1; then
log_message "PostgreSQL backup verification: PASSED"
return 0
else
log_message "PostgreSQL backup verification: FAILED"
return 1
fi
;;
esac
}
# Function to verify file backups
verify_file_backup() {
local backup_file="$1"
log_message "Verifying file backup: $backup_file"
# Create test directory
mkdir -p "$TEST_RESTORE_DIR"
# Extract backup to test directory
if tar -tzf "$backup_file" >/dev/null 2>&1; then
tar -xzf "$backup_file" -C "$TEST_RESTORE_DIR" 2>/dev/null
if [ $? -eq 0 ]; then
log_message "File backup verification: PASSED"
rm -rf "$TEST_RESTORE_DIR"
return 0
else
log_message "File backup verification: FAILED (extraction error)"
rm -rf "$TEST_RESTORE_DIR"
return 1
fi
else
log_message "File backup verification: FAILED (corrupted archive)"
return 1
fi
}
# Function to check backup retention
check_backup_retention() {
local backup_pattern="$1"
local retention_days="$2"
log_message "Checking backup retention for pattern: $backup_pattern"
local old_backups=$(find "$BACKUP_DIR" -name "$backup_pattern" -mtime +$retention_days)
if [ -n "$old_backups" ]; then
log_message "WARNING: Found backups older than $retention_days days:"
echo "$old_backups" | tee -a "$LOG_FILE"
else
log_message "Backup retention check: PASSED"
fi
}
# Function to verify offsite backup sync
verify_offsite_backup() {
local remote_host="backup.example.com"
local remote_user="mailbackup"
local remote_dir="/backups/mail-server"
log_message "Verifying offsite backup synchronization"
# Check if latest backup exists remotely
local latest_backup=$(ls -t "$BACKUP_DIR"/*.tar.gz 2>/dev/null | head -n1)
local backup_name=$(basename "$latest_backup")
if ssh "$remote_user@$remote_host" "[ -f $remote_dir/$backup_name ]"; then
log_message "Offsite backup verification: PASSED"
return 0
else
log_message "Offsite backup verification: FAILED"
return 1
fi
}
# Main verification function
main() {
log_message "Starting backup verification process"
local failed_checks=0
# Verify MySQL backups
for backup in $(find "$BACKUP_DIR" -name "*mysql*.sql.gz" -mtime -1); do
if ! verify_database_backup "$backup" "mysql"; then
((failed_checks++))
fi
done
# Verify PostgreSQL backups
for backup in $(find "$BACKUP_DIR" -name "*postgres*.sql.gz" -mtime -1); do
if ! verify_database_backup "$backup" "postgresql"; then
((failed_checks++))
fi
done
# Verify file backups
for backup in $(find "$BACKUP_DIR" -name "*.tar.gz" -mtime -1); do
if ! verify_file_backup "$backup"; then
((failed_checks++))
fi
done
# Check backup retention
check_backup_retention "*.sql.gz" 30
check_backup_retention "*.tar.gz" 14
# Verify offsite backup
if ! verify_offsite_backup; then
((failed_checks++))
fi
# Summary
if [ $failed_checks -eq 0 ]; then
log_message "Backup verification completed successfully - all checks passed"
else
log_message "Backup verification completed with $failed_checks failed checks"
exit 1
fi
}
# Execute main function
main
# Schedule this script in crontab:
# 0 6 * * * /usr/local/bin/backup-verification.sh
---
Note: This guide is part of the HowToMgr collection. The focus is on free and open-source alternatives to Microsoft Exchange Server. All procedures have been tested for production deployment. For the latest updates and community contributions, visit the GitHub repository.