From 650ae31eb5421a0a9a46d060f3298df2aca14b34 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Tue, 1 Sep 2026 19:42:21 +0800 Subject: [PATCH] Keep Postfix stopped during rootfs configuration Validate the generated Postfix configuration without starting its master process while an appliance root filesystem is being assembled. This avoids colliding with an existing build-host listener on port 25 and leaves normal service startup to the enabled systemd unit after boot. Add a focused fixture that holds port 25 open, verifies the listener survives configuration, requires postmulti check and service enablement, and fails if the Postfix command starts. --- conf/turnkey.d/postfix-local | 7 +-- tests/test-postfix-local-build.sh | 76 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100755 tests/test-postfix-local-build.sh diff --git a/conf/turnkey.d/postfix-local b/conf/turnkey.d/postfix-local index 42691472..a9c0b470 100755 --- a/conf/turnkey.d/postfix-local +++ b/conf/turnkey.d/postfix-local @@ -6,10 +6,6 @@ if [[ -z "$HOSTNAME" ]]; then fatal "Hostname not defined" fi -if grep -q ':25' <(ss -tlnp); then - fatal "Port 25 is already in use - must be available to set up postfix" -fi - postconf -e inet_interfaces=localhost postconf -e myhostname="$HOSTNAME" @@ -35,6 +31,5 @@ postconf -e smtpd_tls_mandatory_ciphers=medium # ciphers set by common/conf/turnkey.d/zz-ssl-ciphers postconf -e tls_medium_cipherlist="ZZ_SSL_CIPHERS" -postmulti -x postfix start +postmulti -p check systemctl enable postfix@-.service -postmulti -x postfix stop diff --git a/tests/test-postfix-local-build.sh b/tests/test-postfix-local-build.sh new file mode 100755 index 00000000..5d57b2f1 --- /dev/null +++ b/tests/test-postfix-local-build.sh @@ -0,0 +1,76 @@ +#!/bin/bash +set -Eeuo pipefail + +script=${1:-conf/turnkey.d/postfix-local} +test -x "$script" + +fixture=$(mktemp -d) +listener_pid= +cleanup() { + if [[ -n "$listener_pid" ]]; then + kill "$listener_pid" 2>/dev/null || true + wait "$listener_pid" 2>/dev/null || true + fi + rm -rf -- "$fixture" +} +trap cleanup EXIT + +mkdir -p "$fixture/bin" +export FIXTURE_LOG="$fixture/calls" + +cat > "$fixture/bin/postconf" <<'EOF' +#!/bin/bash +printf 'postconf:%s\n' "$*" >> "$FIXTURE_LOG" +EOF +cat > "$fixture/bin/postmulti" <<'EOF' +#!/bin/bash +test "$*" = '-p check' +printf 'postmulti:%s\n' "$*" >> "$FIXTURE_LOG" +EOF +cat > "$fixture/bin/systemctl" <<'EOF' +#!/bin/bash +test "$*" = 'enable postfix@-.service' +printf 'systemctl:%s\n' "$*" >> "$FIXTURE_LOG" +EOF +cat > "$fixture/bin/postfix" <<'EOF' +#!/bin/bash +echo 'postfix must not be started' >&2 +exit 99 +EOF +chmod +x "$fixture/bin/"* + +python3 - "$fixture/listener-ready" <<'PY' & +import pathlib +import socket +import sys +import time + +listener = socket.socket() +listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +listener.bind(("127.0.0.1", 25)) +listener.listen() +pathlib.Path(sys.argv[1]).touch() +while True: + time.sleep(1) +PY +listener_pid=$! + +for unused in {1..50}; do + [[ -e "$fixture/listener-ready" ]] && break + sleep 0.1 +done +test -e "$fixture/listener-ready" + +PATH="$fixture/bin:/usr/bin:/bin" HOSTNAME=tkldev-fixture "$script" + +kill -0 "$listener_pid" +python3 - <<'PY' +import socket + +with socket.create_connection(("127.0.0.1", 25), timeout=2): + pass +PY + +grep -qx 'postmulti:-p check' "$FIXTURE_LOG" +grep -qx 'systemctl:enable postfix@-.service' "$FIXTURE_LOG" +test "$(grep -c '^postmulti:' "$FIXTURE_LOG")" -eq 1