Skip to content

Commit 3637bba

Browse files
committed
move dovecot deployer out to dovecot/ directory
1 parent e2b157b commit 3637bba

File tree

4 files changed

+197
-178
lines changed

4 files changed

+197
-178
lines changed

cmdeploy/src/cmdeploy/basedeploy.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,63 @@
11
import importlib.resources
2+
import io
23
import os
34

4-
from pyinfra.operations import server
5+
from pyinfra.operations import files, server, systemd
56

67

78
def get_resource(arg, pkg=__package__):
89
return importlib.resources.files(pkg).joinpath(arg)
910

1011

12+
def _configure_remote_units(mail_domain, units) -> None:
13+
remote_base_dir = "/usr/local/lib/chatmaild"
14+
remote_venv_dir = f"{remote_base_dir}/venv"
15+
remote_chatmail_inipath = f"{remote_base_dir}/chatmail.ini"
16+
root_owned = dict(user="root", group="root", mode="644")
17+
18+
# install systemd units
19+
for fn in units:
20+
execpath = fn if fn != "filtermail-incoming" else "filtermail"
21+
params = dict(
22+
execpath=f"{remote_venv_dir}/bin/{execpath}",
23+
config_path=remote_chatmail_inipath,
24+
remote_venv_dir=remote_venv_dir,
25+
mail_domain=mail_domain,
26+
)
27+
28+
basename = fn if "." in fn else f"{fn}.service"
29+
30+
source_path = get_resource(f"service/{basename}.f")
31+
content = source_path.read_text().format(**params).encode()
32+
33+
files.put(
34+
name=f"Upload {basename}",
35+
src=io.BytesIO(content),
36+
dest=f"/etc/systemd/system/{basename}",
37+
**root_owned,
38+
)
39+
40+
41+
def _activate_remote_units(units) -> None:
42+
# activate systemd units
43+
for fn in units:
44+
basename = fn if "." in fn else f"{fn}.service"
45+
46+
if fn == "chatmail-expire" or fn == "chatmail-fsreport":
47+
# don't auto-start but let the corresponding timer trigger execution
48+
enabled = False
49+
else:
50+
enabled = True
51+
systemd.service(
52+
name=f"Setup {basename}",
53+
service=basename,
54+
running=enabled,
55+
enabled=enabled,
56+
restarted=enabled,
57+
daemon_reload=True,
58+
)
59+
60+
1161
class Deployment:
1262
def install(self, deployer):
1363
# optional 'required_users' contains a list of (user, group, secondary-group-list) tuples.

cmdeploy/src/cmdeploy/deployers.py

