A complete, portable mail server solution using Docker with PostgreSQL database integration. Based on the BillionMail project architecture.
- Postfix - SMTP server with PostgreSQL integration
- Dovecot - IMAP/POP3 server with PostgreSQL authentication
- Rspamd - Advanced spam filtering
- Redis - Caching and session management
- PostgreSQL - External database support for domains, mailboxes, and aliases
- Portable - Easy to move between servers
- Complete Authentication - User and alias handling
- Remote Database - Support for external PostgreSQL servers
- Direct SSL - SSL/TLS handled directly by mail services
# 1. Clone the repository
git clone https://github.com/rudra-2/mail_server.git
cd mail_server
# 2. Run the setup script
chmod +x setup.sh
./setup.sh
# 3. Follow the prompts to configure your environment
# 4. Set up your remote PostgreSQL database
# 5. Configure DNS records- Docker and Docker Compose
- Domain name with proper DNS records
- SSL certificates (optional, self-signed will be generated)
- Remote PostgreSQL database server
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git ufw fail2ban
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo usermod -aG docker $USER
newgrp dockersudo ufw allow ssh
sudo ufw allow 22/tcp
sudo ufw allow 25/tcp # SMTP
sudo ufw allow 465/tcp # SMTPS
sudo ufw allow 587/tcp # Submission
sudo ufw allow 143/tcp # IMAP
sudo ufw allow 993/tcp # IMAPS
sudo ufw allow 110/tcp # POP3
sudo ufw allow 995/tcp # POP3S
sudo ufw enableSet up these DNS records for your domain:
A mail.yourdomain.com → Your VPS IP
MX yourdomain.com → mail.yourdomain.com (priority 10)
SPF yourdomain.com → v=spf1 mx a ip4:YOUR_VPS_IP ~all
DKIM default._domainkey.yourdomain.com → (DKIM key)
DMARC _dmarc.yourdomain.com → v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
# Clone the repository
git clone https://github.com/rudra-2/mail_server.git
cd reloop
# Run the setup script
chmod +x setup.sh
./setup.shThe setup script will automatically create the .env file and prompt you to configure it. You'll need to set:
Required Configuration:
MAIL_HOSTNAME=mail.yourdomain.com
DB_HOST=your_remote_postgresql_host
DB_NAME=reloop_mail
DB_USER=reloop_user
DB_PASSWORD=reloop_secure_password_2024
REDIS_PASSWORD=reloop_redis_password_2024The setup script will automatically generate self-signed certificates for testing.
For production, replace with Let's Encrypt certificates:
sudo apt install certbot
# Generate certificates
sudo certbot certonly --standalone -d mail.yourdomain.com
# Copy certificates
sudo cp /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem ssl/cert.pem
sudo cp /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem ssl/key.pem
# Set proper permissions
sudo chown $USER:$USER ssl/cert.pem ssl/key.pem
chmod 600 ssl/key.pem
chmod 644 ssl/cert.pemOn your remote PostgreSQL server:
CREATE DATABASE reloop_mail;
CREATE USER reloop_user WITH PASSWORD 'your_secure_password';
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE reloop_mail TO reloop_user;
-- Connect to database and initialize schema
\c reloop_mail
\i database/init.sql
-- Add your domain
INSERT INTO domain (domain, a_record, create_time)
VALUES ('yourdomain.com', 'YOUR_VPS_IP', extract(epoch from now()));
-- Add a test user (password: test123)
INSERT INTO mailbox (username, password, password_encode, full_name, maildir, local_part, domain, create_time)
VALUES ('admin@yourdomain.com', '$1$test123', 'MD5-CRYPT', 'Admin User', 'yourdomain.com/admin/', 'admin', 'yourdomain.com', extract(epoch from now()));The setup script will automatically start all services. If you need to restart:
docker-compose up -d
docker-compose ps
docker-compose logs -f# Test SMTP
telnet localhost 25
EHLO mail.yourdomain.com
QUIT
# Test IMAP
telnet localhost 143
a001 LOGIN admin@yourdomain.com test123
a002 LOGOUT
QUIT
# Test database connection
docker-compose exec postfix psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "SELECT * FROM domain;"| Service | Port | Description |
|---|---|---|
| SMTP | 25 | Mail sending/receiving |
| SMTPS | 465 | Secure SMTP |
| Submission | 587 | Mail submission |
| IMAP | 143 | Mail access |
| IMAPS | 993 | Secure IMAP |
| POP3 | 110 | POP3 access |
| POP3S | 995 | Secure POP3 |
| Redis | 6379 | Caching (internal) |
| PostgreSQL | External | Database (remote server) |
The mail server uses these tables:
domain- Mail domainsmailbox- Email accountsalias- Email forwardingalias_domain- Domain forwarding
- Remote PostgreSQL server accessible from your mail server
- PostgreSQL user with proper permissions
- Network connectivity on port 5432
-
Create the database on your remote PostgreSQL server:
CREATE DATABASE reloop_mail;
-
Create a user with proper permissions:
CREATE USER reloop_user WITH PASSWORD 'your_secure_password'; GRANT ALL PRIVILEGES ON DATABASE reloop_mail TO reloop_user;
-
Initialize the database schema:
psql -h your_remote_host -U reloop_user -d reloop_mail -f database/init.sql
Ensure your firewall allows connections from your mail server to the remote PostgreSQL server on port 5432.
-- Add a domain
INSERT INTO domain (domain, a_record, create_time)
VALUES ('yourdomain.com', 'YOUR_SERVER_IP', extract(epoch from now()));
-- Add a mailbox (password should be MD5-CRYPT hashed)
-- Use: openssl passwd -1 "your_password" to generate the hash
INSERT INTO mailbox (username, password, password_encode, full_name, maildir, local_part, domain, create_time)
VALUES ('admin@yourdomain.com', '$1$hashedpassword', 'MD5-CRYPT', 'Admin User', 'yourdomain.com/admin/', 'admin', 'yourdomain.com', extract(epoch from now()));
-- Add an alias (email forwarding)
INSERT INTO alias (address, goto, domain, create_time)
VALUES ('info@yourdomain.com', 'admin@yourdomain.com', 'yourdomain.com', extract(epoch from now()));Since this mail server doesn't include a webmail interface, users should configure desktop or mobile mail clients:
- Thunderbird - Free, open-source email client
- Outlook - Microsoft email client
- Apple Mail - macOS email client
- Evolution - Linux email client
- Gmail app - Android/iOS
- Apple Mail - iOS
- Outlook app - Android/iOS
- K-9 Mail - Android (open-source)
SMTP Settings:
- Server: your_mail_server_ip
- Port: 587 (Submission) or 465 (SMTPS)
- Security: STARTTLS or SSL/TLS
- Authentication: Username and Password
IMAP Settings:
- Server: your_mail_server_ip
- Port: 143 (IMAP) or 993 (IMAPS)
- Security: STARTTLS or SSL/TLS
- Authentication: Username and Password
Main configuration: config/postfix/main.cf
- Virtual domains via PostgreSQL
- TLS/SSL support
- Rspamd integration
- Dovecot SASL authentication
Main configuration: config/dovecot/dovecot.conf
- PostgreSQL authentication
- Maildir storage
- Sieve filtering
- SSL/TLS support
Main configuration: config/rspamd/rspamd.conf
- Spam filtering rules
- Redis integration
- Postfix milter integration
For production use, you should replace the self-signed certificates:
- Replace
ssl/cert.pemandssl/key.pemwith your certificates - Ensure proper file permissions (600 for key, 644 for cert)
- Restart services after certificate changes
Note: SSL certificates are used by Postfix and Dovecot for secure connections.
docker-compose up -d
docker-compose down
docker-compose restart
docker-compose ps
docker-compose logs [service_name]
docker-compose logs -f [service_name]docker-compose psdocker-compose logs
docker-compose logs postfix
docker-compose logs dovecot
docker-compose logs rspamd
docker-compose logs -f #real-timetelnet localhost 25
EHLO mail.yourdomain.com
telnet localhost 587
EHLO mail.yourdomain.com
AUTH LOGIN
telnet localhost 143
a001 LOGIN username password
docker-compose exec postfix psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "SELECT * FROM domain;"To move this mail server to another server:
- Copy the entire
reloopdirectory - Update
.envfile with new domain settings - Update DNS records to point to new server IP
- Run
docker-compose up -d
- All services run in isolated containers
- SSL/TLS encryption for all connections
- Spam filtering with Rspamd
- Proper file permissions
- PostgreSQL authentication
- Firewall protection with UFW
-
Database Connection Failed
- Check database credentials in
.env - Ensure remote PostgreSQL server is accessible
- Verify database schema is loaded
- Test connection:
docker-compose exec postfix psql -h $DB_HOST -U $DB_USER -d $DB_NAME
- Check database credentials in
-
Mail Not Received
- Check DNS records
- Verify firewall settings
- Check Postfix logs:
docker-compose logs postfix
-
Authentication Failed
- Verify mailbox exists in database
- Check password format (MD5-CRYPT)
- Review Dovecot logs:
docker-compose logs dovecot
-
SSL Issues
- Verify certificate files exist
- Check file permissions
- Review service logs
# Rebuild containers
docker-compose build --no-cache
# Restart specific service
docker-compose restart postfix
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -v
# Check container logs
docker-compose logs -f
# Access container shell
docker-compose exec postfix bash
docker-compose exec dovecot bashThis project is based on the Reloop project and is licensed under AGPLv3.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
For issues and questions:
- Check the troubleshooting section
- Review service logs
- Open an issue on GitHub