18 KiB
Selective SRS Installer – Review Draft 0.9
Stand: 18.10.2026. Target: Debian 13, PostgreSQL/PostfixAdmin; reference implementation mx.warenform.de.
This directory is a review bundle, not a production-tested release. Copy its templates into the corresponding location of the shared mailsystem Git repository (files/srs/templates/) before the installer can be run in its normal script directory. The four Python programs and helpers/srs-common.sh in the bundle are unmodified reference snapshots from the user's repository/uploads.
Files
install-update-srs.sh— draft with read-only--checkand an unapproved--installimplementation.files/srs/templates/delivery-main.cf.in— reference delivery main.cf with selected Postfix parameters templated.files/srs/templates/delivery-master.cf— reference delivery master.cf, unchanged.files/srs/templates/transport.in— reference transport file with SRS domain placeholder.files/srs/templates/postsrsd.conf.in— reference PostSRSd configuration with SRS domain placeholder.files/srs/templates/*.service— reference systemd units, unchanged.
Conventions
- The product Postfix instance
/etc/postfix/main.cfand/etc/postfix/master.cfis never modified by this draft. Separateactivate-srs.sh/deactivate-srs.shdo that. - Initial PRE-SRS state is derived once; existing state is preserved.
- PostSRSd CMake 2.4.1 options match the working reference.
- The Debian unit
postfix@srs-delivery.servicedecodes its%Iinstance tokensrs-deliveryassrs/delivery, yielding/etc/postfix-srs/delivery. No special directory symlink is necessary. - Three reference Python programs have their single
srs.warenform.destring replaced by the locally configured_SRS_DOMAINwhen installed, without modifying the Git sources. - In this initial draft, active-service updates to another PostSRSd version are refused; coordinated restarts, full rollback of queue initialisation, semantic rendering parity tests and cross-host integration tests remain to be implemented.
- No attempt is made to install Debian build dependencies. On
a.mx.oopen.de,cmakewas found missing during inventory.
Safe first check
Run only --check after placing the script and templates in the repository. This path does not run init_srs_runtime(), create a lock, install files, build anything or touch services.
Do not run --install on any production mail server yet. Syntax validation alone is insufficient; the installation stage and its rollback require offline/staging testing and explicit approval.
Findings after systemd template inspection (18 October 2026)
postfix@srs-delivery.serviceusesEnvironment=MAIL_CONFIG=/etc/postfix-%I. The unescaped%Ifor instancesrs-deliveryissrs/delivery; thus the intended configuration path is/etc/postfix-srs/delivery. There is NO/etc/postfix-srs-deliverysymlink on the working reference server and none is needed.- The SRS private configuration directory is now created with root:root mode
0700; an already-existing directory must match these permissions. - Snapshotting existing files records a rollback entry only AFTER the backup is successful, and installation to a symlinked destination is rejected.
- Remaining blockers: package provisioning (CMake missing on a.mx), semantic config parity validation, coordinated active-version upgrades, complete rollback of newly created directories/queue initialization and failure-injection testing.
--installis NOT approved.
Changes in draft 0.3
- The
--checkreport correctly distinguishes an available Debianpostfix@.servicetemplate from an installed, ready SRS delivery instance. - Rollback removes a freshly installed PostSRSd version prefix only after the previous stable link has been restored and only if it is not selected.
- An initial installation aborts if SRS configuration files already exist without a stable PostSRSd symlink, rather than overwriting an ambiguous partial installation.
Still NOT production ready: CMake package provisioning, comprehensive rollback of new directories and Postfix queue creation, service upgrade orchestration, DNS checks, and integration tests are not yet implemented.
Changes in draft 0.4
-
Both
--checkand--installfirst ask interactively for the SRS domain, before inspecting prerequisites. For the targeta.mx.oopen.de, entersrs.oopen.de. This value is not hardcoded into the shared Git source. -
If a local
conf/srs.confcontains a straightforward domain assignment, that domain is offered as the default. The hint is read as plain text, not sourced. -
--checkdisplays the selected domain and detects an evident conflict with a previously configured domain; it never writesconf/srs.conf. -
First
--installnow stages and installsconf/srs.conf(root:root,0644) after user confirmation. Existing configuration is validated usingload_srs_config()and must match the selected domain; automatic domain migration is refused. -
Add
conf/srs.confto the Git repository's.gitignore; onlyconf/srs.conf.samplebelongs in Git. -
Still a REVIEW DRAFT, NOT approved for production
--install. Other known blockers from 0.3 remain. -
After domain selection,
--checkprints informational DNS TXT/MX/A/AAAA lookups whendigis available. These outputs are not a completed SPF/MX validation.
Changes in review draft 0.5 (18 October 2026)
- Adds
helpers/srs-dns-check.py. Both modes ask for the domain first.--checkuses it without any writes and reports readiness;--installstops before changes if the public-DNS preflight fails. - The DNS helper resolves delegation via public DNS resolvers, then directly queries every discovered authoritative nameserver. This bypasses the local
/etc/hostsoverride wherea.mx.oopen.deresolves to127.0.1.1via systemd-resolved on this machine. - The agreed strict single-host DNS profile is checked: precisely one MX pointing to Postfix
myhostname, exactly one SPF record equal tov=spf1 mx -all, and public MX-target A/AAAA answers containing the explicitsmtp_bind_addressandsmtp_bind_address6values. Fora.mx.oopen.de, that means MXa.mx.oopen.de, IPv495.217.204.247, IPv62a01:4f9:4a:47e5::247. No server domain or IP has been hardcoded into the installer or helper. - This is not a complete SPF evaluator, an SMTP connectivity test, or a guarantee of bounce routing through arbitrary topologies. DNS setups using other valid SPF expressions, shared SRS domains, multiple MX hosts or hosts without explicit IPv4/IPv6 bind addresses require a considered implementation extension, rather than being silently accepted.
- Reorders
--installso it performs root/command/source/DNS and installation-state preflight before asking the operator to approve preparation and before acquiring the lock or writing files.--checkstays read-only. It checks fordigas a required installation dependency. - Add the new helper to the common Git repository at
helpers/srs-dns-check.pyalongside the updatedinstall-update-srs.sh. Keepconf/srs.confignored in Git. - Tests run for this draft: Bash syntax check, Python syntax compilation, three isolated DNS-positive/negative cases, and an end-to-end mocked
--checkwith two nameservers. No productive SRS installation, delivery, failure-injection or rollback testing has been performed.
Known blockers remain: CMake and CTest absent on a.mx.oopen.de; Postfix delivery config semantics and safe rollback/active upgrades need additional testing. Do not run --install in production yet.
Changes in review draft 0.6 (18 October 2026)
- The operator's
git status --short --untracked-files=alllisted precisely the eight expected new files.bash -nof the installer andcompile()of the DNS helper passed ona.mx.oopen.de.conf/srs.confis already ignored by.gitignore(conf/*.conf). No Git commit has been performed. - Preflight now rejects symlinked/non-directory SRS destination paths and a nonprivate existing
/etc/postsrsd-srsdirectory BEFORE the build and filesystem-deployment confirmation. - Newly created configuration directories are tracked separately and removed on failed installation only if empty (after tracked file rollback).
- Newly created
/var/spool/postfix-srs-deliveryand/var/lib/postfix-srs-deliveryroots are remembered beforepostfix -c ... check. Rollback tries onlyrmdir; it never recursively deletes Postfix runtime data. If Postfix created a nonempty hierarchy, that hierarchy remains for manual inspection. Thus rollback is not fully automatic for initialized Postfix queue/data. - Unexpected process EXIT after the file-deployment phase begins is routed through tracked-file rollback (normal success and explicit rollback disarm this trap). This does not guarantee recovery from SIGKILL, power loss, process crash without shell handling, or full operational restore.
- No changes to the six reference templates, the four reference SRS Python scripts,
helpers/srs-common.sh, or the existing activation/deactivation tools.
Release status: NOT approved for --install. Active upgrades with running SRS services are deliberately rejected and still need a separate safe restart/rollback design. CMake/CTest provisioning, live first-install, Postfix config semantic comparison, and injected-failure/queue behavior tests remain open. Do not commit this draft as a production-ready release.
Changes in review draft 0.7 (18 October 2026)
apt-get -s install cmakeona.mx.oopen.deproposed exactly four new Debian 13 packages:cmake,cmake-data,libjsoncpp26,librhash1; zero upgrades and removals. No backports packages were proposed.--checkstill never changes packages or SRS state; it reports missing CMake/CTest and prints anapt-get -s --no-install-recommendssimulation when CMake is missing.--installfirst asks for the SRS domain, then performs read-only preflight and simulates the APT transaction. The simulated transaction must have exactly zero upgrades and zero removals. A general preparation approval and a separate, explicit yes for CMake package installation are required. APT is run only after the shared SRS lock has been acquired.- Re-simulates the APT transaction immediately before the actual install and refuses changed plans. Does not run
apt-get updateor request backports. Validates thatcmake >= 3.24andctestare available after package installation. APT package changes are intentionally not reverted by SRS file rollback; an interrupted APT transaction requires manual inspection. - These checks are a safety guard, not an absolute guarantee against concurrent external changes in APT repositories, package indexes or package states.
Still not approved for production --install. No live package installation, PostSRSd build, first-install or failure-injection/rollback test has been performed for v0.7.
Changes in review draft 0.8 (18 October 2026)
- Fixed actual delivery
main.cftemplate rendering: template placeholders must be resolved by the exact case-sensitive Postfix parameter name on the left-hand side of the template assignment, notplaceholder.lower().smtp_tls_CAfilewas erroneously queried assmtp_tls_cafile, causing a Postfix warning and an emptysmtp_tls_CAfilein the generated delivery configuration. - The rendering step now refuses placeholders not standing alone in a Postfix assignment and refuses
postconferrors/warnings instead of silently accepting an empty value. Existing valid empty settings remain possible. No reference template changed. - Still a review draft; no production
--installapproval.
Changes in review draft 0.9 (18 October 2026)
- Same-version maintenance update: If
/usr/local/postsrsdalready resolves to the selected/usr/local/postsrsd-<version>, no Git/CMake/CTest build, no new installation prefix, and no symlink switch are performed. Instead, the installer renders and updates the four integration Python programs, PostSRSd config, separate Postfix delivery config/map and two systemd unit files with existing file snapshots and rollback. - Version-change update: When the selected version differs from the existing symlink target, the previous immutable version prefix is retained; the new version is built, staged and selected only after the prepared integration files have been copied. Failed deployment attempts restore the previous symlink and tracked files and remove the new prefix, provided it is not selected. This requires services to be inactive.
- Strict inactive-only updates: For both maintenance updates and version changes, any SRS managed block in either productive Postfix
main.cformaster.cf, or any running SRS systemd service, causes an immediate refusal. The operator must coordinate deactivation and downtime separately; live/zero-downtime updates remain unsupported. This draft never restarts or activates services. - Existing SRS secret and PRE-SRS state are never regenerated during an update. A missing secret or state on an existing installation is treated as an error before any writes.
- CMake/CTest and Debian package provisioning are not required for same-version integration-only updates. They remain required for initial installation or PostSRSd version changes. The requested version defaults to 2.4.1; use
--version X.Y.Zto specify another release. - Installation directory backups are created only after the final deployment confirmation; operator cancellation before deployment does not create an empty backup snapshot.
- The change-tracking flags for new prefixes and symlink switches are set immediately before the respective filesystem operation to improve interruption handling (but SIGKILL, power loss and concurrent external changes remain outside the rollback guarantee).
- A controlled offline mock test was run with all install paths remapped into a temporary directory, with fake
systemctl,postfix,postmap,postconf,git,cmake,ctestand DNS checks. Cases that passed: same-version maintenance update, failed maintenance update with rollback of the helper and preservation of secret/symlink, version-change update (2.4.1 → simulated 2.4.2), failed version-change update (simulated 2.4.3) with symlink restoration and removal of new prefix. These were mock tests, not real PostSRSd builds, Postfix validation or service starts. - The six reference configuration templates, the four reference Python programs,
helpers/srs-common.sh,helpers/srs-dns-check.pyandactivate-srs.sh/deactivate-srs.share unchanged. No Git commit has been made ona.mx.oopen.deby this development process.
NOT production-ready yet: First-install and rollback tests with actual Postfix and PostSRSd in a disposable Debian 13 environment, source-build verification and runtime end-to-end delivery checks remain necessary. Do not execute --install on a production mail server yet.
Changes in review draft 0.10 – display and offline test status (18 October 2026)
- Shortens the APT dry-run output in both
--checkand--installpreflight: report the transaction summary and the packages inInstlines. The actualapt-get -soutput remains the source of truth; the--installsafety gate still requires zero upgrades and removals and still compares the full plan before installing packages. If the simulation cannot be summarized, the full text is printed for diagnosis and the--installplan is rejected. - No changes to the six Postfix/PostSRSd templates, to the four SRS Python integration programs, or to the SRS common and DNS helper scripts.
- A simulated end-to-end
--checkin a temporary directory, using fakepostconf,apt-get,systemctland DNS helper responses, passed. It detected CMake/CTest as missing, summarized four proposed packages and left the test project files unchanged. Bash syntax passed. - This environment is Debian 13, and CMake/CTest are available, but actual PostSRSd 2.4.1 source retrieval failed because outbound DNS/network access to GitHub was unavailable; no genuine PostSRSd build,
ctestof the real source or real Postfixcheckwas performed. Postfix binaries are unavailable here. The production targeta.mx.oopen.dewas not modified. - As before, do not run
--installon production without a genuinely isolated Debian-13 test exercising real PostSRSd and Postfix, including failure injection and rollback.
Changes in review draft 0.11 – directory mode and reproducible offline tests (18 October 2026)
- A newly created
/etc/postsrsd-srsdirectory must be exactlyroot:rootmode0700. On directories under a setgid parent,install -d -m 0700may leave an inherited SGID bit and produce mode2700. This caused the subsequent maintenance update to fail its strict permission preflight in the isolated test. - After creating and registering the new directory for rollback, the installer now applies a five-digit octal chmod (
00700), which removes inherited setgid/sticky flags, then confirms owner/group and exact mode. This applies only to newly created paths using a requested explicit mode; existing directory permissions are not silently changed. - The new test runner
tests/test_installer_mock.pyrelocates all managed paths into a temporary fixture tree (which deliberately inherits SGID), mocks Git/CMake/CTest, DNS, Postfix and systemd, and supplies a pseudo-terminal to exercise the complete installer flow. - Successfully tested scenarios: simulated first install, same-version maintenance update, failure of maintenance update with file rollback, version upgrade, failed version upgrade with symlink/prefix rollback, update refusal when SRS managed block exists, failed initial Postfix check retaining runtime queue directories, and failed
postmapwith tracked-file rollback. - Reproduce the mocked scenarios on an isolated development machine by extracting this archive and executing
python3 tests/test_installer_mock.py. This is not a real PostSRSd source build or a Postfix integration test. The fake programs do not validate Postfix syntax, actual LMTP routing, service listeners or mail delivery. - Production use remains forbidden pending real integration testing in a disposable Debian 13 VM/container. No changes were made to the productive mailserver
a.mx.oopen.de.