This is a complete self-hosted infrastructure solution providing both web hosting and email services. Built on Docker containers, this platform offers a production-ready environment featuring WordPress CMS, a full-featured mail server with spam filtering and virus scanning, and web-based email account management through PostfixAdmin.
This is a template repository - you can use it to stand up your own web and mail server infrastructure with your own domain.
- WordPress Website - Full-featured content management system
- Email Server - Complete mail solution with SMTP, IMAP, DKIM, SPF, and DMARC
- PostfixAdmin - Web-based email account management
- SSL/TLS - Automatic certificate management via Let's Encrypt
- Security - Fail2Ban intrusion prevention, SpamAssassin, and ClamAV antivirus
- Nginx - High-performance reverse proxy and web server
- Docker Engine 20.10+
- Docker Compose 2.0+
- Domain name with DNS configured
- Ports 25, 80, 143, 443, 465, 587, 993 available
-
Clone the repository:
git clone <repository-url> YourDomain cd YourDomain
-
Configure environment variables:
cp ENV-TEMPLATE.txt .env nano .env # Edit with your settings -
Generate configuration files:
bash scripts/generate-configs.sh
This creates mail server configs from templates with your credentials.
-
Start the services:
docker compose up -d
-
Obtain SSL certificates:
docker compose run --rm certbot certonly \ --webroot --webroot-path=/var/www/html \ --email your-email@example.com --agree-tos --no-eff-email \ -d yourdomain.com -d www.yourdomain.com \ -d mailadmin.yourdomain.com -d mail.yourdomain.com
-
Restart services to load certificates:
docker compose restart webserver mailserver
See DEPLOYMENT-CHECKLIST.md for detailed deployment instructions.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Internet β
ββββββββββββββ¬βββββββββββββββββββββββββ¬ββββββββββββββββββββ
β β
ββββββΌβββββ ββββββΌβββββ
β Nginx β β Mail β
β (80/443)β β Server β
ββββββ¬βββββ ββββββ¬βββββ
β β
ββββββββββ΄ββββββββββ β
β β β
βββββΌββββββ βββββββΌβββββββ βββββΌβββββ
βWordPressβ βPostfixAdminβ βDatabaseβ
β CMS β β WebUI β β MySQL β
βββββββββββ ββββββββββββββ ββββββββββ
See ARCHITECTURE.md for detailed system architecture.
| Service | Ports | Purpose |
|---|---|---|
| Nginx | 80, 443 | Web server (HTTP/HTTPS) |
| Mail Server | 25, 587, 465 | SMTP (email sending) |
| Mail Server | 143, 993 | IMAP (email access) |
| WordPress | - | CMS (internal) |
| PostfixAdmin | - | Email management (internal) |
| MySQL | - | Database (internal) |
| Certbot | - | SSL certificates (on-demand) |
Configure your DNS to point to your server's public IP:
- yourdomain.com β Main website (WordPress)
- www.yourdomain.com β Main website alias
- mailadmin.yourdomain.com β Email management interface
- mail.yourdomain.com β Mail server (MX record)
# A Records
yourdomain.com A [YOUR_SERVER_IP]
www.yourdomain.com A [YOUR_SERVER_IP]
mailadmin.yourdomain.com A [YOUR_SERVER_IP]
mail.yourdomain.com A [YOUR_SERVER_IP]
# MX Record
yourdomain.com MX 10 mail.yourdomain.com.
# SPF Record
yourdomain.com TXT "v=spf1 mx ~all"
# DKIM Record (from mail server)
default._domainkey.yourdomain.com TXT "v=DKIM1; h=sha256; k=rsa; p=[PUBLIC_KEY]"
# DMARC Record
_dmarc.yourdomain.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
- DEPLOYMENT-CHECKLIST.md - Step-by-step deployment guide
- QUICK-REFERENCE.md - Quick command reference
- ENV-TEMPLATE.txt - Environment variable template
- SECURITY.md - Comprehensive security guide (credential management, rotation, incident response)
- SECURITY-MIGRATION-GUIDE.md - Migration from old config system
- ARCHITECTURE.md - System architecture and data flow
- CONTAINER-REFERENCE.md - Container configuration reference
- Database Container - MySQL configuration
- WordPress Container - WordPress setup
- Web Server Container - Nginx configuration
- Certbot Container - SSL certificate management
- Mail Server Container - Email server configuration
- PostfixAdmin Container - Email account management
- MAILSERVER-README.md - Comprehensive mail server guide
- BACKUP-RESTORE-GUIDE.md - Complete backup & restore documentation
- Container Documentation Index - Complete container reference
π Security First: This template uses a template-based configuration system to prevent credentials from being committed to version control.
All sensitive configuration is managed through the .env file. Key variables:
# Domain Configuration
DOMAIN=yourdomain.com
CERTBOT_EMAIL=admin@yourdomain.com
# MySQL Configuration
MYSQL_ROOT_PASSWORD=SecureRootPassword123!
MYSQL_WPBE_DATABASE=
MYSQL_WPBE_USER=
MYSQL_WPBE_PASSWORD=SecureWPPassword456!
# PostfixAdmin Configuration
MYSQL_PFBE_DATABASE=
MYSQL_PFBE_USER=
MYSQL_PFBE_PASSWORD=SecurePFPassword789!
POSTFIXADMIN_SETUP_PASS=SetupPasswordHash
# Mail Server Configuration
ENABLE_SPAMASSASSIN=1
ENABLE_CLAMAV=1See ENV-TEMPLATE.txt for complete configuration options.
After creating or updating the .env file, generate configuration files:
bash scripts/generate-configs.shThis script:
- Reads credentials from
.env - Generates mail server configs from templates
- Ensures no credentials are committed to version control
- Verifies configuration integrity
Important: Always run this script after changing credentials in .env.
docker compose up -ddocker compose down# All services
docker compose logs -f
# Specific service
docker logs -f mailserverdocker compose restart mailserverdocker exec -it mailserver bashdocker compose run --rm certbot renew
docker compose restart webserver mailserverdocker exec mailserver postqueue -p- Access https://mailadmin.yourdomain.com
- Login with admin credentials
- Navigate to Virtual List β Add Mailbox
- Enter email address and password
- Set quota and click Add
- Monitor logs:
docker compose logs --tail=100 - Check disk space:
df -h - Review mail queue:
docker exec mailserver postqueue -p
- Automated backups run every Sunday at 2:00 AM
- Review fail2ban logs:
docker exec mailserver fail2ban-client status - Check certificate expiry:
docker exec webserver openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -noout -dates
- Verify backup integrity (see Backup & Recovery)
- Database optimization
- Review security logs
- Update containers:
docker compose pull && docker compose up -d
π Comprehensive automated backup system is in place!
- Schedule: Weekly (every Sunday at 2:00 AM)
- Retention: Last 4 weeks (28 days)
- Location:
/var/backups/yourdomain/ - Backup Size: ~2.2 GB per backup
- Components: WordPress, Mail Server, PostfixAdmin, Databases, Certificates, Configuration
# Run full backup manually
sudo ~/path/to/YourDomain/scripts/backup.sh full
# List all backups
sudo ls -lt /var/backups/yourdomain/ | grep "^d"
# View latest backup details
LATEST=$(sudo ls -1t /var/backups/yourdomain/ | grep "^202" | head -1)
sudo cat /var/backups/yourdomain/$LATEST/MANIFEST.txt
# Verify backup integrity
sudo bash -c "cd /var/backups/yourdomain/$LATEST && sha256sum -c checksums.sha256"
# Check backup size
sudo du -sh /var/backups/yourdomain/# Full system restore
sudo ~/path/to/YourDomain/scripts/restore.sh 20251122_204514 full
# Partial restore (database, wordpress, mail, config, etc.)
sudo ~/path/to/YourDomain/scripts/restore.sh 20251122_204514 databaseFor detailed backup/restore procedures, disaster recovery, troubleshooting, and more:
#!/bin/bash
BACKUP_DIR="backups/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# Backup databases
docker exec db mysqldump -u root -p[PASSWORD] --all-databases > $BACKUP_DIR/databases.sql
# Backup WordPress
docker run --rm --volumes-from wordpress -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/wordpress.tar.gz /var/www/html
# Backup mail data
docker run --rm --volumes-from mailserver -v $(pwd)/$BACKUP_DIR:/backup alpine tar czf /backup/mail-data.tar.gz /var/mail
# Backup configuration
tar czf $BACKUP_DIR/config.tar.gz docker-data/ nginx-conf/ .envSee individual container documentation for detailed backup procedures.
Problem: Website not accessible
Solution:
# Check Nginx status
docker logs webserver
# Test Nginx configuration
docker exec webserver nginx -t
# Check WordPress connection
docker exec wordpress ping dbProblem: Cannot send email
Solution:
# Check mail server logs
docker logs mailserver | tail -50
# Check DKIM configuration
docker exec mailserver opendkim-testkey -d yourdomain.com -s default -vvv
# Verify DNS records
dig mail.yourdomain.com
dig default._domainkey.yourdomain.com TXTProblem: Cannot receive email
Solution:
# Check Postfix configuration
docker exec mailserver postconf | grep virtual
# Test database connection
docker exec mailserver mysql -h db -u pfbesvc -p pfbe
# Check mail queue
docker exec mailserver postqueue -pSee ARCHITECTURE.md for detailed troubleshooting flowcharts.
- SSL/TLS Encryption - All connections encrypted with Let's Encrypt certificates
- DKIM Signing - Email authentication with 2048-bit RSA keys
- SPF & DMARC - Sender authentication and policy enforcement
- Fail2Ban - Intrusion detection and automatic IP blocking
- SpamAssassin - Spam filtering with multiple rulesets
- ClamAV - Real-time virus scanning
- Firewall Rules - Only necessary ports exposed
- Password Hashing - SHA512-CRYPT for email accounts
- Network Isolation - Database not exposed externally
- Template-Based Configs - π No credentials in version control
- Configuration Generator - Secure config generation from environment variables
- Strong Passwords - Use complex passwords in
.envfile (generate withopenssl rand -base64 32) - Never Commit Credentials -
.envand generated configs are gitignored - Regular Credential Rotation - See SECURITY.md for procedures
- Regular Updates - Keep containers updated monthly
- Monitor Logs - Check for suspicious activity daily
- Backup Regularly - Automated weekly backups with 4-week retention
- Firewall Configuration - Limit access to management ports
- SSL Certificate Renewal - Automated via cron job
π For comprehensive security guidance, see SECURITY.md
- Install caching plugin (WP Super Cache)
- Enable OpCache (built into PHP 8.2)
- Use CDN for static assets
- Optimize images with Smush plugin
- Configure proper SPF/DKIM/DMARC to avoid spam folders
- Regular spam filter training
- Monitor queue and clean regularly
- Implement rate limiting for outbound mail
- Regular optimization:
OPTIMIZE TABLE - Remove old revisions and spam
- Monitor slow queries
- Proper indexing on frequently queried columns
# Check all containers
docker ps
# Check container health
docker inspect mailserver | grep -A 10 Health
# View resource usage
docker stats# Check mail server status
docker exec mailserver supervisorctl status
# View authentication attempts
docker logs mailserver | grep "auth"
# Check spam filtering stats
docker exec mailserver sa-learn --dump magicThis version has been converted to a template for others to use. All specific domain references have been replaced with yourdomain.com placeholders.
- Implemented Docker Compose infrastructure with 6 core services
- Configured Nginx reverse proxy with SSL/TLS termination
- Deployed WordPress 6.4.3 with PHP 8.2-FPM
- Integrated MySQL 8.0 database for dual purposes (WordPress + PostfixAdmin)
- Implemented Certbot for automated SSL certificate management
- Deployed docker-mailserver with full SMTP/IMAP functionality
- Integrated PostfixAdmin for web-based email account management
-
MySQL Integration: Configured Postfix and Dovecot to use PostfixAdmin MySQL database
- Virtual domain support via MySQL queries
- Virtual mailbox management via MySQL
- Virtual alias mapping via MySQL
- Dovecot SQL authentication with {CRYPT} prefix for password hash auto-detection
-
DKIM Implementation: Configured email signing with default selector
- Generated 2048-bit RSA DKIM keys
- Fixed DKIM SigningTable and KeyTable configuration
- Resolved key selector mismatch (mail β default)
- Published complete DKIM public key to DNS
-
Security Enhancements:
- Implemented Fail2Ban with custom whitelist for internal VLANs
- Whitelisted internal networks: 10.0.6.0/24, 10.0.8.0/24, 10.0.12.0/24, 10.254.254.0/24
- Configured SpamAssassin for spam filtering
- Integrated ClamAV for virus scanning
- Enabled SPF and DMARC validation
-
Custom Configuration:
- Created user-patches.sh for post-startup customization
- Automated MySQL package installation (postfix-mysql, dovecot-mysql)
- Automated fail2ban whitelist application
- Automated Dovecot SQL configuration with {CRYPT} prefix
- Configured Let's Encrypt certificates for all domains:
- yourdomain.com
- www.yourdomain.com
- mailadmin.yourdomain.com
- mail.yourdomain.com
- Shared certificate volume between webserver and mailserver
- Implemented strong cipher suites and TLS 1.2+ only
- DKIM Signing Failure - Fixed OpenDKIM key selector from 'mail' to 'default'
- Password Authentication - Added {CRYPT} prefix to Dovecot password query for SHA512-CRYPT compatibility
- Fail2Ban Blocking - Whitelisted internal VLANs to prevent legitimate traffic blocking
- DKIM DNS Truncation - Identified and documented complete DKIM public key requirements
- System Architecture: Complete architecture diagrams and data flow documentation
- Container Documentation: Individual guides for all 6 containers
- Deployment Guide: Step-by-step deployment checklist
- Quick Reference: Common commands and operations
- Troubleshooting: Comprehensive troubleshooting guides based on production issues
- Security Documentation: Implemented security features and best practices
- Backup & Recovery: Complete automated backup system with disaster recovery procedures
- Automated Backups: Implemented weekly backup system (every Sunday at 2:00 AM)
- Retention Policy: 4-week rolling retention (28 days)
- Comprehensive Coverage: WordPress, Mail Server, PostfixAdmin, Databases, Certificates, Configuration
- Integrity Verification: SHA256 checksums for all backup files
- Backup Scripts:
scripts/backup.sh- Full and partial backup capabilitiesscripts/restore.sh- Full and partial restore capabilities
- Documentation: Complete 350+ line user guide in
docs/BACKUP-RESTORE-GUIDE.md - Security: Root-only access to backups (chmod 700)
- Backup Size: ~2.2 GB per backup, ~8-10 GB total with 4 weeks retention
- Configured inter-VLAN routing considerations
- Documented split DNS requirements for internal vs. external access
- Resolved port blocking issues (desktop VLAN firewall)
-
Automated backup scripts with rotationβ COMPLETED - Monitoring dashboard (Grafana/Prometheus)
- Log aggregation (ELK stack consideration)
- Mail server performance metrics
- WordPress multisite support (if needed)
- Redis caching layer for WordPress
- Database replication for high availability
- Automated security updates
- Off-site backup replication
When making changes to the infrastructure:
- Test in Staging - Use
--dry-runwhere available - Document Changes - Update relevant documentation
- Backup First - Always backup before major changes
- Update Changelog - Add entry to this README
- Version Control - Commit configuration changes (except .env)
- Check relevant documentation in
docs/directory - Review container-specific guides in
docs/containers/ - Check Docker logs:
docker logs [container-name] - Review troubleshooting sections in documentation
This infrastructure configuration template is provided as-is for anyone to use and customize for their own domains.
Built with:
- Docker - Container platform
- WordPress - Content management system
- Nginx - Web server and reverse proxy
- MySQL - Database
- docker-mailserver - Mail server
- PostfixAdmin - Email management
- Let's Encrypt - Free SSL certificates
Last Updated: November 2025
Infrastructure Version: 2.0 (Template Release)
Status: Production-Ready Template