.. _selfhost-chatmail: .. meta:: :http-equiv=onion-location: http://hackeavw7lge3rj7vwfewaaid7akgmys2vlqggeirtorcg5g6zoawzqd.onion/archivo/selfhost-chatmail.html How to self-host a Chatmail relay ================================= If you want to run your own Chatmail relay but you don't want to run it on `someone else's computer `_, follow this guide. Unfortunately, you will need a VPS to act as a VPN gateway. You will use its reputable public IP address, but the relay will run on your own hardware at home -an old laptop, a Proxmox LXC container or whatever you want- tunneling its traffic through Wireguard. No third-party access. 0. Standard requirements ------------------------ Check the `Minimal requirements and prerequisites `_ section at the official documentation (from now on we will call *relay* to that Debian system where the Chatmail server will be later installed). For our setup, you will need a VPS too. 1. Get a VPS ------------ A Chatmail relay is an email server. Denylist providers will consider your residential public IP address as a source of spam and include it in its denylists. So you need a non-residential public IP address to be able to communicate with Delta Chat users that have accounts on mail servers that trust those lists (most mail servers do). Get the cheapest VPS you can find, the resources needed are minimal. 2. [VPS] Take some notes ------------------------ Run ``ip a`` and take note of: - The name of its ethernet interface (ens18, eth0, whatever...) - Its public IPv4 address - Its public IPv6 address 3. [VPS] Check external firewall -------------------------------- In the case the cloud provider provides a firewall external to the VPS, make sure you allow `every needed port for the relay `_, as well as for SSH and Wireguard (UDP 51820). 4. [VPS] Allow IP forwarding ---------------------------- Edit ``/etc/sysctl.conf``, uncomment the following lines :: net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 And do ``sudo sysctl -p`` 5. [Both Relay and VPS] Install Wireguard ----------------------------------------- :: sudo apt install wireguard Or adapt to your package manager. 6. [Both Relay and VPS]: Create the keys ---------------------------------------- :: cd /etc/wireguard sudo wg genkey | tee privatekey | wg pubkey > publickey Check the keys are available at ``/etc/wireguard/`` 7. [VPS] Configure wg0.conf --------------------------- Create the file ``/etc/wireguard/wg0.conf`` Paste the following block and edit as noted. :: [Interface] PrivateKey = [write here the private key of the VPS] Address = 10.6.0.1/24,fd42:42:42::1/64 ListenPort = 51820 SaveConfig = true PostUp = bash /etc/wireguard/PostUp.sh PostDown = bash /etc/wireguard/PostDown.sh [Peer] PublicKey = [insert here the public key of the Relay] AllowedIPs = 10.6.0.2/32,fd42:42:42::2/128 8. [VPS] Configure PostUp.sh ---------------------------- Create the file ``/etc/wireguard/PostUp.sh`` Paste the following block and edit as noted. :: # LET VPN CLIENTS ACCESS THE INTERNET (that is chatmail's outgoing port-25/465/587 traffic) iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o [write here the name of the VPS' ethernet interface] -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o [write here the name of the VPS' ethernet interface] -j MASQUERADE; # ICMP iptables -A INPUT -p icmp -j ACCEPT; ip6tables -A INPUT -p ipv6-icmp -j ACCEPT; # ROUTING TCP FROM VPS TO RELAY (in this example 22222 for SSH) for m in 25 80 143 443 465 587 993 8443 22222 do iptables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p tcp --dport $m -j DNAT --to-destination 10.6.0.2; iptables -A FORWARD -d 10.6.0.2 -p tcp --dport $m -j ACCEPT; ip6tables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p tcp --dport $m -j DNAT --to-destination fd42:42:42::2; ip6tables -A FORWARD -d fd42:42:42::2 -p tcp --dport $m -j ACCEPT; done # ROUTING UDP FROM VPS TO RELAY # Control port iptables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 3478 -j DNAT --to-destination 10.6.0.2; iptables -A FORWARD -d 10.6.0.2 -p udp --dport 3478 -j ACCEPT; ip6tables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 3478 -j DNAT --to-destination fd42:42:42::2; ip6tables -A FORWARD -d fd42:42:42::2 -p udp --dport 3478 -j ACCEPT; # TURN allocation range (ephemeral ports) iptables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 49152:65535 -j DNAT --to-destination 10.6.0.2; iptables -A FORWARD -d 10.6.0.2 -p udp --dport 49152:65535 -j ACCEPT; ip6tables -t nat -A PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 49152:65535 -j DNAT --to-destination fd42:42:42::2; ip6tables -A FORWARD -d fd42:42:42::2 -p udp --dport 49152:65535 -j ACCEPT; # HAIRPIN HANDLING (to avoid port 80 issues on cert creation and renewal) # IPv4: allow VPS-local processes to reach the public IP and hairpin wg clients iptables -t nat -C OUTPUT -d [write here the VPS public IPv4 address]/32 -p tcp --dport 80 -j DNAT --to-destination 10.6.0.2:80 2>/dev/null || \ iptables -t nat -A OUTPUT -d [write here the VPS public IPv4 address]/32 -p tcp --dport 80 -j DNAT --to-destination 10.6.0.2:80 iptables -t nat -C POSTROUTING -s 10.6.0.0/24 -d 10.6.0.2/32 -j MASQUERADE 2>/dev/null || \ iptables -t nat -A POSTROUTING -s 10.6.0.0/24 -d 10.6.0.2/32 -j MASQUERADE # IPv6: mirror if ip6tables nat table is available ip6tables -t nat -C OUTPUT -d [write here the VPS public IPv6 address]/128 -p tcp --dport 80 -j DNAT --to-destination fd42:42:42::2 2>/dev/null || \ ip6tables -t nat -A OUTPUT -d [write here the VPS public IPv6 address]/128 -p tcp --dport 80 -j DNAT --to-destination fd42:42:42::2 ip6tables -t nat -C POSTROUTING -s fd42:42:42::/64 -d fd42:42:42::2/128 -j MASQUERADE 2>/dev/null || \ ip6tables -t nat -A POSTROUTING -s fd42:42:42::/64 -d fd42:42:42::2/128 -j MASQUERADE # Remove stale HTTP conntrack entries for relay to avoid hairpin state issues conntrack -D -d 10.6.0.2 -p tcp --dport 80 2>/dev/null || true conntrack -D -s 10.6.0.2 -p tcp --sport 80 2>/dev/null || true 9. [VPS] Configure PostDown.sh ------------------------------ Create the file ``/etc/wireguard/PostDown.sh`` Paste the following block and edit as noted. :: iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o [write here the name of the VPS' ethernet interface] -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o [write here the name of the VPS' ethernet interface] -j MASQUERADE; # ICMP iptables -D INPUT -p icmp -j ACCEPT; ip6tables -D INPUT -p ipv6-icmp -j ACCEPT; # ROUTING TCP FROM VPS TO CHATMAIL for m in 25 80 143 443 465 587 993 8443 22222 do iptables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p tcp --dport $m -j DNAT --to-destination 10.6.0.2; iptables -D FORWARD -d 10.6.0.2 -p tcp --dport $m -j ACCEPT; ip6tables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p tcp --dport $m -j DNAT --to-destination fd42:42:42::2; ip6tables -D FORWARD -d fd42:42:42::2 -p tcp --dport $m -j ACCEPT; done # ROUTING UDP FROM VPS TO CHATMAIL # Control port iptables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 3478 -j DNAT --to-destination 10.6.0.2; iptables -D FORWARD -d 10.6.0.2 -p udp --dport 3478 -j ACCEPT; ip6tables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 3478 -j DNAT --to-destination fd42:42:42::2; ip6tables -D FORWARD -d fd42:42:42::2 -p udp --dport 3478 -j ACCEPT; # TURN allocation range (ephemeral ports) iptables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 49152:65535 -j DNAT --to-destination 10.6.0.2; iptables -D FORWARD -d 10.6.0.2 -p udp --dport 49152:65535 -j ACCEPT; ip6tables -t nat -D PREROUTING -i [write here the name of the VPS' ethernet interface] -p udp --dport 49152:65535 -j DNAT --to-destination fd42:42:42::2; ip6tables -D FORWARD -d fd42:42:42::2 -p udp --dport 49152:65535 -j ACCEPT; # HAIRPIN HANDLING iptables -t nat -D OUTPUT -d [write here the VPS public IPv4 address]/32 -p tcp --dport 80 -j DNAT --to-destination 10.6.0.2:80 2>/dev/null || true iptables -t nat -D POSTROUTING -s 10.6.0.0/24 -d 10.6.0.2/32 -j MASQUERADE 2>/dev/null || true ip6tables -t nat -D OUTPUT -d [write here the VPS public IPv6 address]/128 -p tcp --dport 80 -j DNAT --to-destination fd42:42:42::2 2>/dev/null || true ip6tables -t nat -D POSTROUTING -s fd42:42:42::/64 -d fd42:42:42::2/128 -j MASQUERADE 2>/dev/null || true # #remove stale HTTP conntrack entries for relay to avoid hairpin state issues conntrack -D -d 10.6.0.2 -p tcp --dport 80 2>/dev/null || true conntrack -D -s 10.6.0.2 -p tcp --sport 80 2>/dev/null || true 10. [VPS] Give the scripts exec permissions ------------------------------------------- :: sudo chmod +x /etc/wireguard/PostUp.sh sudo chmod +x /etc/wireguard/PostDown.sh 11. [Relay] Configure wg0.conf ------------------------------ Create the file ``/etc/wireguard/wg0.conf`` Paste the following block and edit as noted. :: [Interface] PrivateKey = [write here the relay's private key] Address = 10.6.0.2/24, fd42:42:42::2/64 # choose your DNS [modify the DNS addresses below as you like] DNS = 94.247.43.254, 2a00:f826:8:1::254 PostUp = bash /etc/wireguard/PostUp.sh PostDown = bash /etc/wireguard/PostDown.sh [Peer] PublicKey = [write here the VPS' public key] Endpoint = [write here the VPS' public IPv4 address]:51820 AllowedIPs = 0.0.0.0/0, ::0/0 PersistentKeepalive = 25 12. [Relay] Configure PostUp.sh ------------------------------- Create the file ``/etc/wireguard/PostUp.sh`` Paste the following block and edit the SSH port if needed. :: # IPV4 iptables -w -N vpnclient_in; iptables -w -N vpnclient_out; iptables -w -N vpnclient_fwd; iptables -w -A vpnclient_in -p icmp -j ACCEPT; # TCP (in this example 22222 for SSH) for i in 25 80 143 443 465 587 993 8443 22222 do iptables -w -A vpnclient_in -p tcp --dport $i -j ACCEPT; done # UDP # TURN control port iptables -w -A vpnclient_in -p udp --dport 3478 -j ACCEPT # TURN allocation range (ephemeral ports) iptables -w -A vpnclient_in -p udp --dport 49152:65535 -j ACCEPT iptables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT; iptables -w -A vpnclient_in -j DROP; iptables -w -A vpnclient_out -j ACCEPT; iptables -w -A vpnclient_fwd -j DROP; iptables -w -I INPUT 1 -i wg0 -j vpnclient_in; iptables -w -I OUTPUT 1 -o wg0 -j vpnclient_out; iptables -w -I FORWARD 1 -o wg0 -j vpnclient_fwd; # IPV6 ip6tables -w -N vpnclient_in; ip6tables -w -N vpnclient_out; ip6tables -w -N vpnclient_fwd; ip6tables -w -A vpnclient_in -p ipv6-icmp -j ACCEPT; # TCP (in this example 22222 for SSH) for i in 25 80 143 443 465 587 993 8443 22222 do ip6tables -w -A vpnclient_in -p tcp --dport $i -j ACCEPT; done # UDP # TURN control port ip6tables -w -A vpnclient_in -p udp --dport 3478 -j ACCEPT # TURN allocation range (ephemeral ports) ip6tables -w -A vpnclient_in -p udp --dport 49152:65535 -j ACCEPT ip6tables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT; ip6tables -w -A vpnclient_in -j DROP; ip6tables -w -A vpnclient_out -j ACCEPT; ip6tables -w -A vpnclient_fwd -j DROP; ip6tables -w -I INPUT 1 -i wg0 -j vpnclient_in; ip6tables -w -I OUTPUT 1 -o wg0 -j vpnclient_out; ip6tables -w -I FORWARD 1 -o wg0 -j vpnclient_fwd; 13. [Relay] Configure PostDown.sh --------------------------------- Create the file ``/etc/wireguard/PostDown.sh`` Paste the following block. :: # IPV4 iptables -w -F vpnclient_in; iptables -w -F vpnclient_out; iptables -w -F vpnclient_fwd; iptables -D INPUT -i wg0 -j vpnclient_in; iptables -D FORWARD -o wg0 -j vpnclient_fwd; iptables -D OUTPUT -o wg0 -j vpnclient_out; iptables -w -X vpnclient_in; iptables -w -X vpnclient_out; iptables -w -X vpnclient_fwd; # IPV6 ip6tables -w -F vpnclient_in; ip6tables -w -F vpnclient_out; ip6tables -w -F vpnclient_fwd; ip6tables -D INPUT -i wg0 -j vpnclient_in; ip6tables -D FORWARD -o wg0 -j vpnclient_fwd; ip6tables -D OUTPUT -o wg0 -j vpnclient_out; ip6tables -w -X vpnclient_in; ip6tables -w -X vpnclient_out; ip6tables -w -X vpnclient_fwd; 14. [Relay] Give the scripts exec permissions --------------------------------------------- :: sudo chmod +x /etc/wireguard/PostUp.sh sudo chmod +x /etc/wireguard/PostDown.sh 15. [Both Relay and VPS] Enable Wireguard ----------------------------------------- :: sudo systemctl start wg-quick@wg0.service sudo systemctl enable wg-quick@wg0.service 16. [Relay or VPS] Check tunnel ------------------------------- Run ``wg show``. You should see the peer with some data transfered and you should also see a line reading ``latest handshake:`` showing a minute and/or some seconds. 17. Deploy your relay --------------------- Now you are ready to follow the official documentation: https://chatmail.at/doc/relay/index.html