Integrate Postfix with Rspamd for filtering and DKIM signing
Install Rspamd, use local milter sockets, define fail behavior, train no data implicitly, add DKIM keys and DNS, tune actions, and test inbound and outbound paths.
Add observable spam filtering and authorized-domain DKIM signing without creating a mail-flow single point of silent loss.
- Rspamd 3.x
- Authoritative DNS and stable identity Control forward and reverse DNS, choose the canonical mail hostname and domains, and verify the host is not behind an outbound SMTP-blocking network.
hostname -f; getent ahosts $(hostname -f); dig +short -x {{publicIp}} - Recovery and queue safety Keep console access, back up active configuration, and record queue state before changing routing, authentication, filters, or mailbox delivery.
- Abuse and deliverability plan Define relay boundaries, account owners, rate limits, bounce handling, postmaster address, monitoring, and how compromised credentials will be revoked.
OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.
Full guide
What you will build
- A production Postfix implementation of “Integrate Postfix with Rspamd for filtering and DKIM signing” with explicit SMTP/IMAP boundaries, identity, durable state and observable delivery evidence.
- A read-only baseline, staged candidate and end-to-end canary covering DNS, TLS, authentication, recipient or route policy, queue/mailbox state and logs.
- A security and rollback procedure that avoids open relay, backscatter, plaintext credentials, world-readable keys/mail and unreviewed bulk queue actions.
- Add observable spam filtering and authorized-domain DKIM signing without creating a mail-flow single point of silent loss. The intended success path is visible in native status, protocol transcript, headers or mailbox evidence.
- Expected unauthorized relay, unknown-recipient, wrong-sender, invalid-authentication or wrong-certificate tests fail at the declared boundary without harming unrelated mail.
Architecture
How the parts fit together
Outbound mail passes through a signing or filtering boundary that evaluates content and adds a DKIM signature using a selector-specific private key. DNS publishes the matching public key and authentication policy. Key files are readable only by the signer, allowed-sender rules prevent unauthorized signing, and headers/logs expose the decision. Rotation overlaps old and new selectors until previously delivered mail and DNS caches no longer require the old public key.
- Inventory hostname/DNS, listeners, certificates, identities, recipient/relay maps, queue/mailbox state, logs and a recoverable configuration/data baseline.
- Prepare the dkim filter candidate with official Postfix syntax, protected secrets and one explicit service/data boundary at a time.
- Run native configuration validation and immediate read-only checkpoint before reload or acceptance of new messages.
- Use controlled local and external canaries plus an expected-denial test, preserve message identifiers/headers, and retain the prior configuration for rollback.
Assumptions
- The public mail hostname, forward/reverse DNS ownership, supported package version and responsibility for ports 25/587/993 are known.
- A maintenance or canary window, console recovery and current protected backup of configuration, keys, identity mappings and relevant mailbox/queue data exist.
- Test sender and recipient addresses are owned by the operator; no unsolicited or third-party traffic is generated during verification.
- Secrets and private keys are delivered outside shell history and have narrowly defined service ownership and rotation plans.
Key concepts
- envelope identity
- SMTP sender and recipient used for routing, delivery status and SPF; it is distinct from visible message headers.
- open relay
- An MTA that accepts unauthorized third-party sender-to-recipient forwarding, enabling abuse and reputation damage.
- backscatter
- A later non-delivery report sent to a forged sender because an invalid recipient was accepted instead of rejected during SMTP.
- alignment
- DMARC relationship between visible From domain and authenticated SPF or DKIM domain.
- Maildir
- A mailbox format storing messages as individual files in cur/new/tmp directories with strict ownership.
Before you copy
Values used in this guide
{{cleanCanary}}Operator-reviewed value used by this tutorial for cleanCanary; derive it from the target environment and never from untrusted request data.
Example: /srv/mail-fixtures/clean-message.eml{{domain}}Fully qualified public or internal hostname served by this configuration.
Example: example.com{{externalRecipient}}Operator-reviewed value used by this tutorial for externalRecipient; derive it from the target environment and never from untrusted request data.
Example: owned-test@example.net{{mailHost}}Operator-reviewed value used by this tutorial for mailHost; derive it from the target environment and never from untrusted request data.
Example: mail.example.com{{ownedSender}}Operator-reviewed value used by this tutorial for ownedSender; derive it from the target environment and never from untrusted request data.
Example: example-ownedsender{{protectedSecret}}Operator-reviewed value used by this tutorial for protectedSecret; derive it from the target environment and never from untrusted request data.
Example: secret-manager-reference{{receivedMessageFile}}Operator-reviewed value used by this tutorial for receivedMessageFile; derive it from the target environment and never from untrusted request data.
Example: /srv/mail-fixtures/received-message.eml{{selector}}Operator-reviewed value used by this tutorial for selector; derive it from the target environment and never from untrusted request data.
Example: mail2026{{testRecipient}}Operator-reviewed value used by this tutorial for testRecipient; derive it from the target environment and never from untrusted request data.
Example: owned-test@example.net{{user}}Operator-reviewed value used by this tutorial for user; derive it from the target environment and never from untrusted request data.
Example: alice@example.comSecurity and production boundaries
- Never weaken relay/recipient checks, publish private DKIM/TLS keys, enable plaintext authentication, or expose web/IMAP administration broadly to make a test pass.
- Mail content, credentials, queues, logs and backups contain personal or confidential data; restrict, encrypt, minimize and retain them under an explicit policy.
- Use dedicated service identities and root-readable credential maps; verify logs and configuration output are redacted before sharing.
Stop before continuing if
- Stop if a test permits unauthorized relay, accepts unknown recipients for later bounce, sends credentials without verified TLS, or exposes private keys/mailbox files.
- Do not continue when hostname/PTR ownership, package/config version, recipient map, route, queue, mailbox ownership or rollback backup is ambiguous.
- Immediately quarantine the candidate when unrelated mail is rerouted, deleted, multiply delivered, signed by the wrong domain, or inaccessible after reload.
instruction
Capture current mail-flow and filtering baseline
Record Postfix milters, restrictions, queue, latency, rejection rate, trusted networks, and outbound authentication path.
Why this step matters
Capture current mail-flow and filtering baseline is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Record Postfix milters, restrictions, queue, latency, rejection rate, trusted networks, and outbound authentication path. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Capture current mail-flow and filtering baseline”. The scope must remain limited to the selected application and supported host.
Syntax explained
postconf- Invokes the principal tool or configuration operation for “Capture current mail-flow and filtering baseline”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
|- Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
postconf smtpd_milters non_smtpd_milters milter_default_action mynetworks; postqueue -p; sudo journalctl -u postfix --since '-1 hour' --no-pager | tail -n 100Existing policy and queue state are recorded.
Checkpoint: Checkpoint: Capture current mail-flow and filtering baseline
Continue whenExisting policy and queue state are recorded. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when postconf reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Capture current mail-flow and filtering baseline” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v postconf 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
command
Install Rspamd and Redis from approved repositories
Use supported distribution/upstream packages, pin ownership, and keep management controller inaccessible from public networks.
Why this step matters
Install Rspamd and Redis from approved repositories is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Use supported distribution/upstream packages, pin ownership, and keep management controller inaccessible from public networks. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Install Rspamd and Redis from approved repositories”. The scope must remain limited to the selected application and supported host.
Syntax explained
apt- Invokes the principal tool or configuration operation for “Install Rspamd and Redis from approved repositories”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
&&- Runs the following operation only when the previous command succeeds, preventing a reload or state transition after a failed validation.
sudo apt update && sudo apt install --yes rspamd redis-server; sudo systemctl enable --now redis-server rspamdRedis and Rspamd start with packaged configuration.
Checkpoint: Checkpoint: Install Rspamd and Redis from approved repositories
Continue whenRedis and Rspamd start with packaged configuration. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when apt reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Install Rspamd and Redis from approved repositories” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v apt 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
config
Configure a local normal worker socket
Bind the milter worker to a Unix socket or loopback only, set postfix-readable ownership, and leave the controller on a protected interface.
Why this step matters
Configure a local normal worker socket is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Bind the milter worker to a Unix socket or loopback only, set postfix-readable ownership, and leave the controller on a protected interface. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Configure a local normal worker socket”. The scope must remain limited to the selected application and supported host.
Syntax explained
sudoedit- Invokes the principal tool or configuration operation for “Configure a local normal worker socket”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
|- Passes standard output to the next read-only inspection stage; review each stage separately if the combined result is surprising.
/etc/rspamd/local.d/worker-normal.inc- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
/etc/rspamd/local.d/worker-normal.incsudoedit /etc/rspamd/local.d/worker-normal.inc; sudo rspamadm configtest; sudo systemctl restart rspamd; sudo ss -lxnp | grep rspamdThe milter socket is local and accessible to Postfix.
Checkpoint: Checkpoint: Configure a local normal worker socket
Continue whenThe milter socket is local and accessible to Postfix. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when sudoedit reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Configure a local normal worker socket” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v sudoedit 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
config
Connect Postfix SMTP and non-SMTP mail to Rspamd
Set smtpd_milters and non_smtpd_milters to the local socket, choose temporary-failure behavior for filter outages, and set macro defaults.
Why this step matters
Connect Postfix SMTP and non-SMTP mail to Rspamd is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Set smtpd_milters and non_smtpd_milters to the local socket, choose temporary-failure behavior for filter outages, and set macro defaults. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Connect Postfix SMTP and non-SMTP mail to Rspamd”. The scope must remain limited to the selected application and supported host.
Syntax explained
postconf- Invokes the principal tool or configuration operation for “Connect Postfix SMTP and non-SMTP mail to Rspamd”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
configuration file- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
sudo postconf -e 'smtpd_milters=unix:/run/rspamd/milter.sock' 'non_smtpd_milters=unix:/run/rspamd/milter.sock' 'milter_default_action=tempfail' 'milter_protocol=6'; sudo postfix checkPostfix uses the local Rspamd milter for inbound and local submissions.
Checkpoint: Checkpoint: Connect Postfix SMTP and non-SMTP mail to Rspamd
Continue whenPostfix uses the local Rspamd milter for inbound and local submissions. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when postconf reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Connect Postfix SMTP and non-SMTP mail to Rspamd” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v postconf 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
config
Set measured action thresholds and trusted paths
Define greylist, add-header, reject thresholds, local/authenticated trust, logging, and rate limits; begin in observation mode before rejecting.
Why this step matters
Set measured action thresholds and trusted paths is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Define greylist, add-header, reject thresholds, local/authenticated trust, logging, and rate limits; begin in observation mode before rejecting. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Set measured action thresholds and trusted paths”. The scope must remain limited to the selected application and supported host.
Syntax explained
sudoedit- Invokes the principal tool or configuration operation for “Set measured action thresholds and trusted paths”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
configuration file- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
sudoedit /etc/rspamd/local.d/actions.conf; sudoedit /etc/rspamd/local.d/options.inc; sudo rspamadm configtestThresholds and trusted paths are explicit and configuration validates.
Checkpoint: Checkpoint: Set measured action thresholds and trusted paths
Continue whenThresholds and trusted paths are explicit and configuration validates. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when sudoedit reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Set measured action thresholds and trusted paths” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v sudoedit 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
config
Create DKIM keys and signing policy
Use rspamadm dkim_keygen, protect private keys, publish selector DNS, and sign only authenticated/local authorized domains.
Why this step matters
Create DKIM keys and signing policy is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Use rspamadm dkim_keygen, protect private keys, publish selector DNS, and sign only authenticated/local authorized domains. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Create DKIM keys and signing policy”. The scope must remain limited to the selected application and supported host.
Syntax explained
install- Invokes the principal tool or configuration operation for “Create DKIM keys and signing policy”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}- Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
configuration file- Is the persistent configuration boundary changed by this step. Keep an attributable backup and validate the consumer before reload.
Values stay on this page and are never sent or saved.
sudo install -d -o _rspamd -g _rspamd -m 0750 /var/lib/rspamd/dkim; sudo rspamadm dkim_keygen -b 2048 -s {{selector}} -d {{domain}} -k /var/lib/rspamd/dkim/{{domain}}.{{selector}}.key > /tmp/{{domain}}.dkim.txt; sudo chmod 0600 /var/lib/rspamd/dkim/{{domain}}.{{selector}}.keyPrivate key and DNS public record are generated.
Checkpoint: Checkpoint: Create DKIM keys and signing policy
Continue whenPrivate key and DNS public record are generated. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when install reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Create DKIM keys and signing policy” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v install 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
verification
Validate and reload both services
Run Rspamd config test and Postfix check, restart in dependency order, inspect socket and logs, and prove mail defers if Rspamd is unavailable according to policy.
Why this step matters
Validate and reload both services is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Run Rspamd config test and Postfix check, restart in dependency order, inspect socket and logs, and prove mail defers if Rspamd is unavailable according to policy. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Validate and reload both services”. The scope must remain limited to the selected application and supported host.
Syntax explained
rspamadm- Invokes the principal tool or configuration operation for “Validate and reload both services”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
sudo rspamadm configtest; sudo postfix check; sudo systemctl restart redis-server rspamd postfix; sudo journalctl -u rspamd -u postfix -n 100 --no-pagerServices start, socket connects, and no milter protocol error appears.
Checkpoint: Checkpoint: Validate and reload both services
Continue whenServices start, socket connects, and no milter protocol error appears. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when rspamadm reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Validate and reload both services” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v rspamadm 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
verification
Test clean, spam, authenticated outbound, and spoofed mail
Use a safe standard antispam test message, normal canaries, and spoofed From attempts; verify Rspamd headers, action, DKIM alignment, and queue behavior.
Why this step matters
Test clean, spam, authenticated outbound, and spoofed mail is a separate checkpoint because it establishes one auditable part of add observable spam filtering and authorized-domain dkim signing without creating a mail-flow single point of silent loss. Performing it independently keeps a failed prerequisite, syntax error, or compatibility mismatch from being hidden by later actions.
What to understand
Use a safe standard antispam test message, normal canaries, and spoofed From attempts; verify Rspamd headers, action, DKIM alignment, and queue behavior. Read the complete command or configuration before execution, replace the documented placeholders, and compare the target host with the supported environments listed at the beginning of this tutorial.
Capture the before-state and the exact output in the change record. If this step modifies a file or service, validate the candidate with its native checker before any reload; a successful process exit alone does not prove that the application uses the intended value.
Use a representative staging or canary host first. Repeat the stated checkpoint immediately, because proceeding with ambiguous evidence makes the later end-to-end verification and rollback materially harder.
System changes
- This step may affect the files, packages, identities, services, or runtime policy named in “Test clean, spam, authenticated outbound, and spoofed mail”. The scope must remain limited to the selected application and supported host.
Syntax explained
swaks- Invokes the principal tool or configuration operation for “Test clean, spam, authenticated outbound, and spoofed mail”; confirm that it resolves to the expected packaged executable or file before using elevated privileges.
{{…}}- Marks an operator-supplied value. Replace every placeholder deliberately; do not paste untrusted text or leave braces in the production command.
Values stay on this page and are never sent or saved.
swaks --server {{mailHost}} --to {{testRecipient}} --from clean@example.net --header 'X-Test: {{cleanCanary}}'; swaks --server {{mailHost}} --port 587 --tls --auth --auth-user {{user}} --auth-password '{{protectedSecret}}' --from {{ownedSender}} --to {{externalRecipient}}Clean mail is accepted, test spam receives intended action, owned outbound passes DKIM, spoofed mail is not signed.
Checkpoint: Checkpoint: Test clean, spam, authenticated outbound, and spoofed mail
Continue whenClean mail is accepted, test spam receives intended action, owned outbound passes DKIM, spoofed mail is not signed. Treat this concrete evidence as the minimum success signal and also confirm that unrelated services and the previous healthy path remain unchanged.
Stop whenStop before the next step when swaks reports an error, the output differs materially from the example, an unexpected package/service/path is affected, or the required before-state and rollback artifact are missing.
If this step fails
The command for “Test clean, spam, authenticated outbound, and spoofed mail” fails, produces no useful evidence, or the expected service/configuration state is absent.
Likely causeA placeholder targets the wrong environment, the installed version uses another path or unit name, permissions are insufficient, or an earlier prerequisite was not satisfied.
command -v swaks 2>/dev/null || truesystemctl --failed --no-pager 2>/dev/null || truejournalctl -p warning -n 50 --no-pager 2>/dev/null || true
ResolutionDo not improvise a privileged workaround. Re-read the environment and variable table, inspect the official source for the installed version, restore the candidate file if necessary, and repeat only this checkpoint.
Security notes
- Keep secrets out of shell history, process arguments, screenshots, logs, and tutorial placeholders. Elevate only the narrow command that requires it and preserve package signature and TLS verification.
Alternatives
- When the host layout or software version differs, use the vendor-supported equivalent in a disposable staging environment and document the mapping before touching production.
Stop conditions
- Stop if the action broadens network exposure, permissions, package sources, writable paths, or service privileges beyond the tutorial's declared architecture.
Finish line
Verification checklist
rspamadm configtest && postconf smtpd_milters non_smtpd_milters milter_default_actionRspamd validates and Postfix points to the intended local socket.grep -iE 'Authentication-Results:.*(dkim=pass|rspamd)' {{receivedMessageFile}}Delivered canary records expected Rspamd and DKIM results.Recovery guidance
Common problems and safe checks
A message remains queued or the remote server returns a temporary 4xx response.
Likely causeDNS/MX resolution, routing, network reachability, TLS negotiation, remote greylisting/rate limits, reputation or recipient policy prevents delivery.
exim -bp 2>/dev/null || postqueue -pdig +short MX example.netjournalctl -u exim4 -u postfix --since '-30 min' --no-pager
ResolutionInspect one message's recorded diagnostic and route first, fix the evidenced dependency, then retry only that message; do not force an undiagnosed bulk queue.
SMTP accepts a recipient, but the mailbox is absent, unreadable or never visible over IMAP.
Likely causeRecipient maps, LMTP/LDA route, virtual UID/GID, Maildir path, quota, Dovecot namespace or filesystem permissions disagree.
doveconf -ndoveadm user user@example.comdoveadm mailbox list -u user@example.com
ResolutionTrace the exact address through recipient validation, delivery socket and resolved mailbox path; correct the narrow mapping/ownership mismatch before accepting more mail.
Authentication or TLS fails despite apparently correct credentials and certificate files.
Likely causeThe listener uses another configuration, hostname/SAN does not match, chain/key permissions are wrong, authentication is attempted without TLS, or the identity backend maps another username.
openssl s_client -connect mail.example.com:587 -starttls smtp -servername mail.example.com </dev/nullopenssl s_client -connect mail.example.com:993 -servername mail.example.com </dev/nulljournalctl -u dovecot -u postfix -u exim4 -p warning -n 100 --no-pager
ResolutionVerify the advertised hostname, chain, listener and mapped user independently; never disable certificate verification or enable plaintext authentication to bypass the failure.
Reference
Frequently asked questions
Why is one successful test email insufficient?
It may bypass the actual external DNS, authentication, recipient, DKIM, queue retry or IMAP path. Test each boundary and preserve protocol/header evidence.
Can TLS be tested by checking that encryption is present?
No. Verify the chain and hostname and ensure authentication is unavailable before STARTTLS; encryption to an unverified endpoint is not server authentication.
Should a stuck queue be forced immediately?
No. Read one message's diagnostic and fix the dependency first. Bulk retries can amplify rate limits, duplicates or reputation damage.
Recovery
Rollback
Remove the milter references and reload Postfix first, then stop Rspamd without losing queued mail.
- Restore prior Postfix milter settings, run postfix check, and reload.
- Stop Rspamd/Redis only after Postfix no longer references their socket.
- Keep DKIM public keys published while any signed delayed message may exist.
Evidence