- Notifications
You must be signed in to change notification settings - Fork20
chatmail service deployment scripts and docs
License
chatmail/server
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This repository helps to setup a ready-to-use chatmail servercomprised of a minimal setup of the battle-testedpostfix smtp anddovecot imap services.
The setup is designed and optimized for providing chatmail accountsfor use byDelta Chat apps.
Chatmail accounts are automatically created by a first login,after which the initially specified password is required for using them.
To deploy chatmail on your own server, you must have set-up ssh authentication and need to use an ed25519 key, due to anupstream bug in paramiko. You also need to add your private key to the local ssh-agent, because you can't type in your password during deployment.
We usechat.example.org
as the chatmail domain in the following steps.Please substitute it with your own domain.
Install the
cmdeploy
command in a virtualenvgit clone https://github.com/deltachat/chatmail cd chatmail scripts/initenv.sh
Create chatmail configuration file
chatmail.ini
:scripts/cmdeploy init chat.example.org # <-- use your domain
Point your domain to the server's IP address,if you haven't done so already.Verify that SSH root login works:
ssh root@chat.example.org # <-- use your domain
Deploy to the remote chatmail server:
scripts/cmdeploy run
This script will check that you have all necessary DNS records.If DNS records are missing, it will recommendwhich you should configure at your DNS provider(it can take some time until they are public).
To check the status of your remotely running chatmail service:
scripts/cmdeploy status
To display and check all recommended DNS records:
scripts/cmdeploy dns
To test whether your chatmail service is working correctly:
scripts/cmdeploy test
To measure the performance of your chatmail service:
scripts/cmdeploy bench
This repository has four directories:
cmdeployis a collection of configuration filesand apyinfra-based deployment script.
chatmaildis a python package containing several small serviceswhich handle authentication,trigger push notifications on new messages,ensure that outbound mails are encrypted,delete inactive users,and some other minor things.chatmaild can also be installed as a stand-alone python package.
wwwcontains the html, css, and markdown fileswhich make up a chatmail server's web page.Edit them before deploying to make your chatmail server stand out.
scriptsoffers two convenience tools for beginners;
initenv.sh
installs the necessary dependencies to a local virtual environment,and thescripts/cmdeploy
script enables youto run thecmdeploy
command line tool in the local virtual environment.
Thecmdeploy/src/cmdeploy/cmdeploy.py
command line toolhelps with setting up and managing the chatmail service.cmdeploy init
creates thechatmail.ini
config file.cmdeploy run
uses apyinfra-basedscriptto automatically install or upgrade all chatmail components on a server,according to thechatmail.ini
config.
The components of chatmail are:
postfix smtp server accepts sent messages (both from your users and from other servers)
dovecot imap server stores messages for your users until they download them
nginx shows the web page with your privacy policy and additional information
acmetool manages TLS certificates for dovecot, postfix, and nginx
opendkim for signing messages with DKIM and rejecting inbound messages without DKIM
mtail for collecting anonymized metrics in case you have monitoring
and the chatmaild services, explained in the next section:
chatmaild offers several commandswhich differentiate achatmail server from a classic mail server.If you deploy them with cmdeploy,they are run by systemd services in the background.A short overview:
doveauth
implementscreate-on-login account creation semantics and is usedby Dovecot during login authentication and by Postfixwhich in turn usesDovecot SASLto authenticate usersto send mails for them.filtermail
preventsunencrypted e-mail from leaving the chatmail serviceand is integrated into postfix's outbound mail pipelines.chatmail-metadata
is contacted by adovecot lua scriptto store user-specific server-side config.On new messages,itpasses the user's push notification tokentonotifications.delta.chatso the push notifications on the user's phone can be triggeredby Apple/Google.delete_inactive_users
deletes users if they have not logged in for a very long time.The timeframe can be configured inchatmail.ini
.lastlogin
is contacted by dovecot when a user logs inand stores the date of the login.echobot
is a small bot for test purposes.It simply echoes back messages from users.chatmail-metrics
collects some metrics and displays them athttps://example.org/metrics
.
cmdeploy run
also creates default static Web pages and deploys themto a nginx web server with:
a default
index.html
along with a QR code that users can click tocreate accounts on your chatmail provider,a default
info.html
that is linked from the home page,a default
policy.html
that is linked from the home page.
All.html
files are generatedby the according markdown.md
file in thewww/src
directory.
scripts/cmdeploy webdev
This starts a local live development cycle for chatmail Web pages:
uses the
www/src/page-layout.html
file for producing staticHTML pages fromwww/src/*.md
filescontinously builds the web presence reading files from
www/src
directoryand generating html files and copying assets to thewww/build
directory.Starts a browser window automatically where you can "refresh" as needed.
If you need to stop account creation,e.g. because some script is wildly creating accounts,login to the server with ssh and run:
touch /etc/chatmail-nocreate
While this file is present, account creation will be blocked.
Postfix listens on ports 25 (smtp) and 587 (submission) and 465 (submissions).Dovecot listens on ports 143 (imap) and 993 (imaps).nginx listens on port 8443 (https-alt) and 443 (https).Port 443 multiplexes HTTPS, IMAP and SMTP using ALPN to redirect connections to ports 8443, 465 or 993.acmetool listens on port 80 (http).
Delta Chat apps will, however, discover all ports and configurationsautomatically by reading theautoconfig XML file from the chatmail service.
chatmail servers rely onDKIMto authenticate incoming emails.Incoming emails must have a valid DKIM signature withSigning Domain Identifier (SDID,d=
parameter in the DKIM-Signature header)equal to theFrom:
header domain.This property is checked by OpenDKIM screen policy scriptbefore validating the signatures.This correpsonds to strictDMARC alignment (adkim=s
),but chatmail does not rely on DMARC and does not consult the sender policy published in DMARC records.Other legacy authentication mechanisms such asiprevandSPF are also not taken into account.If there is no valid DKIM signature on the incoming email,the sender receives a "5.7.1 No valid DKIM signature found" error.
Outgoing emails must be sent over authenticated connectionwith envelope MAIL FROM (return path) corresponding to the login.This is ensured by Postfix which maps login usernameto MAIL FROM withsmtpd_sender_login_maps
and rejects incorrectly authenticated emails withreject_sender_login_mismatch
policy.From:
header must correspond to envelope MAIL FROM,this is ensured byfiltermail
proxy.
Postfix is configured to require valid TLSby settingsmtp_tls_security_level
toverify
.If emails don't arrive from a chatmail server to your server,the problem is likely that your server does not have a valid TLS certificate.
You can test it by resolvingMX
records of your server domainand then connecting to MX servers (e.gmx.example.org
) withopenssl s_client -connect mx.example.org:25 -verify_hostname mx.example.org -verify_return_error -starttls smtp
from the host that has open port 25 to verify that certificate is valid.
When providing a TLS certificate to your server,make sure to provide the full certificate chainand not just the last certificate.
If you are running Exim server and don't see incoming connectionsfrom a chatmail server in the logs,make suresmtp_no_mail
log item is enabled in the configwithlog_selector = +smtp_no_mail
.By default Exim does not log sessions that are closedbefore sending theMAIL
command.This happens if certificate is not recognized as valid by Postfix,so you might think that connection is not establishedwhile actually it is a problem with your TLS certificate.
If you want to migrate chatmail from an old machineto a new machine,you can use these steps.They were tested with a linux laptop;you might need to adjust some of the steps to your environment.
Let's assume that yourmail_domain
ismail.example.org
,all involved machines run Debian 12,your old server's IP address is13.37.13.37
,and your new server's IP address is13.12.23.42
.
During the guide, you might get a warning about changed SSH Host keys;in this case, just runssh-keygen -R "mail.example.org"
as recommendedto make sure you can connect with SSH.
First, copy
/var/lib/acme
to the new server withssh root@13.37.13.37 tar c /var/lib/acme | ssh root@13.12.23.42 tar x -C /var/lib/
.This transfers your TLS certificate.You should also copy
/etc/dkimkeys
to the new server withssh root@13.37.13.37 tar c /etc/dkimkeys | ssh root@13.12.23.42 tar x -C /etc/
so the DKIM DNS record stays correct.On the new server, run
chown root: -R /var/lib/acme
andchown opendkim: -R /etc/dkimkeys
to make sure the permissions are correct.Run
cmdeploy run --disable-mail --ssh-host 13.12.23.42
to install chatmail on the new machine.postfix and dovecot are disabled for now,we will enable them later.Now, point DNS to the new IP addresses.
You can already remove the old IP addresses from DNS.Existing Delta Chat users will still be able to connectto the old server, send and receive messages,but new users will fail to create new profileswith your chatmail server.
If other servers try to deliver messages to your new server they will fail,but normally email servers will retry delivering messagesfor at least a week, so messages will not be lost.
Now you can run
cmdeploy run --disable-mail --ssh-host 13.37.13.37
to disable your old server.Now your users will notice the migrationand will not be able to send or receive messagesuntil the migration is completed.
After everything is stopped,you can copy the
/home/vmail/mail
directory to the new server.It includes all user data, messages, password hashes, etc.Just run:
ssh root@13.37.13.37 tar c /home/vmail/mail | ssh root@13.12.23.42 tar x -C /home/vmail/
After this, your new server has all the necessary files to start operating :)
To be sure the permissions are still fine,run
chown vmail: -R /home/vmail
on the new server.Finally, you can run
cmdeploy run
to turn on chatmail on the new server.Your users can continue using the chatmail server,and messages which were sent after step 6. should arrive now.Voilà!
A chatmail server does not depend on the client IP addressfor its operation, so it can be run behind a reverse proxy.This will not even affect incoming mail authenticationas DKIM only checks the cryptographic signatureof the message and does not use the IP address as the input.
For example, you may want to self-host your chatmail serverand only use hosted VPS to provide a public IP addressfor client connections and incoming mail.You can connect chatmail server to VPSusing a tunnel protocolsuch asWireGuardand setup a reverse proxy on a VPSto forward connections to the chatmail serverover the tunnel.You can also setup multiple reverse proxiesfor your chatmail server in different networksto ensure your server is reachable even whenone of the IPs becomes inaccessible due tohosting or routing problems.
Note that your server still needsto be able to make outgoing connections on port 25to send messages outside.
To setup a reverse proxy(or rather Destination NAT, DNAT)for your chatmail server,put the following configuration in/etc/nftables.conf
:
#!/usr/sbin/nft -fflush rulesetdefine wan = eth0# Which ports to proxy.## Note that SSH is not proxied# so it is possible to log into the proxy server# and not the original one.define ports = { smtp, http, https, imap, imaps, submission, submissions }# The host we want to proxy to.define ipv4_address = AAA.BBB.CCC.DDDdefine ipv6_address = [XXX::1]table ip nat { chain prerouting { type nat hook prerouting priority dstnat; policy accept; iif $wan tcp dport $ports dnat to $ipv4_address } chain postrouting { type nat hook postrouting priority 0; oifname $wan masquerade }}table ip6 nat { chain prerouting { type nat hook prerouting priority dstnat; policy accept; iif $wan tcp dport $ports dnat to $ipv6_address } chain postrouting { type nat hook postrouting priority 0; oifname $wan masquerade }}table inet filter { chain input { type filter hook input priority filter; policy drop; # Accept ICMP. # It is especially important to accept ICMPv6 ND messages, # otherwise IPv6 connectivity breaks. icmp type { echo-request } accept icmpv6 type { echo-request, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept # Allow incoming SSH connections. tcp dport { ssh } accept ct state established accept } chain forward { type filter hook forward priority filter; policy drop; ct state established accept ip daddr $ipv4_address counter accept ip6 daddr $ipv6_address counter accept } chain output { type filter hook output priority filter; }}
Runsystemctl enable nftables.service
to ensure configuration is reloaded when the proxy server reboots.
Uncomment in/etc/sysctl.conf
the following two lines:
net.ipv4.ip_forward=1net.ipv6.conf.all.forwarding=1
Then reboot the server or dosysctl -p
andnft -f /etc/nftables.conf
.
Once proxy server is set up,you can add its IP address to the DNS.
About
chatmail service deployment scripts and docs