MAS-WP-0003-T03: optional Scaleway TEM relay for replies; unchroot Postfix
Port 25 outbound is blocked on railiance01, so replies need an authenticated submission relay. Enabled only when Secret mas-relay is mounted; otherwise non-local mail is refused at RCPT time instead of queueing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 252470@bnt-lap001 Assistant-Session: ad628c8f-4be2-4979-94c9-76c7ed6f8241
This commit is contained in:
parent
2a94672239
commit
a80f858643
4 changed files with 45 additions and 5 deletions
|
|
@ -2,7 +2,7 @@
|
|||
# Build from the repo root: docker build -f deploy/railiance/Dockerfile .
|
||||
FROM debian:bookworm-slim
|
||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
postfix python3 python3-jsonschema ssl-cert ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
postfix libsasl2-modules python3 python3-jsonschema ssl-cert ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
RUN useradd -r -s /usr/sbin/nologin mas
|
||||
COPY mas_core /app/mas_core
|
||||
COPY mas_gateway /app/mas_gateway
|
||||
|
|
|
|||
|
|
@ -41,6 +41,28 @@ postconf -e \
|
|||
"smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem" \
|
||||
"smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key" \
|
||||
"inet_protocols=ipv4" "compatibility_level=3.6"
|
||||
# start-fg does not populate the chroot (no resolv.conf), so DNS fails inside
|
||||
# it: client rDNS shows "unknown" and a relayhost would not resolve. The
|
||||
# container already isolates Postfix, so run the daemons unchrooted.
|
||||
postconf -F '*/*/chroot = n'
|
||||
|
||||
# Outbound replies (reply test). Port 25 out is blocked on railiance01, so
|
||||
# replies go through an authenticated submission relay, and only when its
|
||||
# credentials are mounted. Only loopback (the ticket service) may relay.
|
||||
# Without a relay all non-local mail fails fast instead of queueing.
|
||||
SMTP_ARG=""
|
||||
if [ -n "$MAS_RELAY" ] && [ -s /etc/mas-relay/username ]; then
|
||||
printf '%s %s:%s\n' "$MAS_RELAY" "$(cat /etc/mas-relay/username)" \
|
||||
"$(cat /etc/mas-relay/password)" > /etc/postfix/sasl_passwd
|
||||
chmod 600 /etc/postfix/sasl_passwd && postmap /etc/postfix/sasl_passwd
|
||||
postconf -e "relayhost=$MAS_RELAY" "smtp_sasl_auth_enable=yes" \
|
||||
"smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd" \
|
||||
"smtp_sasl_security_options=noanonymous" "smtp_tls_security_level=secure" \
|
||||
"smtp_tls_CApath=/etc/ssl/certs"
|
||||
SMTP_ARG="--smtp 127.0.0.1:25"
|
||||
else
|
||||
postconf -e "default_transport=error:5.7.1 outbound mail disabled"
|
||||
fi
|
||||
cat >> /etc/postfix/master.cf <<CF
|
||||
mas unix - n n - - pipe
|
||||
flags=Rq user=mas argv=/usr/local/bin/mas-gateway
|
||||
|
|
@ -49,9 +71,9 @@ mas unix - n n - - pipe
|
|||
CF
|
||||
|
||||
mkdir -p /var/lib/mas && chown mas /var/lib/mas
|
||||
# Replies stay in the outbox (no --smtp) until the subdomain has SPF/DKIM.
|
||||
# Replies are only recorded in the outbox unless a relay is configured above.
|
||||
su -s /bin/sh mas -c "python3 /app/examples/ticket_service/ticket_service.py \
|
||||
--db /var/lib/mas/tickets.sqlite3 --listen 127.0.0.1:8025" &
|
||||
--db /var/lib/mas/tickets.sqlite3 --listen 127.0.0.1:8025 $SMTP_ARG" &
|
||||
su -s /bin/sh mas -c "python3 /app/capture.py http://127.0.0.1:8025/mas-events \
|
||||
/var/lib/mas/events.jsonl 127.0.0.1" &
|
||||
exec postfix start-fg
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# MAS live provider test (mail-address-semantics MAS-WP-0003).
|
||||
# Founder go for A-D: 2026-10-08. Temporary: delete the namespace after the test.
|
||||
# A namespace + MX pod B LoadBalancer :25 C statute-only ingress D no outbound mail
|
||||
# D superseded 2026-10-18: operator chose replies via Scaleway TEM (Secret mas-relay).
|
||||
# IMAGE is replaced with the pushed digest at apply time.
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
|
|
@ -34,8 +35,13 @@ spec:
|
|||
- name: mx
|
||||
image: IMAGE
|
||||
args: [mx]
|
||||
# Outbound replies via Scaleway TEM, enabled only when Secret mas-relay
|
||||
# (keys username, password) exists. Port 25 out is blocked on the node.
|
||||
env: [{name: MAS_RELAY, value: "[smtp.tem.scaleway.com]:587"}]
|
||||
ports: [{name: smtp, containerPort: 25}]
|
||||
volumeMounts: [{name: evidence, mountPath: /var/lib/mas}]
|
||||
volumeMounts:
|
||||
- {name: evidence, mountPath: /var/lib/mas}
|
||||
- {name: relay, mountPath: /etc/mas-relay, readOnly: true}
|
||||
readinessProbe: {tcpSocket: {port: 25}, periodSeconds: 10}
|
||||
resources:
|
||||
requests: {cpu: 20m, memory: 64Mi}
|
||||
|
|
@ -43,6 +49,8 @@ spec:
|
|||
volumes:
|
||||
- name: evidence
|
||||
persistentVolumeClaim: {claimName: mas-evidence}
|
||||
- name: relay
|
||||
secret: {secretName: mas-relay, optional: true}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
|
|
|
|||
|
|
@ -130,7 +130,17 @@ address and what envelope recipient arrives.
|
|||
Consumer Outlook.com runs on the same Exchange Online infrastructure as
|
||||
M365, so outbound handling is covered by the two M365 runs. Not covered:
|
||||
the Outlook-on-the-web compose form (only the native apps were used).
|
||||
Still open: the reply test (blocked: no outbound mail).
|
||||
- Reply test: operator chose to set up outbound now (2026-10-18). Port 25
|
||||
outbound is blocked on railiance01 (to Gmail and Outlook MX it times out;
|
||||
587 and 465 are open), so replies go through Scaleway Transactional
|
||||
Email on [smtp.tem.scaleway.com]:587 with SASL. This is enabled only when
|
||||
Secret `mas-relay` exists; without it, non-local mail fails fast with
|
||||
5.7.1. Image `mas-live:wp0003-20261018b` also runs Postfix unchrooted:
|
||||
the chroot lacked resolv.conf, which is why rDNS showed "unknown".
|
||||
Tested locally against the real TEM endpoint with dummy credentials:
|
||||
TLS verified, SASL rejected as expected.
|
||||
Pending: TEM domain verification and DNS at IONOS (operator), Secret,
|
||||
redeploy, then the reply send.
|
||||
|
||||
## Forwarding and list paths
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue