From 38246ca8ea33bc2f3bafd94934df4061bf22afdc Mon Sep 17 00:00:00 2001 From: j4n Date: Tue, 17 Mar 2026 14:15:15 +0100 Subject: [PATCH] feat(cmdeploy): Add blocked_service_startup() context manager Prevent services from auto-starting during package installation by installing a policy-rc.d that exits 101. This avoids dovecot startup failures when no TLS cert exists yet (e.g. acmetool failed on first run). Picked out of 62fe113b from hpk/lxcdeploy branch. --- cmdeploy/src/cmdeploy/basedeploy.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cmdeploy/src/cmdeploy/basedeploy.py b/cmdeploy/src/cmdeploy/basedeploy.py index 45654c27..732ed049 100644 --- a/cmdeploy/src/cmdeploy/basedeploy.py +++ b/cmdeploy/src/cmdeploy/basedeploy.py @@ -1,6 +1,7 @@ import importlib.resources import io import os +from contextlib import contextmanager from pyinfra.operations import files, server, systemd @@ -10,6 +11,28 @@ def has_systemd(): return os.path.isdir("/run/systemd/system") +@contextmanager +def blocked_service_startup(): + """Prevent services from auto-starting during package installation. + + Installs a ``/usr/sbin/policy-rc.d`` that exits 101, blocking any + service from being started by the package manager. This avoids bind + conflicts and CPU/RAM spikes during initial setup. The file is removed + when the context exits. + """ + # 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", + ) + yield + files.file("/usr/sbin/policy-rc.d", present=False) + + def get_resource(arg, pkg=__package__): return importlib.resources.files(pkg).joinpath(arg)