Skip to content

Latest commit

 

History

History
415 lines (312 loc) · 9.25 KB

mail-server-setup.md

File metadata and controls

415 lines (312 loc) · 9.25 KB

Mail Server with WireGuard and Linode Proxy

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.


Prerequisites

  • 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

1. Set Up WireGuard VPN

WireGuard will create a private VPN tunnel between your Linode VPS and your local Fedora server.


1.1 Generate WireGuard Keys

On the Linode VPS:

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

On the Local Server:

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

1.2 Configure WireGuard

On the Linode VPS (/etc/wireguard/wg0.conf):

[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

On the Local Server (/etc/wireguard/wg0.conf):

[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

1.3 Start WireGuard

Enable and Start WireGuard on Both Servers:

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Verify the Tunnel:

ping 10.0.0.1  # From local server
ping 10.0.0.2  # From Linode VPS

2. Forward Mail Traffic Using rinetd

Install and configure rinetd on the Linode VPS to forward mail traffic to your local server.

Install rinetd:

sudo apt update
sudo apt install rinetd -y

Configure rinetd:

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

3. Install and Configure Mail Server (Postfix + Dovecot)

3.1 Install Postfix and Dovecot

On the local Fedora server:

sudo dnf install postfix dovecot -y

3.2 Configure Postfix

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

3.3 Configure Dovecot

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

4. Set Up RainLoop Webmail in Docker

4.1 Create Docker Compose File

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"

4.2 Start RainLoop

From the ~/docker/rainloop/ directory, run:

sudo docker-compose up -d

4.3 Access RainLoop Admin Panel

  1. Open a browser and visit:

    https://mail.<your-domain.com>:8888/?admin
    
  2. Log in with:

    • Username: admin
    • Password: 12345 (default).
  3. Add your domain configuration:

    • IMAP: mail.<your-domain.com> (Port 993, SSL)
    • SMTP: mail.<your-domain.com> (Port 587, STARTTLS)

Test the configuration and save.


5. Update DNS Records

Set the following DNS records in your provider (e.g., Cloudflare):

  • MX Record:

    • Name: @
    • Content: mail.<your-domain.com>
    • Priority: 10
  • A Record:

    • Name: mail
    • Content: <LINODE_PUBLIC_IP>

6. Test the Mail Server

  1. Send a test email to user@<your-domain.com> from an external account (e.g., Gmail).

  2. Log in to RainLoop:

    • Visit: https://mail.<your-domain.com>:8888
    • Log in with your email account credentials.
  3. Check for incoming emails.


7. Errors and Troubleshooting

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/.

1. WireGuard: "Required key not available"

Cause:

  • Missing or mismatched WireGuard keys.
  • Configuration errors in the AllowedIPs or Endpoint.

Solution:

  • 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 and ping 10.0.0.2).

2. Postfix: "inet_interfaces: no local interface found"

Cause:

  • Postfix is configured to bind to 10.0.0.2 before WireGuard is active.

Solution:

  • Temporarily set Postfix to listen on all interfaces:
    inet_interfaces = all
  • Use systemd overrides to start Postfix after WireGuard:
    sudo systemctl edit postfix
    Add:
    [Unit]
    After=network.target [email protected]
    Wants[email protected]

Restart Postfix:

sudo systemctl restart postfix

3. RainLoop: "Data folder permissions error [is_readable]"

Cause:

  • RainLoop container cannot access the host data directory due to file ownership or SELinux restrictions.

Solution:

  1. Fix directory ownership for RainLoop's user (UID 33):

    sudo chown -R 33:33 ~/docker/rainloop/data
    sudo chmod -R 755 ~/docker/rainloop/data
  2. Adjust SELinux labels (Fedora specific):

    sudo chcon -R -t container_file_t ~/docker/rainloop/data
  3. 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

4. Dovecot: "ssl_cert: Can't open file"

Cause:

  • The SSL certificate file is missing or incorrectly referenced.

Solution:

  1. 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>"
  2. 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
  3. Restart Dovecot:

    sudo systemctl restart dovecot

5. rinetd Errors: Permission Denied

Cause:

  • rinetd may not have permissions to forward traffic.

Solution:

  1. 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
    
  2. Restart rinetd:

    sudo systemctl restart rinetd
  3. 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

Summary of Error Handling

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.