Lines changed: 8 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Chat Mail pyinfra deploy.
33
"""
44

5-
import io
65
import shutil
76
import subprocess
87
import sys
@@ -13,14 +12,20 @@
1312
from pyinfra import facts, host, logger
1413
from pyinfra.api import FactBase
1514
from pyinfra.facts.files import Sha256File
16-
from pyinfra.facts.server import Sysctl
1715
from pyinfra.facts.systemd import SystemdEnabled
1816
from pyinfra.operations import apt, files, pip, server, systemd
1917

2018
from cmdeploy.cmdeploy import Out
2119

2220
from .acmetool import AcmetoolDeployer
23-
from .basedeploy import Deployer, Deployment, get_resource
21+
from .basedeploy import (
22+
Deployer,
23+
Deployment,
24+
_activate_remote_units,
25+
_configure_remote_units,
26+
get_resource,
27+
)
28+
from .dovecot.deployer import DovecotDeployer
2429
from .opendkim.deployer import OpendkimDeployer
2530
from .postfix.deployer import PostfixDeployer
2631
from .www import build_webpages, find_merge_conflict, get_paths
@@ -132,55 +137,6 @@ def _configure_remote_venv_with_chatmaild(config) -> None:
132137
)
133138

134139

135-
def _configure_remote_units(mail_domain, units) -> None:
136-
remote_base_dir = "/usr/local/lib/chatmaild"
137-
remote_venv_dir = f"{remote_base_dir}/venv"
138-
remote_chatmail_inipath = f"{remote_base_dir}/chatmail.ini"
139-
root_owned = dict(user="root", group="root", mode="644")
140-
141-
# install systemd units
142-
for fn in units:
143-
execpath = fn if fn != "filtermail-incoming" else "filtermail"
144-
params = dict(
145-
execpath=f"{remote_venv_dir}/bin/{execpath}",
146-
config_path=remote_chatmail_inipath,
147-
remote_venv_dir=remote_venv_dir,
148-
mail_domain=mail_domain,
149-
)
150-
151-
basename = fn if "." in fn else f"{fn}.service"
152-
153-
source_path = get_resource(f"service/{basename}.f")
154-
content = source_path.read_text().format(**params).encode()
155-
156-
files.put(
157-
name=f"Upload {basename}",
158-
src=io.BytesIO(content),
159-
dest=f"/etc/systemd/system/{basename}",
160-
**root_owned,
161-
)
162-
163-
164-
def _activate_remote_units(units) -> None:
165-
# activate systemd units
166-
for fn in units:
167-
basename = fn if "." in fn else f"{fn}.service"
168-
169-
if fn == "chatmail-expire" or fn == "chatmail-fsreport":
170-
# don't auto-start but let the corresponding timer trigger execution
171-
enabled = False
172-
else:
173-
enabled = True
174-
systemd.service(
175-
name=f"Setup {basename}",
176-
service=basename,
177-
running=enabled,
178-
enabled=enabled,
179-
restarted=enabled,
180-
daemon_reload=True,
181-
)
182-
183-
184140
class UnboundDeployer(Deployer):
185141
def install(self):
186142
# Run local DNS resolver `unbound`.
@@ -252,131 +208,6 @@ def activate(self):
252208
)
253209

254210

255-
def _install_dovecot_package(package: str, arch: str):
256-
arch = "amd64" if arch == "x86_64" else arch
257-
arch = "arm64" if arch == "aarch64" else arch
258-
url = f"https://download.delta.chat/dovecot/dovecot-{package}_2.3.21%2Bdfsg1-3_{arch}.deb"
259-
deb_filename = "/root/" + url.split("/")[-1]
260-
261-
match (package, arch):
262-
case ("core", "amd64"):
263-
sha256 = "dd060706f52a306fa863d874717210b9fe10536c824afe1790eec247ded5b27d"
264-
case ("core", "arm64"):
265-
sha256 = "e7548e8a82929722e973629ecc40fcfa886894cef3db88f23535149e7f730dc9"
266-
case ("imapd", "amd64"):
267-
sha256 = "8d8dc6fc00bbb6cdb25d345844f41ce2f1c53f764b79a838eb2a03103eebfa86"
268-
case ("imapd", "arm64"):
269-
sha256 = "178fa877ddd5df9930e8308b518f4b07df10e759050725f8217a0c1fb3fd707f"
270-
case ("lmtpd", "amd64"):
271-
sha256 = "2f69ba5e35363de50962d42cccbfe4ed8495265044e244007d7ccddad77513ab"
272-
case ("lmtpd", "arm64"):
273-
sha256 = "89f52fb36524f5877a177dff4a713ba771fd3f91f22ed0af7238d495e143b38f"
274-
case _:
275-
apt.packages(packages=[f"dovecot-{package}"])
276-
return
277-
278-
files.download(
279-
name=f"Download dovecot-{package}",
280-
src=url,
281-
dest=deb_filename,
282-
sha256sum=sha256,
283-
cache_time=60 * 60 * 24 * 365 * 10, # never redownload the package
284-
)
285-
286-
apt.deb(name=f"Install dovecot-{package}", src=deb_filename)
287-
288-
289-
def _configure_dovecot(config: Config, debug: bool = False) -> bool:
290-
"""Configures Dovecot IMAP server."""
291-
need_restart = False
292-
293-
main_config = files.template(
294-
src=get_resource("dovecot/dovecot.conf.j2"),
295-
dest="/etc/dovecot/dovecot.conf",
296-
user="root",
297-
group="root",
298-
mode="644",
299-
config=config,
300-
debug=debug,
301-
disable_ipv6=config.disable_ipv6,
302-
)
303-
need_restart |= main_config.changed
304-
auth_config = files.put(
305-
src=get_resource("dovecot/auth.conf"),
306-
dest="/etc/dovecot/auth.conf",
307-
user="root",
308-
group="root",
309-
mode="644",
310-
)
311-
need_restart |= auth_config.changed
312-
lua_push_notification_script = files.put(
313-
src=get_resource("dovecot/push_notification.lua"),
314-
dest="/etc/dovecot/push_notification.lua",
315-
user="root",
316-
group="root",
317-
mode="644",
318-
)
319-
need_restart |= lua_push_notification_script.changed
320-
321-
# as per https://doc.dovecot.org/configuration_manual/os/
322-
# it is recommended to set the following inotify limits
323-
for name in ("max_user_instances", "max_user_watches"):
324-
key = f"fs.inotify.{name}"
325-
if host.get_fact(Sysctl)[key] > 65535:
326-
# Skip updating limits if already sufficient
327-
# (enables running in incus containers where sysctl readonly)
328-
continue
329-
server.sysctl(
330-
name=f"Change {key}",
331-
key=key,
332-
value=65535,
333-
persist=True,
334-
)
335-
336-
timezone_env = files.line(
337-
name="Set TZ environment variable",
338-
path="/etc/environment",
339-
line="TZ=:/etc/localtime",
340-
)
341-
need_restart |= timezone_env.changed
342-
343-
return need_restart
344-
345-
346-
class DovecotDeployer(Deployer):
347-
def __init__(self, config, disable_mail):
348-
self.config = config
349-
self.disable_mail = disable_mail
350-
self.units = ["doveauth"]
351-
352-
def install(self):
353-
arch = host.get_fact(facts.server.Arch)
354-
if not "dovecot.service" in host.get_fact(SystemdEnabled):
355-
_install_dovecot_package("core", arch)
356-
_install_dovecot_package("imapd", arch)
357-
_install_dovecot_package("lmtpd", arch)
358-
359-
def configure(self):
360-
_configure_remote_units(self.config.mail_domain, self.units)
361-
self.need_restart = _configure_dovecot(self.config)
362-
363-
def activate(self):
364-
_activate_remote_units(self.units)
365-
366-
restart = False if self.disable_mail else self.need_restart
367-
368-
systemd.service(
369-
name="disable dovecot for now"
370-
if self.disable_mail
371-
else "Start and enable Dovecot",
372-
service="dovecot.service",
373-
running=False if self.disable_mail else True,
374-
enabled=False if self.disable_mail else True,
375-
restarted=restart,
376-
)
377-
self.need_restart = False
378-
379-
380211
def _configure_nginx(config: Config, debug: bool = False) -> bool:
381212
"""Configures nginx HTTP server."""
382213
need_restart = False
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#

0 commit comments

Comments
 (0)