5ed2ef0958
Build and Deploy Platform / build-push-deploy (push) Has been cancelled
Harbor in-cluster builds via Kaniko, ArgoCD auto-sync, and production Helm values for abrban.com domains. Co-authored-by: Cursor <cursoragent@cursor.com>
249 lines
6.5 KiB
YAML
249 lines
6.5 KiB
YAML
# Maddy mail server — lightweight full mail server (SMTP + IMAP + DKIM)
|
|
# Namespace: mail | Host: mail.abrban.com | Primary domain: abrban.com
|
|
#
|
|
# Exposed on node IP 78.157.39.52 via k3s servicelb (klipper).
|
|
# TLS uses the *.abrban.com wildcard cert (secret abrban-wildcard-tls, copied into ns mail).
|
|
#
|
|
# NOTE (Iran/IP reputation): inbound mail (receiving) works; outbound delivery to
|
|
# Gmail/Outlook may be blocked or land in spam, and outbound port 25 may be filtered
|
|
# by the ISP. Use a smarthost relay if real external delivery is required.
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: maddy-config
|
|
namespace: mail
|
|
data:
|
|
maddy.conf: |
|
|
## Maddy Mail Server - configuration (mail.abrban.com)
|
|
|
|
$(hostname) = mail.abrban.com
|
|
$(primary_domain) = abrban.com
|
|
$(local_domains) = $(primary_domain)
|
|
|
|
tls file /etc/maddy/tls/tls.crt /etc/maddy/tls/tls.key
|
|
|
|
# ---- Local storage & authentication ----
|
|
storage.imapsql local_mailboxes {
|
|
driver sqlite3
|
|
dsn imapsql.db
|
|
}
|
|
|
|
auth.pass_table local_authdb {
|
|
table sql_table {
|
|
driver sqlite3
|
|
dsn credentials.db
|
|
table_name passwords
|
|
}
|
|
}
|
|
|
|
# ---- Routing ----
|
|
hostname $(hostname)
|
|
|
|
table.chain local_rewrites {
|
|
optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3"
|
|
optional_step static {
|
|
entry postmaster postmaster@$(primary_domain)
|
|
}
|
|
optional_step file /data/aliases
|
|
}
|
|
|
|
msgpipeline local_routing {
|
|
destination postmaster $(local_domains) {
|
|
modify {
|
|
replace_rcpt &local_rewrites
|
|
}
|
|
deliver_to &local_mailboxes
|
|
}
|
|
default_destination {
|
|
reject 550 5.1.1 "User doesn't exist"
|
|
}
|
|
}
|
|
|
|
# ---- Inbound SMTP (port 25) ----
|
|
smtp tcp://0.0.0.0:25 {
|
|
limits {
|
|
all rate 20 1s
|
|
all concurrency 10
|
|
}
|
|
dmarc yes
|
|
check {
|
|
require_mx_record
|
|
dkim
|
|
spf
|
|
}
|
|
source $(local_domains) {
|
|
reject 501 5.1.8 "Use Submission for outgoing SMTP"
|
|
}
|
|
default_source {
|
|
destination postmaster $(local_domains) {
|
|
deliver_to &local_routing
|
|
}
|
|
default_destination {
|
|
reject 550 5.1.1 "User doesn't exist"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ---- Submission (ports 465 implicit-TLS, 587 STARTTLS) ----
|
|
submission tls://0.0.0.0:465 tcp://0.0.0.0:587 {
|
|
limits {
|
|
all rate 50 1s
|
|
}
|
|
auth &local_authdb
|
|
source $(local_domains) {
|
|
check {
|
|
authorize_sender {
|
|
prepare_email &local_rewrites
|
|
user_to_email identity
|
|
}
|
|
}
|
|
destination postmaster $(local_domains) {
|
|
deliver_to &local_routing
|
|
}
|
|
default_destination {
|
|
modify {
|
|
dkim $(primary_domain) $(hostname) default
|
|
}
|
|
deliver_to &remote_queue
|
|
}
|
|
}
|
|
default_source {
|
|
reject 501 5.1.8 "Non-local sender domain"
|
|
}
|
|
}
|
|
|
|
# ---- Outbound delivery queue ----
|
|
target.remote outbound_delivery {
|
|
limits {
|
|
destination rate 20 1s
|
|
destination concurrency 10
|
|
}
|
|
mx_auth {
|
|
dane
|
|
mtasts {
|
|
cache fs
|
|
fs_dir mtasts_cache/
|
|
}
|
|
local_policy {
|
|
min_tls_level encrypted
|
|
min_mx_level none
|
|
}
|
|
}
|
|
}
|
|
|
|
target.queue remote_queue {
|
|
target &outbound_delivery
|
|
autogenerated_msg_domain $(primary_domain)
|
|
bounce {
|
|
destination postmaster $(local_domains) {
|
|
deliver_to &local_routing
|
|
}
|
|
default_destination {
|
|
reject 550 5.0.0 "Refusing to send DSNs to non-local addresses"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ---- IMAP (993 implicit-TLS, 143 STARTTLS) ----
|
|
imap tls://0.0.0.0:993 tcp://0.0.0.0:143 {
|
|
auth &local_authdb
|
|
storage &local_mailboxes
|
|
}
|
|
---
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: maddy-data
|
|
namespace: mail
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
storageClassName: local-path
|
|
resources:
|
|
requests:
|
|
storage: 5Gi
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: maddy
|
|
namespace: mail
|
|
labels:
|
|
app: maddy
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app: maddy
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: maddy
|
|
spec:
|
|
containers:
|
|
- name: maddy
|
|
image: foxcpp/maddy:0.7
|
|
imagePullPolicy: IfNotPresent
|
|
env:
|
|
- name: MADDY_HOSTNAME
|
|
value: mail.abrban.com
|
|
- name: MADDY_DOMAIN
|
|
value: abrban.com
|
|
ports:
|
|
- { name: smtp, containerPort: 25 }
|
|
- { name: submission, containerPort: 587 }
|
|
- { name: smtps, containerPort: 465 }
|
|
- { name: imap, containerPort: 143 }
|
|
- { name: imaps, containerPort: 993 }
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /data
|
|
- name: config
|
|
mountPath: /data/maddy.conf
|
|
subPath: maddy.conf
|
|
- name: tls
|
|
mountPath: /etc/maddy/tls
|
|
readOnly: true
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 256Mi
|
|
livenessProbe:
|
|
tcpSocket: { port: 25 }
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 30
|
|
volumes:
|
|
- name: data
|
|
persistentVolumeClaim:
|
|
claimName: maddy-data
|
|
- name: config
|
|
configMap:
|
|
name: maddy-config
|
|
- name: tls
|
|
secret:
|
|
secretName: abrban-wildcard-tls
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: maddy
|
|
namespace: mail
|
|
labels:
|
|
app: maddy
|
|
spec:
|
|
type: LoadBalancer
|
|
externalTrafficPolicy: Local # preserve client source IP (needed for SPF/spam checks)
|
|
selector:
|
|
app: maddy
|
|
ports:
|
|
- { name: smtp, port: 25, targetPort: 25 }
|
|
- { name: submission, port: 587, targetPort: 587 }
|
|
- { name: smtps, port: 465, targetPort: 465 }
|
|
- { name: imap, port: 143, targetPort: 143 }
|
|
- { name: imaps, port: 993, targetPort: 993 }
|