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 later
wg 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 = 25
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
ping 10.0.0.1 # From local server
ping 10.0.0.2 # From Linode VPS
Install and configure rinetd
on the Linode VPS to forward mail traffic to your local server.
sudo apt update
sudo apt install rinetd -y
Edit /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 rinetd
On the local Fedora server:
sudo dnf install postfix dovecot -y
Edit /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.key
Restart Postfix:
sudo systemctl restart postfix
Edit /etc/dovecot/conf.d/10-mail.conf
:
mail_location = mbox:~/mail:INBOX=/var/mail/%u
Edit /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
Create 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
AllowedIPs
orEndpoint
.
- Regenerate and verify keys on both servers:
wg genkey | tee private.key | wg pubkey > public.key
- Replace keys in
/etc/wireguard/wg0.conf
and restart WireGuard:sudo systemctl restart wg-quick@wg0
- Verify the tunnel with
wg show
and ping test (ping 10.0.0.1
andping 10.0.0.2
).
- Postfix is configured to bind to
10.0.0.2
before 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 [email protected] Wants[email protected]
Restart Postfix:
sudo systemctl restart postfix
- RainLoop container cannot access the host
data
directory 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.yml
to add:z
for 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
rinetd
may not have permissions to forward traffic.
-
Ensure
rinetd.conf
is 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 testing
If 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. |