Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions chatmaild/src/chatmaild/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def __init__(self, inipath, params):
params = dict(params)
raw_domain = params.pop("mail_domain")
self.mail_domain_bare = raw_domain
self.ssh_host = params.pop("ssh_host", raw_domain)

if is_valid_ipv4(raw_domain):
self.ipv4_relay = raw_domain
Expand Down
3 changes: 3 additions & 0 deletions chatmaild/src/chatmaild/ini/chatmail.ini.f
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# mail domain (MUST be set to fully qualified chat mail domain)
mail_domain = {mail_domain}

# Where to deploy the relay - if unspecified, mail_domain will be used.
ssh_host = localhost
Comment on lines +6 to +7

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still a bit worried, this will confuse some people (although, it indeed makes more sense).

@missytake missytake Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I couldn't come up with a better path forward. If you have a better wording, let me work :)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mostly confusing because mail_domain is the default... except it's not because it is also overwritten by default by localhost.

Maybe something like:

Suggested change
# Where to deploy the relay - if unspecified, mail_domain will be used.
ssh_host = localhost
# Where to deploy the relay.
# Change the following line to deploy on a remote machine instead,
# or remove it to deploy on mail_domain.

Not sure :/


#
# If you only do private test deploys, you don't need to modify any settings below
#
Expand Down
8 changes: 4 additions & 4 deletions cmdeploy/src/cmdeploy/cmdeploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _warn_unused_settings(unused_keys, out):
def run_cmd(args, out):
"""Deploy chatmail services on the remote server."""

ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain_bare
ssh_host = args.ssh_host if args.ssh_host else args.config.ssh_host
sshexec = get_sshexec(ssh_host)
require_iroh = args.config.enable_iroh_relay
strict_tls = args.config.tls_cert_mode == "acme"
Expand All @@ -116,7 +116,7 @@ def run_cmd(args, out):
pyinf = "pyinfra --dry" if args.dry_run else "pyinfra"

cmd = f"{pyinf} --ssh-user root {ssh_host} {deploy_path} -y"
if ssh_host == "localhost":
if ssh_host in ["localhost", "@local"]:
Comment thread
j-g00da marked this conversation as resolved.
cmd = f"{pyinf} @local {deploy_path} -y"

if version.parse(pyinfra.__version__) < version.parse("3"):
Expand Down Expand Up @@ -158,7 +158,7 @@ def dns_cmd(args, out):
ipv4 = args.config.ipv4_relay
print(f"[WARNING] {ipv4} is not a domain, skipping DNS checks.")
return 0
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain
ssh_host = args.ssh_host if args.ssh_host else args.config.ssh_host
sshexec = get_sshexec(ssh_host, verbose=args.verbose)
tls_cert_mode = args.config.tls_cert_mode
strict_tls = tls_cert_mode == "acme"
Expand Down Expand Up @@ -195,7 +195,7 @@ def status_cmd_options(parser):
def status_cmd(args, out):
"""Display status for online chatmail instance."""

ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain_bare
ssh_host = args.ssh_host if args.ssh_host else args.config.ssh_host
sshexec = get_sshexec(ssh_host, verbose=args.verbose)

out.green(f"chatmail domain: {args.config.mail_domain}")
Expand Down
4 changes: 2 additions & 2 deletions cmdeploy/src/cmdeploy/tests/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def maildomain(chatmail_config):


@pytest.fixture(scope="session")
def sshdomain(maildomain):
return os.environ.get("CHATMAIL_SSH", maildomain)
def sshdomain(chatmail_config):
return os.environ.get("CHATMAIL_SSH", chatmail_config.ssh_host)


@pytest.fixture
Expand Down
84 changes: 29 additions & 55 deletions doc/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,14 @@ Minimal requirements and prerequisites

You will need the following:

- A Debian 12 **deployment server** with reachable SMTP/SUBMISSIONS/IMAPS/HTTPS ports.
- Control over a domain through a DNS provider of your choice.
(there is experimental support for :ref:`IP-only relays <iponly>`).

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

- A Linux or Unix **build machine** with key-based SSH access to the root
user of the deployment server.
You must add a passphrase-protected private key to your local ssh-agent because you
can’t type in your passphrase during deployment.
(An ed25519 private key is required due to an `upstream bug in
paramiko <https://github.com/paramiko/paramiko/issues/2191>`_)

