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 04451ad537
commit 84ab4bb6b8
2 changed files with 79 additions and 62 deletions

View File

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

View File

@@ -2,66 +2,79 @@ import importlib.resources
from pyinfra.operations import apt, files, server, systemd 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.put( class AcmetoolDeployer(Deployer):
src=importlib.resources.files(__package__).joinpath("acmetool.cron").open("rb"), def __init__(self, *, email, domains, **kwargs):
dest="/etc/cron.d/acmetool", super().__init__(**kwargs)
user="root", self.domains = domains
group="root", self.email = email
mode="644", self.need_restart = False
)
files.put( @staticmethod
src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"), def install_impl():
dest="/usr/lib/acme/hooks/nginx", apt.packages(
user="root", name="Install acmetool",
group="root", packages=["acmetool"],
mode="744", )
)
files.template( def configure_impl(self):
src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"), files.put(
dest="/var/lib/acme/conf/responses", src=importlib.resources.files(__package__).joinpath("acmetool.cron").open("rb"),
user="root", dest="/etc/cron.d/acmetool",
group="root", user="root",
mode="644", group="root",
email=email, mode="644",
) )
files.template( files.put(
src=importlib.resources.files(__package__).joinpath("target.yaml.j2"), src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"),
dest="/var/lib/acme/conf/target", dest="/usr/lib/acme/hooks/nginx",
user="root", user="root",
group="root", group="root",
mode="644", mode="744",
) )
service_file = files.put( files.template(
src=importlib.resources.files(__package__).joinpath( src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"),
"acmetool-redirector.service" dest="/var/lib/acme/conf/responses",
), user="root",
dest="/etc/systemd/system/acmetool-redirector.service", group="root",
user="root", mode="644",
group="root", email=self.email,
mode="644", )
)
systemd.service( files.template(
name="Setup acmetool-redirector service", src=importlib.resources.files(__package__).joinpath("target.yaml.j2"),
service="acmetool-redirector.service", dest="/var/lib/acme/conf/target",
running=True, user="root",
enabled=True, group="root",
restarted=service_file.changed, mode="644",
) )
server.shell( service_file = files.put(
name=f"Request certificate for: {', '.join(domains)}", src=importlib.resources.files(__package__).joinpath(
commands=[f"acmetool want --xlog.severity=debug {' '.join(domains)}"], "acmetool-redirector.service"
) ),
dest="/etc/systemd/system/acmetool-redirector.service",
user="root",
group="root",
mode="644",
)
self.need_restart = service_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,
)
self.need_restart = False
server.shell(
name=f"Request certificate for: {', '.join(self.domains)}",
commands=[f"acmetool want --xlog.severity=debug {' '.join(self.domains)}"],
)