mirror of
https://github.com/chatmail/relay.git
synced 2026-05-19 12:28:06 +00:00
refactor: deployer improvements (VM detection, mailboxes dir ensured to be there, proper unbound on ipv4)
This commit is contained in:
@@ -111,7 +111,6 @@ def run_cmd(args, out):
|
|||||||
if ssh_host in ["localhost", "@docker"]:
|
if ssh_host in ["localhost", "@docker"]:
|
||||||
if ssh_host == "@docker":
|
if ssh_host == "@docker":
|
||||||
env["CHATMAIL_NOPORTCHECK"] = "True"
|
env["CHATMAIL_NOPORTCHECK"] = "True"
|
||||||
env["CHATMAIL_NOSYSCTL"] = "True"
|
|
||||||
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"):
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from .basedeploy import (
|
|||||||
Deployer,
|
Deployer,
|
||||||
Deployment,
|
Deployment,
|
||||||
activate_remote_units,
|
activate_remote_units,
|
||||||
|
blocked_service_startup,
|
||||||
configure_remote_units,
|
configure_remote_units,
|
||||||
get_resource,
|
get_resource,
|
||||||
has_systemd,
|
has_systemd,
|
||||||
@@ -149,33 +150,16 @@ class UnboundDeployer(Deployer):
|
|||||||
self.need_restart = False
|
self.need_restart = False
|
||||||
|
|
||||||
def install(self):
|
def install(self):
|
||||||
# Run local DNS resolver `unbound`.
|
# Run local DNS resolver `unbound`. `resolvconf` takes care of
|
||||||
# `resolvconf` takes care of setting up /etc/resolv.conf
|
# setting up /etc/resolv.conf to use 127.0.0.1 as the resolver.
|
||||||
# to use 127.0.0.1 as the resolver.
|
|
||||||
|
|
||||||
#
|
# On an IPv4-only system, if unbound is started but not configured,
|
||||||
# On an IPv4-only system, if unbound is started but not
|
# it causes subsequent steps to fail to resolve hosts.
|
||||||
# configured, it causes subsequent steps to fail to resolve hosts.
|
with blocked_service_startup():
|
||||||
# Here, we use policy-rc.d to prevent unbound from starting up
|
apt.packages(
|
||||||
# on initial install. Later, we will configure it and start it.
|
name="Install unbound",
|
||||||
#
|
packages=["unbound", "unbound-anchor", "dnsutils"],
|
||||||
# For documentation about policy-rc.d, see:
|
)
|
||||||
# https://people.debian.org/~hmh/invokerc.d-policyrc.d-specification.txt
|
|
||||||
#
|
|
||||||
files.put(
|
|
||||||
src=get_resource("policy-rc.d"),
|
|
||||||
dest="/usr/sbin/policy-rc.d",
|
|
||||||
user="root",
|
|
||||||
group="root",
|
|
||||||
mode="755",
|
|
||||||
)
|
|
||||||
|
|
||||||
apt.packages(
|
|
||||||
name="Install unbound",
|
|
||||||
packages=["unbound", "unbound-anchor", "dnsutils"],
|
|
||||||
)
|
|
||||||
|
|
||||||
files.file("/usr/sbin/policy-rc.d", present=False)
|
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
server.shell(
|
server.shell(
|
||||||
@@ -474,8 +458,9 @@ class ChatmailDeployer(Deployer):
|
|||||||
("iroh", None, None),
|
("iroh", None, None),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, mail_domain):
|
def __init__(self, config):
|
||||||
self.mail_domain = mail_domain
|
self.config = config
|
||||||
|
self.mail_domain = config.mail_domain
|
||||||
|
|
||||||
def install(self):
|
def install(self):
|
||||||
files.put(
|
files.put(
|
||||||
@@ -500,6 +485,16 @@ class ChatmailDeployer(Deployer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
|
# metadata crashes if the mailboxes dir does not exist
|
||||||
|
files.directory(
|
||||||
|
name="Ensure vmail mailbox directory exists",
|
||||||
|
path=str(self.config.mailboxes_dir),
|
||||||
|
user="vmail",
|
||||||
|
group="vmail",
|
||||||
|
mode="700",
|
||||||
|
present=True,
|
||||||
|
)
|
||||||
|
|
||||||
# This file is used by auth proxy.
|
# This file is used by auth proxy.
|
||||||
# https://wiki.debian.org/EtcMailName
|
# https://wiki.debian.org/EtcMailName
|
||||||
server.shell(
|
server.shell(
|
||||||
@@ -629,7 +624,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool, website_only: bool) -
|
|||||||
tls_deployer = get_tls_deployer(config, mail_domain)
|
tls_deployer = get_tls_deployer(config, mail_domain)
|
||||||
|
|
||||||
all_deployers = [
|
all_deployers = [
|
||||||
ChatmailDeployer(mail_domain),
|
ChatmailDeployer(config),
|
||||||
LegacyRemoveDeployer(),
|
LegacyRemoveDeployer(),
|
||||||
FiltermailDeployer(),
|
FiltermailDeployer(),
|
||||||
JournaldDeployer(),
|
JournaldDeployer(),
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import io
|
import io
|
||||||
import os
|
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
from chatmaild.config import Config
|
from chatmaild.config import Config
|
||||||
from pyinfra import host
|
from pyinfra import host
|
||||||
from pyinfra.facts.deb import DebPackages
|
from pyinfra.facts.deb import DebPackages
|
||||||
from pyinfra.facts.server import Arch, Sysctl
|
from pyinfra.facts.server import Arch, Command, Sysctl
|
||||||
from pyinfra.operations import apt, files, server, systemd
|
from pyinfra.operations import apt, files, server, systemd
|
||||||
|
|
||||||
from cmdeploy.basedeploy import (
|
from cmdeploy.basedeploy import (
|
||||||
@@ -128,7 +127,18 @@ def _download_dovecot_package(package: str, arch: str):
|
|||||||
return deb_filename
|
return deb_filename
|
||||||
|
|
||||||
|
|
||||||
def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
|
def _can_set_inotify_limits() -> bool:
|
||||||
|
is_container = (
|
||||||
|
host.get_fact(
|
||||||
|
Command,
|
||||||
|
"systemd-detect-virt --container --quiet 2>/dev/null && echo yes || true",
|
||||||
|
)
|
||||||
|
== "yes"
|
||||||
|
)
|
||||||
|
return not is_container
|
||||||
|
|
||||||
|
|
||||||
|
def _configure_dovecot(config: Config, debug: bool = False) -> tuple[bool, bool]:
|
||||||
"""Configures Dovecot IMAP server."""
|
"""Configures Dovecot IMAP server."""
|
||||||
need_restart = False
|
need_restart = False
|
||||||
daemon_reload = False
|
daemon_reload = False
|
||||||
@@ -163,19 +173,25 @@ def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
|
|||||||
|
|
||||||
# as per https://doc.dovecot.org/2.3/configuration_manual/os/
|
# as per https://doc.dovecot.org/2.3/configuration_manual/os/
|
||||||
# it is recommended to set the following inotify limits
|
# it is recommended to set the following inotify limits
|
||||||
if not os.environ.get("CHATMAIL_NOSYSCTL"):
|
can_modify = _can_set_inotify_limits()
|
||||||
for name in ("max_user_instances", "max_user_watches"):
|
for name in ("max_user_instances", "max_user_watches"):
|
||||||
key = f"fs.inotify.{name}"
|
key = f"fs.inotify.{name}"
|
||||||
if host.get_fact(Sysctl)[key] > 65535:
|
value = host.get_fact(Sysctl)[key]
|
||||||
# Skip updating limits if already sufficient
|
if value > 65534:
|
||||||
# (enables running in incus containers where sysctl readonly)
|
continue
|
||||||
continue
|
if not can_modify:
|
||||||
server.sysctl(
|
print(
|
||||||
name=f"Change {key}",
|
"\n!!!! refusing to attempt sysctl setting in containers\n"
|
||||||
key=key,
|
f"!!!! dovecot: sysctl {key!r}={value}, should be >65534 for production setups\n"
|
||||||
value=65535,
|
"!!!!"
|
||||||
persist=True,
|
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
|
server.sysctl(
|
||||||
|
name=f"Change {key}",
|
||||||
|
key=key,
|
||||||
|
value=65535,
|
||||||
|
persist=True,
|
||||||
|
)
|
||||||
|
|
||||||
timezone_env = files.line(
|
timezone_env = files.line(
|
||||||
name="Set TZ environment variable",
|
name="Set TZ environment variable",
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ def openssl_selfsigned_args(domain, cert_path, key_path, days=36500):
|
|||||||
"-keyout", str(key_path),
|
"-keyout", str(key_path),
|
||||||
"-out", str(cert_path),
|
"-out", str(cert_path),
|
||||||
"-subj", f"/CN={domain}",
|
"-subj", f"/CN={domain}",
|
||||||
|
# Mark as end-entity cert so it cannot be used as a CA to sign others.
|
||||||
|
"-addext", "basicConstraints=critical,CA:FALSE",
|
||||||
"-addext", "extendedKeyUsage=serverAuth,clientAuth",
|
"-addext", "extendedKeyUsage=serverAuth,clientAuth",
|
||||||
"-addext",
|
"-addext",
|
||||||
f"subjectAltName=DNS:{domain},DNS:www.{domain},DNS:mta-sts.{domain}",
|
f"subjectAltName=DNS:{domain},DNS:www.{domain},DNS:mta-sts.{domain}",
|
||||||
|
|||||||
Reference in New Issue
Block a user