Merge remote-tracking branch 'origin/main' into benvin/mail-stalwart
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

# Conflicts:
#	apps/base/mail/kustomization.yaml
This commit is contained in:
2026-10-12 22:32:16 +11:00
15 changed files with 382 additions and 3 deletions
+18
View File
@@ -8,6 +8,10 @@ resources:
- gateway.yaml
- httproute.yaml
- namespace.yaml
- smarthost-networkpolicy.yaml
- smarthost-pdb.yaml
- smarthost-service.yaml
- smarthost-statefulset.yaml
- stalwart-apply-job.yaml
- stalwart-apply-rbac.yaml
- stalwart-blobs-bucket.yaml
@@ -19,3 +23,17 @@ resources:
- vaultauth.yaml
- vaultstaticsecret.yaml
- vmpodscrape.yaml
configMapGenerator:
- name: smarthost-config
namespace: mail
options:
disableNameSuffixHash: true
files:
- smarthost/main.cf
- smarthost/master.cf
- smarthost/relay_domains
- smarthost/transport
- smarthost/gateways.cidr
- smarthost/mynetworks.cidr
- smarthost/tls_policy
@@ -0,0 +1,78 @@
---
# Gateways (public IPs, see smarthost/gateways.cidr), lab networks (incl. node IPs for kubelet probes) and opted-in pods in any namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: smarthost
namespace: mail
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: smarthost
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 192.0.2.1/32
- ipBlock:
cidr: 192.0.2.2/32
- ipBlock:
cidr: 10.10.12.200/32
- ipBlock:
cidr: 198.18.1.10/32
- ipBlock:
cidr: 198.18.2.160/27
- ipBlock:
cidr: 198.18.2.192/27
- ipBlock:
cidr: 198.18.13.0/24
- ipBlock:
cidr: 198.18.14.0/24
- ipBlock:
cidr: 198.18.15.0/24
- ipBlock:
cidr: 198.18.16.0/24
- ipBlock:
cidr: 198.18.17.0/24
- ipBlock:
cidr: 198.18.18.0/24
- ipBlock:
cidr: 198.18.19.0/24
- ipBlock:
cidr: 198.18.20.0/24
- ipBlock:
cidr: 198.18.21.0/24
- ipBlock:
cidr: 198.18.22.0/24
- ipBlock:
cidr: 198.18.23.0/24
- ipBlock:
cidr: 198.18.25.0/24
- ipBlock:
cidr: 198.18.26.0/24
- ipBlock:
cidr: 198.18.27.0/24
- ipBlock:
cidr: 198.18.28.0/24
- ipBlock:
cidr: 198.18.29.0/24
- ipBlock:
cidr: 198.18.64.0/24
- ipBlock:
cidr: 198.18.65.0/24
- ipBlock:
cidr: 198.18.66.0/24
- ipBlock:
cidr: 198.18.67.0/24
- ipBlock:
cidr: 198.18.68.0/24
- ipBlock:
cidr: 198.18.69.0/24
- namespaceSelector: {}
podSelector:
matchLabels:
mail.unkin.net/smarthost-client: "true"
ports:
- port: smtp
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: smarthost
namespace: mail
spec:
maxUnavailable: 1
selector:
matchLabels:
app.kubernetes.io/name: smarthost
+33
View File
@@ -0,0 +1,33 @@
---
apiVersion: v1
kind: Service
metadata:
name: smarthost
namespace: mail
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: smarthost
ports:
- name: smtp
port: 25
targetPort: smtp
---
# Gateways and lab networks; Local keeps client IPs for the postfix CIDR checks.
apiVersion: v1
kind: Service
metadata:
name: smarthost-lb
namespace: mail
annotations:
purelb.io/addresses: 198.18.200.16
purelb.io/service-group: common
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: smarthost
ports:
- name: smtp
port: 25
targetPort: smtp
+117
View File
@@ -0,0 +1,117 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: smarthost
namespace: mail
annotations:
configmap.reloader.stakater.com/reload: "smarthost-config"
spec:
serviceName: smarthost
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: smarthost
template:
metadata:
labels:
app.kubernetes.io/name: smarthost
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/name: smarthost
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: postfix
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/postfix:0.1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 25
name: smtp
protocol: TCP
readinessProbe:
tcpSocket:
port: smtp
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
exec:
command: ["postfix", "status"]
initialDelaySeconds: 30
periodSeconds: 30
# postfix master runs as root and drops to the postfix user per service.
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETUID
- SETGID
- NET_BIND_SERVICE
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumeMounts:
- name: spool
mountPath: /var/spool/postfix
- name: tls
mountPath: /etc/postfix/tls
readOnly: true
- name: config
mountPath: /etc/postfix/main.cf
subPath: main.cf
readOnly: true
- name: config
mountPath: /etc/postfix/master.cf
subPath: master.cf
readOnly: true
- name: config
mountPath: /etc/postfix/relay_domains
subPath: relay_domains
readOnly: true
- name: config
mountPath: /etc/postfix/transport
subPath: transport
readOnly: true
- name: config
mountPath: /etc/postfix/gateways.cidr
subPath: gateways.cidr
readOnly: true
- name: config
mountPath: /etc/postfix/mynetworks.cidr
subPath: mynetworks.cidr
readOnly: true
- name: config
mountPath: /etc/postfix/tls_policy
subPath: tls_policy
readOnly: true
volumes:
- name: config
configMap:
name: smarthost-config
- name: tls
secret:
secretName: wildcard-main-unkin-net-tls
volumeClaimTemplates:
- metadata:
name: spool
spec:
accessModes: [ReadWriteOnce]
storageClassName: cephrbd-fast-delete
resources:
requests:
storage: 50Gi
+3
View File
@@ -0,0 +1,3 @@
# Gateway (mta1/mta2) public IPs; TEST-NET placeholders until the BinaryLane servers exist.
192.0.2.1/32 reject_plaintext_session, permit
192.0.2.2/32 reject_plaintext_session, permit
+42
View File
@@ -0,0 +1,42 @@
compatibility_level = 3.5
myhostname = mail-in.main.unkin.net
myorigin = unkin.net
mydestination =
alias_maps =
local_recipient_maps =
inet_interfaces = all
inet_protocols = ipv4
maillog_file = /dev/stdout
message_size_limit = 52428800
# Relay-anywhere clients; gateways must stay out.
mynetworks = cidr:/etc/postfix/mynetworks.cidr
relay_domains = texthash:/etc/postfix/relay_domains
# Default minus relay_domains: subdomains are not delivered and would loop back out via the gateways.
parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients,smtpd_access_maps
transport_maps = texthash:/etc/postfix/transport
relayhost = [mta1.edge.unkin.net]:25
smtp_fallback_relay = [mta2.edge.unkin.net]:25
smtp_tls_policy_maps = texthash:/etc/postfix/tls_policy
smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt
smtpd_client_restrictions = permit_mynetworks, check_client_access cidr:/etc/postfix/gateways.cidr, reject
smtpd_relay_restrictions = permit_mynetworks, reject_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, reject_unverified_recipient
unverified_recipient_reject_code = 550
unverified_recipient_tempfail_action = defer_if_permit
address_verify_negative_refresh_time = 5m
address_verify_negative_expire_time = 1h
address_verify_positive_refresh_time = 1h
address_verify_positive_expire_time = 1d
milter_default_action = tempfail
smtpd_milters = inet:rspamd.mail.svc:11332
smtpd_authorized_xforward_hosts = cidr:/etc/postfix/gateways.cidr
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/postfix/tls/tls.crt
smtpd_tls_key_file = /etc/postfix/tls/tls.key
smtpd_tls_received_header = yes
smtp_tls_security_level = may
lmtp_tls_security_level = none
+27
View File
@@ -0,0 +1,27 @@
# Gateways (inbound to relay_domains) and mynetworks (relay anywhere); all via the rspamd milter.
25 inet n - n - - smtpd
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
-o syslog_name=postfix/$service_name
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
postlog unix-dgram n - n - 1 postlogd
+31
View File
@@ -0,0 +1,31 @@
# Pod CIDR (narrowed by smarthost-networkpolicy.yaml) plus the lab networks from bind-internal acl-main/acl-common/acl-nomad-jobs.
# Keep in sync with the NetworkPolicy.
10.42.0.0/16 OK
10.10.12.200/32 OK
198.18.1.10/32 OK
198.18.2.160/27 OK
198.18.2.192/27 OK
198.18.21.160/27 OK
198.18.21.192/27 OK
198.18.13.0/24 OK
198.18.14.0/24 OK
198.18.15.0/24 OK
198.18.16.0/24 OK
198.18.17.0/24 OK
198.18.18.0/24 OK
198.18.19.0/24 OK
198.18.20.0/24 OK
198.18.21.0/24 OK
198.18.22.0/24 OK
198.18.23.0/24 OK
198.18.25.0/24 OK
198.18.26.0/24 OK
198.18.27.0/24 OK
198.18.28.0/24 OK
198.18.29.0/24 OK
198.18.64.0/24 OK
198.18.65.0/24 OK
198.18.66.0/24 OK
198.18.67.0/24 OK
198.18.68.0/24 OK
198.18.69.0/24 OK
+1
View File
@@ -0,0 +1 @@
unkin.net OK
+2
View File
@@ -0,0 +1,2 @@
[mta1.edge.unkin.net]:25 secure match=hostname
[mta2.edge.unkin.net]:25 secure match=hostname
+1
View File
@@ -0,0 +1 @@
unkin.net lmtp:[stalwart.mail.svc.cluster.local]:24