This guide will set up a mail server on a local machine (Fedora) behind a restricted network. A Linode VPS (Ubuntu) will act as a proxy to forward traffic using WireGuard and rinetd. The webmail interface will be provided via RainLoop running in a Docker container.
- Linode VPS with a public IP:
<LINODE_PUBLIC_IP> - Local Fedora Server (mail server) without direct internet access.
- Domain:
<your-domain.com>(e.g.,ion606.com) - Tools installed:
- Docker and Docker Compose
- WireGuard
- Postfix and Dovecot
- Nginx
WireGuard will create a private VPN tunnel between your Linode VPS and your local Fedora server.
wg genkey | tee linode-private.key | wg pubkey > linode-public.key
cat linode-private.key # Save this for later
cat linode-public.key # Save this for laterwg genkey | tee local-private.key | wg pubkey > local-public.key
cat local-private.key # Save this for later
cat local-public.key # Save this for later[Interface]
PrivateKey = <LINODE_PRIVATE_KEY>
Address = 10.0.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <LOCAL_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
PersistentKeepalive = 25[Interface]
PrivateKey = <LOCAL_PRIVATE_KEY>
Address = 10.0.0.2/24
[Peer]
PublicKey = <LINODE_PUBLIC_KEY>
AllowedIPs = 10.0.0.1/32
Endpoint = <LINODE_PUBLIC_IP>:51820
PersistentKeepalive = 25sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0ping 10.0.0.1 # From local server
ping 10.0.0.2 # From Linode VPSInstall and configure rinetd on the Linode VPS to forward mail traffic to your local server.
sudo apt update
sudo apt install rinetd -yEdit /etc/rinetd.conf:
0.0.0.0 587 10.0.0.2 587
0.0.0.0 993 10.0.0.2 993
Restart rinetd:
sudo systemctl restart rinetdOn the local Fedora server:
sudo dnf install postfix dovecot -yEdit /etc/postfix/main.cf:
inet_interfaces = 10.0.0.2
myhostname = mail.<your-domain.com>
mydomain = <your-domain.com>
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relay_domains = $mydestination
mynetworks = 127.0.0.0/8, 10.0.0.1/32
smtp_use_tls = yes
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.keyRestart Postfix:
sudo systemctl restart postfixEdit /etc/dovecot/conf.d/10-mail.conf:
mail_location = mbox:~/mail:INBOX=/var/mail/%uEdit /etc/dovecot/conf.d/10-ssl.conf:
ssl = yes
ssl_cert = </etc/ssl/certs/dovecot-selfsigned.pem
ssl_key = </etc/ssl/private/dovecot-selfsigned.keyRestart Dovecot:
sudo systemctl restart dovecotCreate the following structure:
~/docker/rainloop/
└── docker-compose.yml
docker-compose.yml:
version: '3.8'
services:
rainloop:
container_name: rainloop
image: hardware/rainloop
restart: always
volumes:
- ./data:/rainloop/data:z
ports:
- "8888:8888"From the ~/docker/rainloop/ directory, run:
sudo docker-compose up -d-
Open a browser and visit:
https://mail.<your-domain.com>:8888/?admin -
Log in with:
- Username:
admin - Password:
12345(default).
- Username:
-
Add your domain configuration:
- IMAP:
mail.<your-domain.com>(Port 993, SSL) - SMTP:
mail.<your-domain.com>(Port 587, STARTTLS)
- IMAP:
Test the configuration and save.
Set the following DNS records in your provider (e.g., Cloudflare):
-
MX Record:
- Name:
@ - Content:
mail.<your-domain.com> - Priority:
10
- Name:
-
A Record:
- Name:
mail - Content:
<LINODE_PUBLIC_IP>
- Name:
-
Send a test email to
user@<your-domain.com>from an external account (e.g., Gmail). -
Log in to RainLoop:
- Visit:
https://mail.<your-domain.com>:8888 - Log in with your email account credentials.
- Visit:
-
Check for incoming emails.
Sidenote: Here are the commands to view the logs from the above programs
- Postfix Logs:
sudo tail -f /var/log/maillog
- Dovecot Logs:
sudo tail -f /var/log/dovecot.log
- RainLoop Errors:
Check
~/docker/rainloop/data/_data_/logs/.
- Missing or mismatched WireGuard keys.
- Configuration errors in the
AllowedIPsorEndpoint.
- Regenerate and verify keys on both servers:
wg genkey | tee private.key | wg pubkey > public.key
- Replace keys in
/etc/wireguard/wg0.confand restart WireGuard:sudo systemctl restart wg-quick@wg0
- Verify the tunnel with
wg showand ping test (ping 10.0.0.1andping 10.0.0.2).
- Postfix is configured to bind to
10.0.0.2before WireGuard is active.
- Temporarily set Postfix to listen on all interfaces:
inet_interfaces = all - Use systemd overrides to start Postfix after WireGuard:
Add:
sudo systemctl edit postfix
[Unit] After=network.target wg-quick@wg0.service Wants=wg-quick@wg0.service
Restart Postfix:
sudo systemctl restart postfix- RainLoop container cannot access the host
datadirectory due to file ownership or SELinux restrictions.
-
Fix directory ownership for RainLoop's user (
UID 33):sudo chown -R 33:33 ~/docker/rainloop/data sudo chmod -R 755 ~/docker/rainloop/data
-
Adjust SELinux labels (Fedora specific):
sudo chcon -R -t container_file_t ~/docker/rainloop/data -
Update
docker-compose.ymlto add:zfor SELinux compatibility:volumes: - ./data:/rainloop/data:z
Restart RainLoop:
sudo docker-compose down
sudo docker-compose up -d- The SSL certificate file is missing or incorrectly referenced.
-
Generate a self-signed SSL certificate:
sudo mkdir -p /etc/ssl/certs /etc/ssl/private sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/dovecot-selfsigned.key \ -out /etc/ssl/certs/dovecot-selfsigned.pem \ -subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=mail.<your-domain.com>" -
Update Dovecot's configuration in
/etc/dovecot/conf.d/10-ssl.conf:ssl = yes ssl_cert = </etc/ssl/certs/dovecot-selfsigned.pem ssl_key = </etc/ssl/private/dovecot-selfsigned.key
-
Restart Dovecot:
sudo systemctl restart dovecot
rinetdmay not have permissions to forward traffic.
-
Ensure
rinetd.confis properly configured:0.0.0.0 587 10.0.0.2 587 0.0.0.0 993 10.0.0.2 993 -
Restart
rinetd:sudo systemctl restart rinetd
-
Check for SELinux interference:
sudo setenforce 0 # Temporarily disable SELinux for testingIf this resolves the issue, fix SELinux permanently:
sudo chcon -R -t container_file_t /etc/rinetd.conf
| Error | Cause | Solution |
|---|---|---|
| Required key not available (WireGuard) | Missing/mismatched keys | Regenerate keys and verify configuration. |
| inet_interfaces error (Postfix) | WireGuard interface not active | Delay Postfix startup using systemd overrides. |
| Data folder permissions error (RainLoop) | Ownership or SELinux restriction | Fix ownership (chown) and SELinux labels. |
| ssl_cert error (Dovecot) | Missing SSL certificate | Generate a self-signed SSL certificate. |
| rinetd permission denied | SELinux or misconfigurations | Fix permissions and test SELinux compatibility. |