- Control over a domain through a DNS provider of your choice
(there is experimental support for :ref:`IP-only relays <iponly>`).


.. _setup:

Expand All @@ -38,7 +31,7 @@ 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 deployment server.
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.
Expand All @@ -58,22 +51,25 @@ steps. Please substitute it with your own domain.
The ``mta-sts`` CNAME and ``_mta-sts`` TXT records
are not needed for such domains.

2. On your local PC, clone the repository and bootstrap the Python
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. On your local build machine (PC), create a chatmail configuration file
3. Then, create a chatmail configuration file
``chatmail.ini``:

::

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

.. note::

To use self-signed TLS certificates
instead of Let's Encrypt,
use a domain name starting with ``_``
Expand All @@ -84,13 +80,7 @@ steps. Please substitute it with your own domain.
See the :doc:`overview`
for details on certificate provisioning.

4. Verify that SSH root login to the deployment server server works:

::

ssh root@chat.example.org # <-- use your domain

5. From your local build machine, setup and configure the remote deployment server:
4. Now run the deployment script to install the relay to the server:

::

Expand All @@ -102,34 +92,39 @@ steps. Please substitute it with your own domain.
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 <https://github.com/chatmail/docker/pkgs/container/docker>`_.
See the `chatmail/docker README <https://github.com/chatmail/docker>`_ for full setup instructions.

Other helpful commands
----------------------

To check the status of your deployment server running the chatmail service:
Next Steps
----------

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

::

scripts/cmdeploy status
scripts/cmdeploy dns

To display and check all recommended DNS records:
You should also test whether your chatmail service is working correctly:

::

scripts/cmdeploy dns
scripts/cmdeploy test

Other Helpful Commands
----------------------

To test whether your chatmail service is working correctly:
To check the status of your chatmail relay:

::

scripts/cmdeploy test
scripts/cmdeploy status


To measure the performance of your chatmail service:

Expand Down Expand Up @@ -171,8 +166,9 @@ This starts a local live development cycle for chatmail web pages:
directory and generating HTML files and copying assets to the
``www/build`` directory.

- Starts a browser window automatically where you can “refresh” as
needed.
- 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
----------------
Expand All @@ -190,7 +186,7 @@ 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 deployment machine and run:
creating addresses, login with ssh to the relay and run:

::

Expand Down Expand Up @@ -246,25 +242,3 @@ The deploy will verify that both files exist on the server.
If you use such a setup, you must trigger the reload explicitly after renewal::

systemctl start tls-cert-reload.service


Migrating to a new build machine
----------------------------------

To move or add a build machine,
clone the relay repository on the new build machine, and copy the ``chatmail.ini`` file from the old build machine.
Make sure ``rsync`` is installed, then initialize the environment:

::

./scripts/initenv.sh

Run safety checks before a new deployment:

::

./scripts/cmdeploy dns
./scripts/cmdeploy status

If you keep multiple build machines (ie laptop and desktop), keep ``chatmail.ini`` in sync between
them.
Comment thread
missytake marked this conversation as resolved.
18 changes: 16 additions & 2 deletions doc/source/migrate.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Migrating to a new machine
===========================
Migrating the relay to a new server
===================================

This migration tutorial provides a step-wise approach
to safely migrate a chatmail relay from one remote machine to another.
Expand Down Expand Up @@ -96,3 +96,17 @@ in this case, just run ``ssh-keygen -R "mail.example.org"`` as recommended.
If you have lowered the Time-to-Live for DNS records in step 1,
better use a higher value again (between 14400 and 86400 seconds) once you are sure everything works.


Migrating a local chatmail/relay repository to the server
=========================================================

To move the directory with your local chatmail/relay repository and ``chatmail.ini`` file,
clone the `relay repository <https://github.com/chatmail/relay/>` to the server where the relay is running,
and copy the ``chatmail.ini`` file from your local chatmail/relay repository there.

If you made local changes to the repository,
you can store them in a file with ``git diff origin/main > local-changes.patch``,
copy the file to the repository on the server,
and run ``git apply local-changes.patch``.

Then you can proceed with the `installation steps <setup>`.
Loading