refactor: Add AcmetoolDeployer

- This splits the existing deploy_acmetool() routine into methods for
  the install, configure, and activate stages.
This commit is contained in:
cliffmccarthy
2025-09-08 08:16:59 -05:00
parent 6afd31fb17
commit afc1be2671
2 changed files with 119 additions and 96 deletions

View File

@@ -19,7 +19,7 @@ from pyinfra.facts.server import Sysctl
from pyinfra.facts.systemd import SystemdEnabled
from pyinfra.operations import apt, files, pip, server, systemd
from .acmetool import deploy_acmetool
from .acmetool import AcmetoolDeployer
from .deployer import Deployer
from .www import build_webpages, find_merge_conflict, get_paths
@@ -913,8 +913,14 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
line="nameserver 9.9.9.9",
)
tls_domains = [mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"]
unbound_deployer = UnboundDeployer()
iroh_deployer = IrohDeployer(enable_iroh_relay=config.enable_iroh_relay)
# Deploy acmetool to have TLS certificates.
acmetool_deployer = AcmetoolDeployer(email=config.acme_email, domains=tls_domains)
opendkim_deployer = OpendkimDeployer(mail_domain=mail_domain)
# Dovecot should be started before Postfix
@@ -929,6 +935,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
all_deployers = [
unbound_deployer,
iroh_deployer,
acmetool_deployer,
opendkim_deployer,
dovecot_deployer,
postfix_deployer,
@@ -1013,12 +1020,9 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
iroh_deployer.configure()
iroh_deployer.activate()
# Deploy acmetool to have TLS certificates.
tls_domains = [mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"]
deploy_acmetool(
email=config.acme_email,
domains=tls_domains,
)
acmetool_deployer.install()
acmetool_deployer.configure()
acmetool_deployer.activate()
apt.packages(
# required for setfacl for echobot

View File

@@ -2,104 +2,123 @@ import importlib.resources
from pyinfra.operations import apt, files, server, systemd
from ..deployer import Deployer
def deploy_acmetool(email="", domains=[]):
"""Deploy acmetool."""
apt.packages(
name="Install acmetool",
packages=["acmetool"],
)
files.file(
name="Remove old acmetool cronjob, it is replaced with systemd timer.",
path="/etc/cron.d/acmetool",
present=False,
)
class AcmetoolDeployer(Deployer):
def __init__(self, *, email, domains, **kwargs):
super().__init__(**kwargs)
self.domains = domains
self.email = email
self.need_restart_redirector = False
self.need_restart_reconcile_service = False
self.need_restart_reconcile_timer = False
files.put(
name="Install acmetool hook.",
src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"),
dest="/etc/acme/hooks/nginx",
user="root",
group="root",
mode="755",
)
files.file(
name="Remove acmetool hook from the wrong location where it was previously installed.",
path="/usr/lib/acme/hooks/nginx",
present=False,
)
@staticmethod
def install_impl():
apt.packages(
name="Install acmetool",
packages=["acmetool"],
)
files.template(
src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"),
dest="/var/lib/acme/conf/responses",
user="root",
group="root",
mode="644",
email=email,
)
files.file(
name="Remove old acmetool cronjob, it is replaced with systemd timer.",
path="/etc/cron.d/acmetool",
present=False,
)
files.template(
src=importlib.resources.files(__package__).joinpath("target.yaml.j2"),
dest="/var/lib/acme/conf/target",
user="root",
group="root",
mode="644",
)
files.put(
name="Install acmetool hook.",
src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"),
dest="/etc/acme/hooks/nginx",
user="root",
group="root",
mode="755",
)
files.file(
name="Remove acmetool hook from the wrong location where it was previously installed.",
path="/usr/lib/acme/hooks/nginx",
present=False,
)
service_file = files.put(
src=importlib.resources.files(__package__).joinpath(
"acmetool-redirector.service"
),
dest="/etc/systemd/system/acmetool-redirector.service",
user="root",
group="root",
mode="644",
)
def configure_impl(self):
files.template(
src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"),
dest="/var/lib/acme/conf/responses",
user="root",
group="root",
mode="644",
email=self.email,
)
systemd.service(
name="Setup acmetool-redirector service",
service="acmetool-redirector.service",
running=True,
enabled=True,
restarted=service_file.changed,
)
files.template(
src=importlib.resources.files(__package__).joinpath("target.yaml.j2"),
dest="/var/lib/acme/conf/target",
user="root",
group="root",
mode="644",
)
reconcile_service_file = files.put(
src=importlib.resources.files(__package__).joinpath(
"acmetool-reconcile.service"
),
dest="/etc/systemd/system/acmetool-reconcile.service",
user="root",
group="root",
mode="644",
)
service_file = files.put(
src=importlib.resources.files(__package__).joinpath(
"acmetool-redirector.service"
),
dest="/etc/systemd/system/acmetool-redirector.service",
user="root",
group="root",
mode="644",
)
self.need_restart_redirector = service_file.changed
systemd.service(
name="Setup acmetool-reconcile service",
service="acmetool-reconcile.service",
running=False,
enabled=False,
daemon_reload=reconcile_service_file.changed,
)
reconcile_service_file = files.put(
src=importlib.resources.files(__package__).joinpath(
"acmetool-reconcile.service"
),
dest="/etc/systemd/system/acmetool-reconcile.service",
user="root",
group="root",
mode="644",
)
self.need_restart_reconcile_service = reconcile_service_file.changed
reconcile_timer_file = files.put(
src=importlib.resources.files(__package__).joinpath("acmetool-reconcile.timer"),
dest="/etc/systemd/system/acmetool-reconcile.timer",
user="root",
group="root",
mode="644",
)
reconcile_timer_file = files.put(
src=importlib.resources.files(__package__).joinpath("acmetool-reconcile.timer"),
dest="/etc/systemd/system/acmetool-reconcile.timer",
user="root",
group="root",
mode="644",
)
self.need_restart_reconcile_timer = reconcile_timer_file.changed
systemd.service(
name="Setup acmetool-reconcile timer",
service="acmetool-reconcile.timer",
running=True,
enabled=True,
daemon_reload=reconcile_timer_file.changed,
)
def activate_impl(self):
systemd.service(
name="Setup acmetool-redirector service",
service="acmetool-redirector.service",
running=True,
enabled=True,
restarted=self.need_restart_redirector,
)
self.need_restart_redirector = False
server.shell(
name=f"Request certificate for: {', '.join(domains)}",
commands=[f"acmetool want --xlog.severity=debug {' '.join(domains)}"],
)
systemd.service(
name="Setup acmetool-reconcile service",
service="acmetool-reconcile.service",
running=False,
enabled=False,
daemon_reload=self.need_restart_reconcile_service,
)
self.need_restart_reconcile_service = False
systemd.service(
name="Setup acmetool-reconcile timer",
service="acmetool-reconcile.timer",
running=True,
enabled=True,
daemon_reload=self.need_restart_reconcile_timer,
)
self.need_restart_reconcile_timer = False
server.shell(
name=f"Request certificate for: {', '.join(self.domains)}",
commands=[f"acmetool want --xlog.severity=debug {' '.join(self.domains)}"],
)