Setup Mail Server Monitoring with Postfix on Ubuntu VPS

Setting Up Postfix Mail Server Monitoring on Ubuntu
Mail delivery issues cost businesses customers and revenue. When your VPS handles email for multiple domains or processes high message volumes, you need active monitoring to catch problems before they impact service.
This guide shows you how to setup mail server monitoring for Postfix on Ubuntu VPS. You'll configure log monitoring, queue alerts, and performance tracking that keeps your email service running smoothly.
Whether you're running a small business email server or managing client domains on Hostperl VPS hosting, these techniques prevent email disasters.
Prerequisites and System Requirements
Before starting this monitoring setup, ensure your Ubuntu VPS meets these requirements:
- Ubuntu 20.04 LTS or Ubuntu 22.04 LTS
- Postfix already installed and configured
- Root or sudo access to your server
- At least 1GB RAM and 10GB available storage
- Python 3 installed (comes with Ubuntu by default)
Your Postfix service should be actively handling mail. If you need to configure basic email authentication first, check our DKIM setup guide for essential security.
Update your system packages before proceeding:
sudo apt update && sudo apt upgrade -y
Install Required Monitoring Packages
Start by installing the monitoring tools you'll need. These packages provide log analysis, alerting, and performance tracking capabilities.
sudo apt install mailutils logwatch pflogsumm postfix-policyd-spf-python -y
Install additional Python packages for custom monitoring scripts:
sudo apt install python3-pip python3-smtplib python3-email -y
pip3 install psutil requests
The `pflogsumm` package analyzes Postfix logs and generates detailed reports. The `logwatch` tool provides daily email summaries of system activity.
Verify the installations completed successfully:
which pflogsumm
which logwatch
python3 --version
Configure Postfix Log Monitoring
Postfix logs contain crucial information about mail delivery, rejections, and performance. Configure enhanced logging to capture the details you need for monitoring.
Edit the Postfix main configuration file:
sudo nano /etc/postfix/main.cf
Add or modify these logging parameters:
# Enhanced logging for monitoring
smtpd_tls_loglevel = 1
smtp_tls_loglevel = 1
notify_classes = resource, software, delay, bounce
delay_warning_time = 4h
maximal_queue_lifetime = 5d
bounce_queue_lifetime = 5d
Configure log rotation to prevent disk space issues. Create a new logrotate configuration:
sudo nano /etc/logrotate.d/postfix-monitoring
Add this configuration:
/var/log/mail.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 syslog adm
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
Restart Postfix to apply the logging changes:
sudo systemctl restart postfix
Setup Mail Queue Monitoring Alerts
Mail queue buildup indicates delivery problems. Create a monitoring script that checks queue sizes and sends alerts when thresholds are exceeded.
Create the queue monitoring script:
sudo nano /usr/local/bin/mail_queue_monitor.py
Add this Python script:
#!/usr/bin/env python3
import subprocess
import sys
import smtplib
from email.mime.text import MIMEText
from datetime import datetime
# Configuration
QUEUE_WARNING_THRESHOLD = 50
QUEUE_CRITICAL_THRESHOLD = 100
ALERT_EMAIL = "admin@yourdomain.com"
SMTP_SERVER = "localhost"
def get_queue_size():
try:
result = subprocess.run(['postqueue', '-p'], capture_output=True, text=True)
lines = result.stdout.strip().split('\n')
if len(lines) <= 1:
return 0
# Count actual mail entries (exclude header/footer)
count = len([line for line in lines[1:] if line.strip() and not line.startswith('--')])
return count
except Exception as e:
print(f"Error getting queue size: {e}")
return -1
def send_alert(subject, message):
try:
msg = MIMEText(message)
msg['Subject'] = subject
msg['From'] = f"postfix-monitor@{subprocess.getoutput('hostname')}"
msg['To'] = ALERT_EMAIL
with smtplib.SMTP(SMTP_SERVER) as server:
server.send_message(msg)
except Exception as e:
print(f"Failed to send alert: {e}")
def main():
queue_size = get_queue_size()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if queue_size >= QUEUE_CRITICAL_THRESHOLD:
message = f"CRITICAL: Mail queue has {queue_size} messages at {timestamp}\n"
message += "Immediate investigation required."
send_alert("CRITICAL: Mail Queue Alert", message)
sys.exit(2)
elif queue_size >= QUEUE_WARNING_THRESHOLD:
message = f"WARNING: Mail queue has {queue_size} messages at {timestamp}\n"
message += "Monitor for continued growth."
send_alert("WARNING: Mail Queue Alert", message)
sys.exit(1)
else:
print(f"Queue OK: {queue_size} messages at {timestamp}")
sys.exit(0)
if __name__ == "__main__":
main()
Make the script executable:
sudo chmod +x /usr/local/bin/mail_queue_monitor.py
Update the alert email address in the script with your actual email:
sudo sed -i 's/admin@yourdomain.com/your-email@domain.com/g' /usr/local/bin/mail_queue_monitor.py
Configure Performance Metrics Collection
Track key performance indicators for your mail server. This script collects delivery rates, connection counts, and response times.
Create the performance monitoring script:
sudo nano /usr/local/bin/mail_performance_monitor.py
Add this comprehensive monitoring script:
#!/usr/bin/env python3
import subprocess
import json
import time
from datetime import datetime, timedelta
import re
def get_delivery_stats():
"""Parse recent mail logs for delivery statistics"""
try:
# Get logs from last hour
result = subprocess.run([
'journalctl', '-u', 'postfix', '--since', '1 hour ago', '--no-pager'
], capture_output=True, text=True)
logs = result.stdout
delivered = len(re.findall(r'status=sent', logs))
bounced = len(re.findall(r'status=bounced', logs))
deferred = len(re.findall(r'status=deferred', logs))
rejected = len(re.findall(r'reject:', logs))
return {
'delivered': delivered,
'bounced': bounced,
'deferred': deferred,
'rejected': rejected,
'total_processed': delivered + bounced + deferred
}
except Exception as e:
return {'error': str(e)}
def get_connection_stats():
"""Get current SMTP connection information"""
try:
result = subprocess.run(['ss', '-tuln', '| grep :25'], shell=True, capture_output=True, text=True)
connections = len(result.stdout.strip().split('\n')) if result.stdout.strip() else 0
# Get Postfix process count
result = subprocess.run(['pgrep', '-c', 'postfix'], capture_output=True, text=True)
processes = int(result.stdout.strip()) if result.stdout.strip().isdigit() else 0
return {
'active_connections': connections,
'postfix_processes': processes
}
except Exception as e:
return {'error': str(e)}
def log_metrics(metrics):
"""Write metrics to log file"""
timestamp = datetime.now().isoformat()
log_entry = {
'timestamp': timestamp,
'metrics': metrics
}
with open('/var/log/mail_performance.log', 'a') as f:
f.write(json.dumps(log_entry) + '\n')
def main():
delivery_stats = get_delivery_stats()
connection_stats = get_connection_stats()
metrics = {
'delivery': delivery_stats,
'connections': connection_stats
}
log_metrics(metrics)
print(f"Performance metrics logged: {json.dumps(metrics, indent=2)}")
if __name__ == "__main__":
main()
Make the performance script executable:
sudo chmod +x /usr/local/bin/mail_performance_monitor.py
For more advanced monitoring setups on VPS hosting, our MySQL backup automation guide covers database monitoring techniques that complement mail server monitoring.
Setup Automated Log Analysis
Configure pflogsumm to generate daily mail server reports. These reports provide detailed insights into mail flow patterns and identify potential issues.
Create a script for daily log analysis:
sudo nano /usr/local/bin/daily_mail_report.sh
Add this reporting script:
#!/bin/bash
# Daily Postfix Log Analysis Script
DATE=$(date +"%Y-%m-%d")
LOG_FILE="/var/log/mail.log"
REPORT_FILE="/tmp/mail_report_${DATE}.txt"
EMAIL="admin@yourdomain.com"
# Generate pflogsumm report
echo "Postfix Log Summary for ${DATE}" > ${REPORT_FILE}
echo "=========================================" >> ${REPORT_FILE}
echo "" >> ${REPORT_FILE}
# Analyze yesterday's logs
pflogsumm -d yesterday ${LOG_FILE} >> ${REPORT_FILE}
# Add queue status
echo "" >> ${REPORT_FILE}
echo "Current Queue Status:" >> ${REPORT_FILE}
echo "====================" >> ${REPORT_FILE}
postqueue -p | tail -1 >> ${REPORT_FILE}
# Add disk usage
echo "" >> ${REPORT_FILE}
echo "Mail Directory Usage:" >> ${REPORT_FILE}
echo "=====================" >> ${REPORT_FILE}
du -sh /var/spool/postfix/* >> ${REPORT_FILE}
# Send report via email
if [ -s "${REPORT_FILE}" ]; then
mail -s "Daily Mail Server Report - ${DATE}" ${EMAIL} < ${REPORT_FILE}
fi
# Clean up
rm ${REPORT_FILE}
Update the email address and make the script executable:
sudo sed -i 's/admin@yourdomain.com/your-email@domain.com/g' /usr/local/bin/daily_mail_report.sh
sudo chmod +x /usr/local/bin/daily_mail_report.sh
Create Monitoring Cron Jobs
Schedule your monitoring scripts to run automatically. This ensures continuous monitoring without manual intervention.
Edit the root crontab:
sudo crontab -e
Add these monitoring cron jobs:
# Mail queue monitoring every 5 minutes
*/5 * * * * /usr/local/bin/mail_queue_monitor.py >> /var/log/mail_queue_monitor.log 2>&1
# Performance metrics every 15 minutes
*/15 * * * * /usr/local/bin/mail_performance_monitor.py >> /var/log/mail_performance_monitor.log 2>&1
# Daily mail report at 6 AM
0 6 * * * /usr/local/bin/daily_mail_report.sh
# Weekly log cleanup
0 2 * * 0 find /var/log -name "mail_*.log" -mtime +30 -delete
Verify the cron jobs are scheduled correctly:
sudo crontab -l
Configure Alerting Thresholds
Fine-tune alert thresholds based on your mail server's normal operating patterns. Start with conservative values and adjust based on your traffic.
Create a configuration file for alert settings:
sudo nano /etc/mail_monitor.conf
Add these configurable thresholds:
# Mail Server Monitoring Configuration
# Queue size thresholds
QUEUE_WARNING=50
QUEUE_CRITICAL=100
# Delivery rate thresholds (messages per hour)
DELIVERY_MIN_RATE=10
DELIVERY_WARNING_RATE=5
# Bounce rate thresholds (percentage)
BOUNCE_WARNING=5
BOUNCE_CRITICAL=15
# Disk usage thresholds (percentage)
DISK_WARNING=80
DISK_CRITICAL=90
# Connection thresholds
CONNECTION_WARNING=50
CONNECTION_CRITICAL=100
# Alert email settings
ALERT_EMAIL="admin@yourdomain.com"
SMTP_SERVER="localhost"
Monitor your server's typical patterns for a week before adjusting these values. High-traffic servers may need higher thresholds.
Testing Your Monitoring Setup
Verify your monitoring configuration works correctly by running manual tests and creating controlled scenarios.
Test the queue monitoring script:
sudo /usr/local/bin/mail_queue_monitor.py
Check performance metrics collection:
sudo /usr/local/bin/mail_performance_monitor.py
cat /var/log/mail_performance.log | tail -5
Generate a test report:
sudo /usr/local/bin/daily_mail_report.sh
Create a test queue buildup to verify alerts work. Send several test emails to a nonexistent domain:
for i in {1..10}; do
echo "Test message $i" | mail -s "Test $i" nonexistent@invaliddomain.test
done
Check the queue and verify monitoring detects the buildup:
postqueue -p
sudo /usr/local/bin/mail_queue_monitor.py
Clear the test messages from the queue:
sudo postqueue -f
Troubleshooting Common Issues
Monitoring setups can encounter several common problems. Here's how to diagnose and resolve them.
Monitoring scripts not running:
Check cron logs and script permissions:
sudo grep CRON /var/log/syslog | tail -10
sudo ls -la /usr/local/bin/mail_*.py
Alert emails not sending:
Verify Postfix is accepting local submissions:
echo "Test alert" | mail -s "Test" root
sudo tail -f /var/log/mail.log
Performance data missing:
Check journalctl permissions and log retention:
sudo journalctl -u postfix --since "1 hour ago" | head -5
sudo ls -la /var/log/mail_performance.log
Queue monitoring false positives:
Adjust thresholds in the monitoring scripts based on your server's normal patterns.
For complex mail server issues, reference our Postfix mail queue monitoring guide for detailed queue analysis techniques.
Maintenance and Best Practices
Regular maintenance keeps your monitoring system effective and prevents false alerts.
Weekly tasks include reviewing alert thresholds, checking log rotation, and validating monitoring script functionality. Update email addresses when staff changes occur.
Monthly tasks involve analyzing performance trends, updating monitoring scripts for new requirements, and testing disaster recovery procedures.
Document your monitoring setup including custom thresholds, alert recipients, and escalation procedures. This documentation helps during incident response and team transitions.
Keep monitoring scripts under version control. This allows you to track changes and quickly revert problematic updates.
Frequently Asked Questions
How often should mail queue monitoring run?
Run queue monitoring every 5 minutes for most setups. High-volume servers may benefit from 2-3 minute intervals, while low-traffic servers can use 10-15 minute intervals.
What queue size indicates a problem?
Queue sizes above 50 messages warrant investigation. Above 100 messages typically indicates delivery issues requiring immediate attention. Adjust thresholds based on your normal traffic patterns.
How long should mail performance logs be retained?
Retain performance logs for 30-90 days depending on your analysis needs. Longer retention helps identify seasonal patterns but requires more storage space.
Should monitoring alerts go to the same mail server being monitored?
Use an external email service for critical alerts to avoid circular dependencies. Configure backup alerting through SMS or external email for mail server failures.
How do I monitor multiple domains on one Postfix server?
Modify the performance monitoring script to parse domain-specific statistics from logs. Use grep patterns to filter delivery stats by recipient domain.
