mirror of
https://github.com/chatmail/relay.git
synced 2026-06-10 21:51:09 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8dcdcba91 | |||
| 6a0bf5abe7 | |||
| e7829672f8 | |||
| 62d19fd910 | |||
| e1a8d798d3 |
@@ -10,6 +10,7 @@ dependencies = [
|
|||||||
"filelock",
|
"filelock",
|
||||||
"requests",
|
"requests",
|
||||||
"crypt-r >= 3.13.1 ; python_version >= '3.11'",
|
"crypt-r >= 3.13.1 ; python_version >= '3.11'",
|
||||||
|
"domain-validator",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from random import randint
|
|
||||||
|
|
||||||
import iniconfig
|
import iniconfig
|
||||||
|
from domain_validator import DomainValidator
|
||||||
|
|
||||||
from chatmaild.user import User
|
from chatmaild.user import User
|
||||||
|
|
||||||
@@ -19,12 +19,14 @@ class Config:
|
|||||||
params = dict(params)
|
params = dict(params)
|
||||||
raw_domain = params.pop("mail_domain")
|
raw_domain = params.pop("mail_domain")
|
||||||
self.mail_domain_bare = raw_domain
|
self.mail_domain_bare = raw_domain
|
||||||
|
self.ssh_host = params.pop("ssh_host", raw_domain)
|
||||||
|
|
||||||
if is_valid_ipv4(raw_domain):
|
if is_valid_ipv4(raw_domain):
|
||||||
self.ipv4_relay = raw_domain
|
self.ipv4_relay = raw_domain
|
||||||
self.mail_domain = f"[{raw_domain}]"
|
self.mail_domain = f"[{raw_domain}]"
|
||||||
self.postfix_myhostname = ipaddress.IPv4Address(raw_domain).reverse_pointer
|
self.postfix_myhostname = ipaddress.IPv4Address(raw_domain).reverse_pointer
|
||||||
else:
|
else:
|
||||||
|
DomainValidator().validate_domain_re(raw_domain)
|
||||||
self.ipv4_relay = None
|
self.ipv4_relay = None
|
||||||
self.mail_domain = raw_domain
|
self.mail_domain = raw_domain
|
||||||
self.postfix_myhostname = raw_domain
|
self.postfix_myhostname = raw_domain
|
||||||
@@ -42,11 +44,6 @@ class Config:
|
|||||||
self.username_max_length = int(params.pop("username_max_length", 9))
|
self.username_max_length = int(params.pop("username_max_length", 9))
|
||||||
self.password_min_length = int(params.pop("password_min_length", 9))
|
self.password_min_length = int(params.pop("password_min_length", 9))
|
||||||
self.www_folder = params.pop("www_folder", "")
|
self.www_folder = params.pop("www_folder", "")
|
||||||
|
|
||||||
self.imap_port = int(params.pop("imap_port", 143))
|
|
||||||
self.imaps_port = int(params.pop("imaps_port", 993))
|
|
||||||
self.smtp_port = int(params.pop("smtp_port", 587))
|
|
||||||
self.smtps_port = int(params.pop("smtps_port", 465))
|
|
||||||
self.filtermail_smtp_port = int(params.pop("filtermail_smtp_port", "10080"))
|
self.filtermail_smtp_port = int(params.pop("filtermail_smtp_port", "10080"))
|
||||||
self.filtermail_smtp_port_incoming = int(
|
self.filtermail_smtp_port_incoming = int(
|
||||||
params.pop("filtermail_smtp_port_incoming", "10081")
|
params.pop("filtermail_smtp_port_incoming", "10081")
|
||||||
@@ -144,15 +141,8 @@ def parse_size_mb(limit):
|
|||||||
|
|
||||||
def write_initial_config(inipath, mail_domain, overrides):
|
def write_initial_config(inipath, mail_domain, overrides):
|
||||||
"""Write out default config file, using the specified config value overrides."""
|
"""Write out default config file, using the specified config value overrides."""
|
||||||
content = get_default_config_content(mail_domain, **overrides).splitlines()
|
content = get_default_config_content(mail_domain, **overrides)
|
||||||
used_ports = [25, 53, 80, 143, 402, 443, 465, 587, 993, 3340, 3903, 3904, 8443, 10080, 10081, 10082, 10083, 10025, 10026]
|
inipath.write_text(content)
|
||||||
for config_key in ["smtp_port", "imap_port", "smtps_port", "imaps_port"]:
|
|
||||||
value = randint(1, 65536)
|
|
||||||
while value in used_ports:
|
|
||||||
value = randint(65535)
|
|
||||||
used_ports.append(value)
|
|
||||||
content.append(f"{config_key} = {value}")
|
|
||||||
inipath.write_text("\n".join(content))
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_config_content(mail_domain, **overrides):
|
def get_default_config_content(mail_domain, **overrides):
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
# mail domain (MUST be set to fully qualified chat mail domain)
|
# mail domain (MUST be set to fully qualified chat mail domain)
|
||||||
mail_domain = {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
|
# If you only do private test deploys, you don't need to modify any settings below
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
"acme-enter-email": "{{ email }}"
|
"acme-enter-email": "{{ email }}"
|
||||||
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.7-June-04-2026.pdf": true
|
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf": true
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ def _warn_unused_settings(unused_keys, out):
|
|||||||
def run_cmd(args, out):
|
def run_cmd(args, out):
|
||||||
"""Deploy chatmail services on the remote server."""
|
"""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)
|
sshexec = get_sshexec(ssh_host)
|
||||||
require_iroh = args.config.enable_iroh_relay
|
require_iroh = args.config.enable_iroh_relay
|
||||||
strict_tls = args.config.tls_cert_mode == "acme"
|
strict_tls = args.config.tls_cert_mode == "acme"
|
||||||
@@ -116,7 +116,7 @@ def run_cmd(args, out):
|
|||||||
pyinf = "pyinfra --dry" if args.dry_run else "pyinfra"
|
pyinf = "pyinfra --dry" if args.dry_run else "pyinfra"
|
||||||
|
|
||||||
cmd = f"{pyinf} --ssh-user root {ssh_host} {deploy_path} -y"
|
cmd = f"{pyinf} --ssh-user root {ssh_host} {deploy_path} -y"
|
||||||
if ssh_host == "localhost":
|
if ssh_host in ["localhost", "@local"]:
|
||||||
cmd = f"{pyinf} @local {deploy_path} -y"
|
cmd = f"{pyinf} @local {deploy_path} -y"
|
||||||
|
|
||||||
if version.parse(pyinfra.__version__) < version.parse("3"):
|
if version.parse(pyinfra.__version__) < version.parse("3"):
|
||||||
@@ -158,7 +158,7 @@ def dns_cmd(args, out):
|
|||||||
ipv4 = args.config.ipv4_relay
|
ipv4 = args.config.ipv4_relay
|
||||||
print(f"[WARNING] {ipv4} is not a domain, skipping DNS checks.")
|
print(f"[WARNING] {ipv4} is not a domain, skipping DNS checks.")
|
||||||
return 0
|
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)
|
sshexec = get_sshexec(ssh_host, verbose=args.verbose)
|
||||||
tls_cert_mode = args.config.tls_cert_mode
|
tls_cert_mode = args.config.tls_cert_mode
|
||||||
strict_tls = tls_cert_mode == "acme"
|
strict_tls = tls_cert_mode == "acme"
|
||||||
@@ -195,7 +195,7 @@ def status_cmd_options(parser):
|
|||||||
def status_cmd(args, out):
|
def status_cmd(args, out):
|
||||||
"""Display status for online chatmail instance."""
|
"""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)
|
sshexec = get_sshexec(ssh_host, verbose=args.verbose)
|
||||||
|
|
||||||
out.green(f"chatmail domain: {args.config.mail_domain}")
|
out.green(f"chatmail domain: {args.config.mail_domain}")
|
||||||
|
|||||||
@@ -495,15 +495,15 @@ def deploy_chatmail(config_path: Path, disable_mail: bool, website_only: bool) -
|
|||||||
if config.tls_cert_mode == "acme":
|
if config.tls_cert_mode == "acme":
|
||||||
port_services.append(("acmetool", 402))
|
port_services.append(("acmetool", 402))
|
||||||
port_services += [
|
port_services += [
|
||||||
(["imap-login", "dovecot"], config.imap_port),
|
(["imap-login", "dovecot"], 143),
|
||||||
# acmetool previously listened on port 80,
|
# acmetool previously listened on port 80,
|
||||||
# so don't complain during upgrade that moved it to port 402
|
# so don't complain during upgrade that moved it to port 402
|
||||||
# and gave the port to nginx.
|
# and gave the port to nginx.
|
||||||
(["acmetool", "nginx"], 80),
|
(["acmetool", "nginx"], 80),
|
||||||
("nginx", 443),
|
("nginx", 443),
|
||||||
(["master", "smtpd"], config.smtp_port),
|
(["master", "smtpd"], 465),
|
||||||
(["master", "smtpd"], config.smtps_port),
|
(["master", "smtpd"], 587),
|
||||||
(["imap-login", "dovecot"], config.imaps_port),
|
(["imap-login", "dovecot"], 993),
|
||||||
("iroh-relay", 3340),
|
("iroh-relay", 3340),
|
||||||
("mtail", 3903),
|
("mtail", 3903),
|
||||||
("stats", 3904),
|
("stats", 3904),
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
<displayShortName>{{ config.mail_domain }}</displayShortName>
|
<displayShortName>{{ config.mail_domain }}</displayShortName>
|
||||||
<incomingServer type="imap">
|
<incomingServer type="imap">
|
||||||
<hostname>{{ config.mail_domain }}</hostname>
|
<hostname>{{ config.mail_domain }}</hostname>
|
||||||
<port>{{ config.imaps_port }}</port>
|
<port>993</port>
|
||||||
<socketType>SSL</socketType>
|
<socketType>SSL</socketType>
|
||||||
<authentication>password-cleartext</authentication>
|
<authentication>password-cleartext</authentication>
|
||||||
<username>%EMAILADDRESS%</username>
|
<username>%EMAILADDRESS%</username>
|
||||||
</incomingServer>
|
</incomingServer>
|
||||||
<incomingServer type="imap">
|
<incomingServer type="imap">
|
||||||
<hostname>{{ config.mail_domain }}</hostname>
|
<hostname>{{ config.mail_domain }}</hostname>
|
||||||
<port>{{ config.imap_port }}</port>
|
<port>143</port>
|
||||||
<socketType>STARTTLS</socketType>
|
<socketType>STARTTLS</socketType>
|
||||||
<authentication>password-cleartext</authentication>
|
<authentication>password-cleartext</authentication>
|
||||||
<username>%EMAILADDRESS%</username>
|
<username>%EMAILADDRESS%</username>
|
||||||
@@ -28,14 +28,14 @@
|
|||||||
</incomingServer>
|
</incomingServer>
|
||||||
<outgoingServer type="smtp">
|
<outgoingServer type="smtp">
|
||||||
<hostname>{{ config.mail_domain }}</hostname>
|
<hostname>{{ config.mail_domain }}</hostname>
|
||||||
<port>{{ config.smtps_port }}</port>
|
<port>465</port>
|
||||||
<socketType>SSL</socketType>
|
<socketType>SSL</socketType>
|
||||||
<authentication>password-cleartext</authentication>
|
<authentication>password-cleartext</authentication>
|
||||||
<username>%EMAILADDRESS%</username>
|
<username>%EMAILADDRESS%</username>
|
||||||
</outgoingServer>
|
</outgoingServer>
|
||||||
<outgoingServer type="smtp">
|
<outgoingServer type="smtp">
|
||||||
<hostname>{{ config.mail_domain }}</hostname>
|
<hostname>{{ config.mail_domain }}</hostname>
|
||||||
<port>{{ config.smtp_port }}</port>
|
<port>587</port>
|
||||||
<socketType>STARTTLS</socketType>
|
<socketType>STARTTLS</socketType>
|
||||||
<authentication>password-cleartext</authentication>
|
<authentication>password-cleartext</authentication>
|
||||||
<username>%EMAILADDRESS%</username>
|
<username>%EMAILADDRESS%</username>
|
||||||
|
|||||||
@@ -31,26 +31,6 @@ stream {
|
|||||||
~\bimap\b 127.0.0.1:993;
|
~\bimap\b 127.0.0.1:993;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
|
||||||
listen {{ config.smtp_port }};
|
|
||||||
proxy_pass 127.0.0.1:587;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen {{ config.imap_port }};
|
|
||||||
proxy_pass 127.0.0.1:143;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen {{ config.smtps_port }};
|
|
||||||
proxy_pass 127.0.0.1:465;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen {{ config.imaps_port }};
|
|
||||||
proxy_pass 127.0.0.1:993;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443;
|
listen 443;
|
||||||
{% if not disable_ipv6 %}
|
{% if not disable_ipv6 %}
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
/^DKIM-Signature:/ IGNORE
|
# List of headers for incoming messages
|
||||||
/^Authentication-Results:/ IGNORE
|
# that must be retained for functionality and compatibility reasons
|
||||||
/^Received:/ IGNORE
|
/^From:/ DUNNO
|
||||||
|
/^Message-Id:/ DUNNO
|
||||||
|
/^Chat-/ DUNNO
|
||||||
|
/^Content-Type:/ DUNNO
|
||||||
|
|
||||||
|
# For receiving clear-text messages (still supported in May 2026)
|
||||||
|
/^Subject:/ DUNNO
|
||||||
|
/^Date:/ DUNNO
|
||||||
|
/^To:/ DUNNO
|
||||||
|
/^CC:/ DUNNO
|
||||||
|
/^References:/ DUNNO
|
||||||
|
/^In-Reply-To:/ DUNNO
|
||||||
|
|
||||||
|
# Senders might support Autocrypt 1 but not RFC9788 (Header Protection)
|
||||||
|
/^Autocrypt:/ DUNNO
|
||||||
|
|
||||||
|
# SecureJoin V2 protocol headers (for backward compatibility)
|
||||||
|
/^Secure-Join/ DUNNO
|
||||||
|
|
||||||
|
# Ignore all other headers
|
||||||
|
/.*/ IGNORE
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from chatmaild.config import is_valid_ipv4, read_config
|
from chatmaild.config import is_valid_ipv4, read_config
|
||||||
|
from domain_validator import DomainValidator
|
||||||
|
|
||||||
|
|
||||||
def format_mail_domain(raw_domain: str) -> str:
|
def format_mail_domain(raw_domain: str) -> str:
|
||||||
if is_valid_ipv4(raw_domain):
|
if is_valid_ipv4(raw_domain):
|
||||||
return f"[{raw_domain}]"
|
return f"[{raw_domain}]"
|
||||||
|
DomainValidator().validate_domain_re(raw_domain)
|
||||||
return raw_domain
|
return raw_domain
|
||||||
|
|
||||||
|
|
||||||
@@ -60,8 +62,8 @@ def maildomain(chatmail_config):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def sshdomain(maildomain):
|
def sshdomain(chatmail_config):
|
||||||
return os.environ.get("CHATMAIL_SSH", maildomain)
|
return os.environ.get("CHATMAIL_SSH", chatmail_config.ssh_host)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -14,21 +14,14 @@ Minimal requirements and prerequisites
|
|||||||
|
|
||||||
You will need the following:
|
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
|
IPv6 is encouraged if available. Chatmail relay servers only require
|
||||||
1GB RAM, one CPU, and perhaps 10GB storage for a few thousand active
|
1GB RAM, one CPU, and perhaps 10GB storage for a few thousand active
|
||||||
chatmail addresses.
|
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:
|
.. _setup:
|
||||||
|
|
||||||
@@ -38,7 +31,7 @@ Setup with ``scripts/cmdeploy``
|
|||||||
We use ``chat.example.org`` as the chatmail domain in the following
|
We use ``chat.example.org`` as the chatmail domain in the following
|
||||||
steps. Please substitute it with your own domain.
|
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
|
The following is an example in the
|
||||||
familiar BIND zone file format with a TTL of 1 hour (3600 seconds).
|
familiar BIND zone file format with a TTL of 1 hour (3600 seconds).
|
||||||
Please substitute your domain and IP addresses.
|
Please substitute your domain and IP addresses.
|
||||||
@@ -58,22 +51,25 @@ steps. Please substitute it with your own domain.
|
|||||||
The ``mta-sts`` CNAME and ``_mta-sts`` TXT records
|
The ``mta-sts`` CNAME and ``_mta-sts`` TXT records
|
||||||
are not needed for such domains.
|
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.
|
virtualenv.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
ssh root@chat.example.org
|
||||||
git clone https://github.com/chatmail/relay
|
git clone https://github.com/chatmail/relay
|
||||||
cd relay
|
cd relay
|
||||||
scripts/initenv.sh
|
scripts/initenv.sh
|
||||||
|
|
||||||
3. On your local build machine (PC), create a chatmail configuration file
|
3. Then, create a chatmail configuration file
|
||||||
``chatmail.ini``:
|
``chatmail.ini``:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
scripts/cmdeploy init chat.example.org # <-- use your domain
|
scripts/cmdeploy init chat.example.org # <-- use your domain
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
To use self-signed TLS certificates
|
To use self-signed TLS certificates
|
||||||
instead of Let's Encrypt,
|
instead of Let's Encrypt,
|
||||||
use a domain name starting with ``_``
|
use a domain name starting with ``_``
|
||||||
@@ -84,13 +80,7 @@ steps. Please substitute it with your own domain.
|
|||||||
See the :doc:`overview`
|
See the :doc:`overview`
|
||||||
for details on certificate provisioning.
|
for details on certificate provisioning.
|
||||||
|
|
||||||
4. Verify that SSH root login to the deployment server server works:
|
4. Now run the deployment script to install the relay to the server:
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
ssh root@chat.example.org # <-- use your domain
|
|
||||||
|
|
||||||
5. From your local build machine, setup and configure the remote deployment server:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@@ -102,7 +92,6 @@ steps. Please substitute it with your own domain.
|
|||||||
public).
|
public).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Docker installation
|
Docker installation
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@@ -110,27 +99,33 @@ 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>`_.
|
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.
|
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
|
|
||||||
|
|
||||||
To display and check all recommended DNS records:
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
scripts/cmdeploy dns
|
scripts/cmdeploy dns
|
||||||
|
|
||||||
To test whether your chatmail service is working correctly:
|
You should also test whether your chatmail service is working correctly:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
scripts/cmdeploy test
|
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:
|
To measure the performance of your chatmail service:
|
||||||
|
|
||||||
::
|
::
|
||||||
@@ -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
|
directory and generating HTML files and copying assets to the
|
||||||
``www/build`` directory.
|
``www/build`` directory.
|
||||||
|
|
||||||
- Starts a browser window automatically where you can “refresh” as
|
- if you are running scripts/cmdeploy webdev on the relay itself,
|
||||||
needed.
|
you need to configure a route in /etc/nginx/nginx.conf
|
||||||
|
to expose the build directory.
|
||||||
|
|
||||||
Custom web pages
|
Custom web pages
|
||||||
----------------
|
----------------
|
||||||
@@ -190,7 +186,7 @@ Disable automatic address creation
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
||||||
If you need to stop address creation, e.g. because some script is wildly
|
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:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@@ -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::
|
If you use such a setup, you must trigger the reload explicitly after renewal::
|
||||||
|
|
||||||
systemctl start tls-cert-reload.service
|
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.
|
|
||||||
|
|||||||
+16
-2
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
Migrating to a new machine
|
Migrating the relay to a new server
|
||||||
===========================
|
===================================
|
||||||
|
|
||||||
This migration tutorial provides a step-wise approach
|
This migration tutorial provides a step-wise approach
|
||||||
to safely migrate a chatmail relay from one remote machine to another.
|
to safely migrate a chatmail relay from one remote machine to another.
|
||||||
@@ -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,
|
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.
|
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>`.
|
||||||
|
|||||||
Reference in New Issue
Block a user