unbound: check that 53 is not occupied by a different process

This commit is contained in:
missytake
2025-04-10 11:44:54 +02:00
parent f9e885c442
commit 21f9885ffe
3 changed files with 35 additions and 16 deletions

View File

@@ -17,7 +17,7 @@
- Enforce end-to-end encryption between local addresses - Enforce end-to-end encryption between local addresses
([#535](https://github.com/chatmail/server/pull/535)) ([#535](https://github.com/chatmail/server/pull/535))
- Disable NSD so it doesn't block port 53 - unbound: check that port 53 is not occupied by a different process
([#537](https://github.com/chatmail/server/pull/537)) ([#537](https://github.com/chatmail/server/pull/537))
- Limit the bind for the HTTPS server on 8443 to 127.0.0.1 - Limit the bind for the HTTPS server on 8443 to 127.0.0.1

View File

@@ -11,6 +11,7 @@ from pathlib import Path
from chatmaild.config import Config, read_config from chatmaild.config import Config, read_config
from pyinfra import facts, host from pyinfra import facts, host
from pyinfra.api import FactBase
from pyinfra.facts.files import File from pyinfra.facts.files import File
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
@@ -18,6 +19,21 @@ from pyinfra.operations import apt, files, pip, server, systemd
from .acmetool import deploy_acmetool from .acmetool import deploy_acmetool
class Port(FactBase):
"""
Returns the process occuping a port.
"""
def command(self, port: int) -> str:
return (
"ss -lptn 'src :%d' | awk 'NR>1 {print $6,$7}' | sed 's/users:((\"//;s/\".*//'"
% (port,)
)
def process(self, output: [str]) -> str:
return output[0]
def _build_chatmaild(dist_dir) -> None: def _build_chatmaild(dist_dir) -> None:
dist_dir = Path(dist_dir).resolve() dist_dir = Path(dist_dir).resolve()
if dist_dir.exists(): if dist_dir.exists():
@@ -230,7 +246,6 @@ def _configure_opendkim(domain: str, dkim_selector: str = "dkim") -> bool:
) )
need_restart |= service_file.changed need_restart |= service_file.changed
return need_restart return need_restart
@@ -588,12 +603,12 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
# Run local DNS resolver `unbound`. # Run local DNS resolver `unbound`.
# `resolvconf` takes care of setting up /etc/resolv.conf # `resolvconf` takes care of setting up /etc/resolv.conf
# to use 127.0.0.1 as the resolver. # to use 127.0.0.1 as the resolver.
systemd.service( from cmdeploy.cmdeploy import Out
name="Disable nsd if it's running, so it doesn't block port 53",
service="nsd.service", process_on_53 = host.get_fact(Port, port=53)
running=False, if process_on_53 not in (None, "unbound"):
enabled=False, Out().red(f"Can't install unbound: port 53 is occupied by: {process_on_53}")
) exit(1)
apt.packages( apt.packages(
name="Install unbound", name="Install unbound",
packages=["unbound", "unbound-anchor", "dnsutils"], packages=["unbound", "unbound-anchor", "dnsutils"],

View File

@@ -86,15 +86,19 @@ def run_cmd(args, out):
out.red("Please re-run scripts/initenv.sh to update pyinfra to version 3.") out.red("Please re-run scripts/initenv.sh to update pyinfra to version 3.")
return 1 return 1
retcode = out.check_call(cmd, env=env) try:
if retcode == 0: retcode = out.check_call(cmd, env=env)
out.green("Deploy completed, call `cmdeploy dns` next.") if retcode == 0:
elif not remote_data["acme_account_url"]: out.green("Deploy completed, call `cmdeploy dns` next.")
out.red("Deploy completed but letsencrypt not configured") elif not remote_data["acme_account_url"]:
out.red("Run 'cmdeploy run' again") out.red("Deploy completed but letsencrypt not configured")
retcode = 0 out.red("Run 'cmdeploy run' again")
else: retcode = 0
else:
out.red("Deploy failed")
except subprocess.CalledProcessError:
out.red("Deploy failed") out.red("Deploy failed")
retcode = 1
return retcode return retcode