mirror of
https://github.com/chatmail/relay.git
synced 2026-05-15 10:24:40 +00:00
Compare commits
23 Commits
link2xt/mx
...
missytake/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f26d2da23b | ||
|
|
3b32387bf8 | ||
|
|
a651fba8b6 | ||
|
|
20f76c83f8 | ||
|
|
b2995551a2 | ||
|
|
c8f46147e0 | ||
|
|
9f6ea8121c | ||
|
|
9c08cbfbec | ||
|
|
c3190dd51a | ||
|
|
5b8de76c22 | ||
|
|
d6205d9a04 | ||
|
|
6a32192e50 | ||
|
|
5c78619750 | ||
|
|
a7b808ebaf | ||
|
|
d11038b7b3 | ||
|
|
88a8dc905b | ||
|
|
a2fbb5dc37 | ||
|
|
97c31e3820 | ||
|
|
08c88caa46 | ||
|
|
8e5174ae44 | ||
|
|
69fe5eac2b | ||
|
|
46f6a07239 | ||
|
|
b268efbc6e |
@@ -17,5 +17,4 @@ $TTL 300
|
|||||||
;; DNS records.
|
;; DNS records.
|
||||||
@ IN A 37.27.95.249
|
@ IN A 37.27.95.249
|
||||||
mta-sts.staging-ipv4.testrun.org. CNAME staging-ipv4.testrun.org.
|
mta-sts.staging-ipv4.testrun.org. CNAME staging-ipv4.testrun.org.
|
||||||
iroh.staging-ipv4.testrun.org. CNAME staging-ipv4.testrun.org.
|
|
||||||
www.staging-ipv4.testrun.org. CNAME staging-ipv4.testrun.org.
|
www.staging-ipv4.testrun.org. CNAME staging-ipv4.testrun.org.
|
||||||
|
|||||||
@@ -17,6 +17,5 @@ $TTL 300
|
|||||||
;; DNS records.
|
;; DNS records.
|
||||||
@ IN A 37.27.24.139
|
@ IN A 37.27.24.139
|
||||||
mta-sts.staging2.testrun.org. CNAME staging2.testrun.org.
|
mta-sts.staging2.testrun.org. CNAME staging2.testrun.org.
|
||||||
iroh.staging2.testrun.org. CNAME staging2.testrun.org.
|
|
||||||
www.staging2.testrun.org. CNAME staging2.testrun.org.
|
www.staging2.testrun.org. CNAME staging2.testrun.org.
|
||||||
|
|
||||||
|
|||||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -2,6 +2,23 @@
|
|||||||
|
|
||||||
## untagged
|
## untagged
|
||||||
|
|
||||||
|
- cmdeploy dns: offer alternative DKIM record format for some web interfaces
|
||||||
|
([#470](https://github.com/deltachat/chatmail/pull/470))
|
||||||
|
|
||||||
|
- migration guide: let opendkim own the DKIM keys directory
|
||||||
|
([#468](https://github.com/deltachat/chatmail/pull/468))
|
||||||
|
|
||||||
|
## 1.5.0 2024-12-20
|
||||||
|
|
||||||
|
- cmdeploy dns: always show recommended DNS records
|
||||||
|
([#463](https://github.com/deltachat/chatmail/pull/463))
|
||||||
|
|
||||||
|
- add `--all` to `cmdeploy dns`
|
||||||
|
([#462](https://github.com/deltachat/chatmail/pull/462))
|
||||||
|
|
||||||
|
- fix `_mta-sts` TXT DNS record
|
||||||
|
([#461](https://github.com/deltachat/chatmail/pull/461)
|
||||||
|
|
||||||
- deploy `iroh-relay` and also update "realtime relay services" in privacy policy.
|
- deploy `iroh-relay` and also update "realtime relay services" in privacy policy.
|
||||||
([#434](https://github.com/deltachat/chatmail/pull/434))
|
([#434](https://github.com/deltachat/chatmail/pull/434))
|
||||||
([#451](https://github.com/deltachat/chatmail/pull/451))
|
([#451](https://github.com/deltachat/chatmail/pull/451))
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ to make sure you can connect with SSH.
|
|||||||
`ssh root@13.37.13.37 tar c /etc/dkimkeys | ssh root@13.12.23.42 tar x -C /etc/`
|
`ssh 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.
|
so the DKIM DNS record stays correct.
|
||||||
|
|
||||||
3. On the new server, run `chown root: -R /var/lib/acme` and `chown root: -R /etc/dkimkeys` to make sure the permissions are correct.
|
3. On the new server, run `chown root: -R /var/lib/acme` and `chown opendkim: -R /etc/dkimkeys` to make sure the permissions are correct.
|
||||||
|
|
||||||
4. Run `cmdeploy run --disable-mail --ssh-host 13.12.23.42` to install chatmail on the new machine.
|
4. 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,
|
postfix and dovecot are disabled for now,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ dependencies = [
|
|||||||
"deltachat-rpc-client",
|
"deltachat-rpc-client",
|
||||||
"filelock",
|
"filelock",
|
||||||
"requests",
|
"requests",
|
||||||
|
"crypt-r",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import crypt
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import crypt_r
|
||||||
|
|
||||||
from .config import Config, read_config
|
from .config import Config, read_config
|
||||||
from .dictproxy import DictProxy
|
from .dictproxy import DictProxy
|
||||||
from .migrate_db import migrate_from_db_to_maildir
|
from .migrate_db import migrate_from_db_to_maildir
|
||||||
@@ -13,7 +14,7 @@ NOCREATE_FILE = "/etc/chatmail-nocreate"
|
|||||||
|
|
||||||
def encrypt_password(password: str):
|
def encrypt_password(password: str):
|
||||||
# https://doc.dovecot.org/configuration_manual/authentication/password_schemes/
|
# https://doc.dovecot.org/configuration_manual/authentication/password_schemes/
|
||||||
passhash = crypt.crypt(password, crypt.METHOD_SHA512)
|
passhash = crypt_r.crypt(password, crypt_r.METHOD_SHA512)
|
||||||
return "{SHA512-CRYPT}" + passhash
|
return "{SHA512-CRYPT}" + passhash
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ def migrate_from_db_to_maildir(config, chunking=10000):
|
|||||||
# don't transfer special/CI accounts
|
# don't transfer special/CI accounts
|
||||||
rows = [row for row in all_rows if row[0][:3] not in ("ci-", "ac_")]
|
rows = [row for row in all_rows if row[0][:3] not in ("ci-", "ac_")]
|
||||||
|
|
||||||
logging.info(f"ignoring {len(all_rows)-len(rows)} CI accounts")
|
logging.info(f"ignoring {len(all_rows) - len(rows)} CI accounts")
|
||||||
logging.info(f"migrating {len(rows)} sqlite database passwords to user dirs")
|
logging.info(f"migrating {len(rows)} sqlite database passwords to user dirs")
|
||||||
|
|
||||||
for i, row in enumerate(rows):
|
for i, row in enumerate(rows):
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from chatmaild.config import Config, read_config
|
from chatmaild.config import Config, read_config
|
||||||
from pyinfra import host, facts
|
from pyinfra import facts, host
|
||||||
from pyinfra.facts.files import File
|
from pyinfra.facts.files import File
|
||||||
from pyinfra.facts.systemd import SystemdEnabled
|
from pyinfra.facts.systemd import SystemdEnabled
|
||||||
from pyinfra.operations import apt, files, pip, server, systemd
|
from pyinfra.operations import apt, files, pip, server, systemd
|
||||||
@@ -78,6 +78,11 @@ def _install_remote_venv_with_chatmaild(config) -> None:
|
|||||||
always_copy=True,
|
always_copy=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
apt.packages(
|
||||||
|
name="install python3-dev to build crypt_r source package",
|
||||||
|
packages=["python3-dev"],
|
||||||
|
)
|
||||||
|
|
||||||
server.shell(
|
server.shell(
|
||||||
name=f"forced pip-install {dist_file.name}",
|
name=f"forced pip-install {dist_file.name}",
|
||||||
commands=[
|
commands=[
|
||||||
@@ -517,9 +522,9 @@ def deploy_iroh_relay(config) -> None:
|
|||||||
need_restart |= systemd_unit.changed
|
need_restart |= systemd_unit.changed
|
||||||
|
|
||||||
iroh_config = files.put(
|
iroh_config = files.put(
|
||||||
name=f"Upload iroh-relay config",
|
name="Upload iroh-relay config",
|
||||||
src=importlib.resources.files(__package__).joinpath("iroh-relay.toml"),
|
src=importlib.resources.files(__package__).joinpath("iroh-relay.toml"),
|
||||||
dest=f"/etc/iroh-relay.toml",
|
dest="/etc/iroh-relay.toml",
|
||||||
user="root",
|
user="root",
|
||||||
group="root",
|
group="root",
|
||||||
mode="644",
|
mode="644",
|
||||||
|
|||||||
@@ -70,6 +70,6 @@ def deploy_acmetool(email="", domains=[]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
server.shell(
|
server.shell(
|
||||||
name=f"Request certificate for: { ', '.join(domains) }",
|
name=f"Request certificate for: {', '.join(domains)}",
|
||||||
commands=[f"acmetool want --xlog.severity=debug { ' '.join(domains)}"],
|
commands=[f"acmetool want --xlog.severity=debug {' '.join(domains)}"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ def run_cmd_options(parser):
|
|||||||
"--disable-mail",
|
"--disable-mail",
|
||||||
dest="disable_mail",
|
dest="disable_mail",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="install/upgrade the server, but disable postfix & dovecot for now"
|
help="install/upgrade the server, but disable postfix & dovecot for now",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--ssh-host",
|
"--ssh-host",
|
||||||
dest="ssh_host",
|
dest="ssh_host",
|
||||||
help="specify an SSH host to deploy to; uses mail_domain from chatmail.ini by default"
|
help="specify an SSH host to deploy to; uses mail_domain from chatmail.ini by default",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ def main():
|
|||||||
"CHATMAIL_INI",
|
"CHATMAIL_INI",
|
||||||
importlib.resources.files("cmdeploy").joinpath("../../../chatmail.ini"),
|
importlib.resources.files("cmdeploy").joinpath("../../../chatmail.ini"),
|
||||||
)
|
)
|
||||||
disable_mail = bool(os.environ.get('CHATMAIL_DISABLE_MAIL'))
|
disable_mail = bool(os.environ.get("CHATMAIL_DISABLE_MAIL"))
|
||||||
|
|
||||||
deploy_chatmail(config_path, disable_mail)
|
deploy_chatmail(config_path, disable_mail)
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ def check_initial_remote_data(remote_data, *, print=print):
|
|||||||
def get_filled_zone_file(remote_data):
|
def get_filled_zone_file(remote_data):
|
||||||
sts_id = remote_data.get("sts_id")
|
sts_id = remote_data.get("sts_id")
|
||||||
if not sts_id:
|
if not sts_id:
|
||||||
sts_id = datetime.datetime.now().strftime("%Y%m%d%H%M")
|
remote_data["sts_id"] = datetime.datetime.now().strftime("%Y%m%d%H%M")
|
||||||
|
|
||||||
template = importlib.resources.files(__package__).joinpath("chatmail.zone.j2")
|
template = importlib.resources.files(__package__).joinpath("chatmail.zone.j2")
|
||||||
content = template.read_text()
|
content = template.read_text()
|
||||||
@@ -49,16 +49,23 @@ def check_full_zone(sshexec, remote_data, out, zonefile) -> int:
|
|||||||
kwargs=dict(zonefile=zonefile, mail_domain=remote_data["mail_domain"]),
|
kwargs=dict(zonefile=zonefile, mail_domain=remote_data["mail_domain"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
returncode = 0
|
||||||
if required_diff:
|
if required_diff:
|
||||||
out.red("Please set required DNS entries at your DNS provider:\n")
|
out.red("Please set required DNS entries at your DNS provider:\n")
|
||||||
for line in required_diff:
|
for line in required_diff:
|
||||||
out(line)
|
out(line)
|
||||||
return 1
|
out("")
|
||||||
elif recommended_diff:
|
returncode = 1
|
||||||
|
if remote_data.get("dkim_entry") in required_diff:
|
||||||
|
out(
|
||||||
|
"If the DKIM entry above does not work with your DNS provider, you can try this one:\n"
|
||||||
|
)
|
||||||
|
out(remote_data.get("web_dkim_entry") + "\n")
|
||||||
|
if recommended_diff:
|
||||||
out("WARNING: these recommended DNS entries are not set:\n")
|
out("WARNING: these recommended DNS entries are not set:\n")
|
||||||
for line in recommended_diff:
|
for line in recommended_diff:
|
||||||
out(line)
|
out(line)
|
||||||
return 0
|
|
||||||
|
|
||||||
out.green("Great! All your DNS entries are verified and correct.")
|
if not (recommended_diff or required_diff):
|
||||||
return 0
|
out.green("Great! All your DNS entries are verified and correct.")
|
||||||
|
return returncode
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ def perform_initial_checks(mail_domain):
|
|||||||
|
|
||||||
res = dict(mail_domain=mail_domain, A=A, AAAA=AAAA, MTA_STS=MTA_STS, WWW=WWW)
|
res = dict(mail_domain=mail_domain, A=A, AAAA=AAAA, MTA_STS=MTA_STS, WWW=WWW)
|
||||||
res["acme_account_url"] = shell("acmetool account-url", fail_ok=True)
|
res["acme_account_url"] = shell("acmetool account-url", fail_ok=True)
|
||||||
res["dkim_entry"] = get_dkim_entry(mail_domain, dkim_selector="opendkim")
|
res["dkim_entry"], res["web_dkim_entry"] = get_dkim_entry(
|
||||||
|
mail_domain, dkim_selector="opendkim"
|
||||||
|
)
|
||||||
|
|
||||||
if not MTA_STS or not WWW or (not A and not AAAA):
|
if not MTA_STS or not WWW or (not A and not AAAA):
|
||||||
return res
|
return res
|
||||||
@@ -48,7 +50,11 @@ def get_dkim_entry(mail_domain, dkim_selector):
|
|||||||
return
|
return
|
||||||
dkim_value_raw = f"v=DKIM1;k=rsa;p={dkim_pubkey};s=email;t=s"
|
dkim_value_raw = f"v=DKIM1;k=rsa;p={dkim_pubkey};s=email;t=s"
|
||||||
dkim_value = '" "'.join(re.findall(".{1,255}", dkim_value_raw))
|
dkim_value = '" "'.join(re.findall(".{1,255}", dkim_value_raw))
|
||||||
return f'{dkim_selector}._domainkey.{mail_domain}. TXT "{dkim_value}"'
|
web_dkim_value = "".join(re.findall(".{1,255}", dkim_value_raw))
|
||||||
|
return (
|
||||||
|
f'{dkim_selector}._domainkey.{mail_domain}. TXT "{dkim_value}"',
|
||||||
|
f'{dkim_selector}._domainkey.{mail_domain}. TXT "{web_dkim_value}"',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def query_dns(typ, domain):
|
def query_dns(typ, domain):
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class TestEndToEndDeltaChat:
|
|||||||
attachsize = 1 * 1024 * 1024
|
attachsize = 1 * 1024 * 1024
|
||||||
num_to_send = quota // attachsize + 2
|
num_to_send = quota // attachsize + 2
|
||||||
lp.sec(f"ac1: send {num_to_send} large files to ac2")
|
lp.sec(f"ac1: send {num_to_send} large files to ac2")
|
||||||
lp.indent(f"per-user quota is assumed to be: {quota/(1024*1024)}MB")
|
lp.indent(f"per-user quota is assumed to be: {quota / (1024 * 1024)}MB")
|
||||||
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
|
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
|
||||||
msgs = []
|
msgs = []
|
||||||
for i in range(num_to_send):
|
for i in range(num_to_send):
|
||||||
@@ -97,7 +97,7 @@ class TestEndToEndDeltaChat:
|
|||||||
|
|
||||||
msg = chat.send_file(str(attachment))
|
msg = chat.send_file(str(attachment))
|
||||||
msgs.append(msg)
|
msgs.append(msg)
|
||||||
lp.indent(f"Sent out msg {i}, size {attachsize/(1024*1024)}MB")
|
lp.indent(f"Sent out msg {i}, size {attachsize / (1024 * 1024)}MB")
|
||||||
|
|
||||||
lp.sec("ac2: check messages are arriving until quota is reached")
|
lp.sec("ac2: check messages are arriving until quota is reached")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user