Setting up a chatmail relay

This section contains everything needed to setup a ready-to-use chatmail relay. The automated setup is designed and optimized for providing chatmail addresses for immediate permission-free onboarding through chat apps and bots. Chatmail addresses are automatically created at first login, after which the initially specified password is required for sending and receiving messages through them.

Minimal requirements and prerequisites

You will need the following:

  • Control over a domain through a DNS provider of your choice. (there is experimental support for IP-only relays).

  • A Debian 12 server with reachable SMTP/SUBMISSIONS/IMAPS/HTTPS ports. IPv6 is encouraged if available. Chatmail relay servers only require 1GB RAM, one CPU, and perhaps 10GB storage for a few thousand active chatmail addresses.

Setup with scripts/cmdeploy

We use chat.example.org as the chatmail domain in the following steps. Please substitute it with your own domain.

  1. Setup the initial DNS records for your relay. The following is an example in the familiar BIND zone file format with a TTL of 1 hour (3600 seconds). Please substitute your domain and IP addresses.

    chat.example.org. 3600 IN A 198.51.100.5
    chat.example.org. 3600 IN AAAA 2001:db8::5
    www.chat.example.org. 3600 IN CNAME chat.example.org.
    mta-sts.chat.example.org. 3600 IN CNAME chat.example.org.
    

    Note

    For experimental deployments using self-signed certificates, use a domain name starting with _ (e.g. _chat.example.org). The mta-sts CNAME and _mta-sts TXT records are not needed for such domains.

  2. Login to the server with SSH, clone the repository and bootstrap the Python virtualenv.

    ssh root@chat.example.org
    git clone https://github.com/chatmail/relay
    cd relay
    scripts/initenv.sh
    
  3. Then, create a chatmail configuration file chatmail.ini:

    scripts/cmdeploy init chat.example.org  # <-- use your domain
    

    To use self-signed TLS certificates instead of Let’s Encrypt, use a domain name starting with _ (e.g. scripts/cmdeploy init _chat.example.org). Domains starting with _ cannot obtain WebPKI certificates, so self-signed mode is derived automatically. This is useful for private or test deployments. See the Technical overview for details on certificate provisioning.

  4. Now run the deployment script to install the relay to the server:

    scripts/cmdeploy run
    

    This script will also check that you have all necessary DNS records. If DNS records are missing, it will recommend which you should configure at your DNS provider (it can take some time until they are public).

Docker installation

There is experimental support for running chatmail via Docker. A monolithic image based on the above cmdeploy method is available through a separate repository. See the chatmail/docker README for full setup instructions.

Next Steps

Now you should display and check all recommended DNS records to enable federation with other relays:

scripts/cmdeploy dns

You should also test whether your chatmail service is working correctly:

scripts/cmdeploy test

Other Helpful Commands

To check the status of your chatmail relay:

scripts/cmdeploy status

To measure the performance of your chatmail service:

scripts/cmdeploy bench

Modifying the home page

cmdeploy run also creates default static web pages and deploys them to a Nginx web server with:

  • a default index.html along with a QR code that users can click to create an address on your chatmail relay

  • 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 generated by the according markdown .md file in the www/src directory.

Refining the web pages

scripts/cmdeploy webdev

This starts a local live development cycle for chatmail web pages:

  • uses the www/src/page-layout.html file for producing static HTML pages from www/src/*.md files

  • continously builds the web presence reading files from www/src directory and generating HTML files and copying assets to the www/build directory.

  • if you are running scripts/cmdeploy webdev on the relay itself, you need to configure a route in /etc/nginx/nginx.conf to expose the build directory.

Custom web pages

You can skip uploading a web page by setting www_folder=disabled in chatmail.ini.

If you want to manage your web pages outside this git repository, you can set www_folder in chatmail.ini to a custom directory on your computer. cmdeploy run will upload it as the server’s home page, and if it contains a src/index.md file, will build it with hugo.

Disable automatic address creation

If you need to stop address creation, e.g. because some script is wildly creating addresses, login with ssh to the relay and run:

touch /etc/chatmail-nocreate

Chatmail address creation will be denied while this file is present.

Running a relay with self-signed certificates

Use a domain name starting with _ (e.g. _chat.example.org) to run a relay with self-signed certificates. Domains starting with _ cannot obtain WebPKI certificates so the relay automatically uses self-signed certificates and all other relays will accept connections from it without requiring certificate verification. This is useful for experimental setups and testing.

Running a relay with externally managed certificates

If you already have a TLS certificate manager (e.g. Traefik, certbot, or another ACME client) running on the deployment server, you can configure the relay to use those certificates instead of the built-in acmetool.

Set the following in chatmail.ini:

tls_external_cert_and_key = /path/to/fullchain.pem /path/to/privkey.pem

The paths must point to certificate and key files on the deployment server. During cmdeploy run, these paths are written into the Postfix, Dovecot, and Nginx configurations. No certificate files are transferred from the build machine — they must already exist on the server, managed by your external certificate tool.

The deploy will verify that both files exist on the server. acmetool is not installed or run in this mode.

Note

You are responsible for certificate renewal. When the certificate file changes on disk, all relay services pick up the new certificate automatically via a systemd path watcher installed during deploy. The watcher uses inotify, which does not cross bind-mount boundaries. If you use such a setup, you must trigger the reload explicitly after renewal:

systemctl start tls-cert-reload.service