From 45660731d24cdfa77445f32e0cac25a7c6b7d9a5 Mon Sep 17 00:00:00 2001 From: missytake Date: Tue, 17 Feb 2026 20:33:16 +0100 Subject: [PATCH 1/5] cmdeploy: add ssh_host chatmail.ini option to deploy remotely --- chatmaild/src/chatmaild/config.py | 1 + chatmaild/src/chatmaild/ini/chatmail.ini.f | 3 +++ cmdeploy/src/cmdeploy/cmdeploy.py | 8 ++++---- cmdeploy/src/cmdeploy/tests/plugin.py | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index 2aef0012d..5d29876b0 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -16,6 +16,7 @@ class Config: def __init__(self, inipath, params): self._inipath = inipath self.mail_domain = params["mail_domain"] + self.ssh_host = params.get("ssh_host", self.mail_domain) self.max_user_send_per_minute = int(params.get("max_user_send_per_minute", 60)) self.max_user_send_burst_size = int(params.get("max_user_send_burst_size", 10)) self.max_mailbox_size = params.get("max_mailbox_size", "500M") diff --git a/chatmaild/src/chatmaild/ini/chatmail.ini.f b/chatmaild/src/chatmaild/ini/chatmail.ini.f index 29d7baa9e..754aaa2ac 100644 --- a/chatmaild/src/chatmaild/ini/chatmail.ini.f +++ b/chatmaild/src/chatmaild/ini/chatmail.ini.f @@ -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 + # # If you only do private test deploys, you don't need to modify any settings below # diff --git a/cmdeploy/src/cmdeploy/cmdeploy.py b/cmdeploy/src/cmdeploy/cmdeploy.py index 260ef5612..bc81cc006 100644 --- a/cmdeploy/src/cmdeploy/cmdeploy.py +++ b/cmdeploy/src/cmdeploy/cmdeploy.py @@ -88,7 +88,7 @@ def run_cmd_options(parser): 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 + 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" @@ -109,7 +109,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 in ["localhost", "@docker"]: + if ssh_host in ["localhost", "@local", "@docker"]: cmd = f"{pyinf} @local {deploy_path} -y" if version.parse(pyinfra.__version__) < version.parse("3"): @@ -150,7 +150,7 @@ def dns_cmd_options(parser): def dns_cmd(args, out): """Check DNS entries and optionally generate dns zone file.""" - 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" @@ -187,7 +187,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 + 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}") diff --git a/cmdeploy/src/cmdeploy/tests/plugin.py b/cmdeploy/src/cmdeploy/tests/plugin.py index 60d27efca..ccd201c43 100644 --- a/cmdeploy/src/cmdeploy/tests/plugin.py +++ b/cmdeploy/src/cmdeploy/tests/plugin.py @@ -55,8 +55,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 From 108cc5ffde94751c5b5fce3cd100baa9ef9b05b8 Mon Sep 17 00:00:00 2001 From: missytake Date: Mon, 16 Feb 2026 15:57:25 +0100 Subject: [PATCH 2/5] docs: cmdeploy dns + test are kind of necessary --- doc/source/getting_started.rst | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst index 69b019d72..993673d10 100644 --- a/doc/source/getting_started.rst +++ b/doc/source/getting_started.rst @@ -98,26 +98,31 @@ steps. Please substitute it with your own domain. configure at your DNS provider (it can take some time until they are public). -Other helpful commands ----------------------- +Next Steps +---------- -To check the status of your deployment server running the chatmail service: +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 -To test whether your chatmail service is working correctly: +Other Helpful Commands +---------------------- + +To check the status of your chatmail relay: :: - scripts/cmdeploy test + scripts/cmdeploy status + To measure the performance of your chatmail service: From 0a4e67dd3034cdd5bbc288807a3574e7ec05ceb5 Mon Sep 17 00:00:00 2001 From: missytake Date: Mon, 16 Feb 2026 15:52:25 +0100 Subject: [PATCH 3/5] docs: use ssh_host = localhost in getting started docs remove mentions of the build machine / deployment server separation --- doc/source/getting_started.rst | 48 +++++++--------------------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst index 993673d10..028960671 100644 --- a/doc/source/getting_started.rst +++ b/doc/source/getting_started.rst @@ -16,18 +16,11 @@ You will need the following: - Control over a domain through a DNS provider of your choice. -- A Debian 12 **deployment server** with reachable SMTP/SUBMISSIONS/IMAPS/HTTPS ports. +- 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 `_) - Setup with ``scripts/cmdeploy`` ------------------------------------- @@ -35,7 +28,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. @@ -55,22 +48,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 ``_`` @@ -81,13 +77,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: :: @@ -183,7 +173,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: :: @@ -203,23 +193,3 @@ and all other relays will accept connections from it without requiring certificate verification. This is useful for experimental setups and testing. -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. From 8163db3b465385e976374149f98e180708845b78 Mon Sep 17 00:00:00 2001 From: missytake Date: Mon, 16 Feb 2026 16:57:56 +0100 Subject: [PATCH 4/5] docs: webdev needs to be exposed via nginx if run on the relay --- doc/source/getting_started.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst index 028960671..f38355946 100644 --- a/doc/source/getting_started.rst +++ b/doc/source/getting_started.rst @@ -154,8 +154,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 ---------------- From 026b09ac125d0b5a4b42ad000cf3813d871a6feb Mon Sep 17 00:00:00 2001 From: missytake Date: Wed, 18 Feb 2026 09:29:49 +0100 Subject: [PATCH 5/5] ci: deploy with --ssh-host localhost on staging-ipv4 --- .github/workflows/test-and-deploy-ipv4only.yaml | 8 ++++---- .github/workflows/test-and-deploy.yaml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-and-deploy-ipv4only.yaml b/.github/workflows/test-and-deploy-ipv4only.yaml index 158bab98d..12e971f42 100644 --- a/.github/workflows/test-and-deploy-ipv4only.yaml +++ b/.github/workflows/test-and-deploy-ipv4only.yaml @@ -85,12 +85,12 @@ jobs: ssh root@staging-ipv4.testrun.org "sed -i 's#disable_ipv6 = False#disable_ipv6 = True#' relay/chatmail.ini" ssh root@staging-ipv4.testrun.org "sed -i 's/#\s*mtail_address/mtail_address/' relay/chatmail.ini" - - run: ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy run --verbose --skip-dns-check --ssh-host localhost" + - run: ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy run --verbose --skip-dns-check" - name: set DNS entries run: | ssh root@staging-ipv4.testrun.org chown opendkim:opendkim -R /etc/dkimkeys - ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy dns --zonefile staging-generated.zone --ssh-host localhost" + ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy dns --zonefile staging-generated.zone" ssh root@staging-ipv4.testrun.org cat relay/staging-generated.zone >> .github/workflows/staging-ipv4.testrun.org-default.zone cat .github/workflows/staging-ipv4.testrun.org-default.zone scp .github/workflows/staging-ipv4.testrun.org-default.zone root@ns.testrun.org:/etc/nsd/staging-ipv4.testrun.org.zone @@ -98,8 +98,8 @@ jobs: ssh root@ns.testrun.org systemctl reload nsd - name: cmdeploy test - run: ssh root@staging-ipv4.testrun.org "cd relay && CHATMAIL_DOMAIN2=ci-chatmail.testrun.org scripts/cmdeploy test --slow --ssh-host localhost" + run: ssh root@staging-ipv4.testrun.org "cd relay && CHATMAIL_DOMAIN2=ci-chatmail.testrun.org scripts/cmdeploy test --slow" - name: cmdeploy dns - run: ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy dns -v --ssh-host localhost" + run: ssh root@staging-ipv4.testrun.org "cd relay && scripts/cmdeploy dns -v" diff --git a/.github/workflows/test-and-deploy.yaml b/.github/workflows/test-and-deploy.yaml index d38a88695..aaace98e0 100644 --- a/.github/workflows/test-and-deploy.yaml +++ b/.github/workflows/test-and-deploy.yaml @@ -76,6 +76,7 @@ jobs: - run: | cmdeploy init staging2.testrun.org + sed -i 's/^ssh_host/#ssh_host/' chatmail.ini sed -i 's/#\s*mtail_address/mtail_address/' chatmail.ini - run: cmdeploy run --verbose --skip-dns-check