Installer: mail-gateway configure downstream smtp server addresses
diff --git a/apps/maddy/auth/main.go b/apps/maddy/auth/main.go
index ab71fdb..6454eb4 100644
--- a/apps/maddy/auth/main.go
+++ b/apps/maddy/auth/main.go
@@ -3,6 +3,7 @@
import (
"bufio"
"crypto/tls"
+ "flag"
"fmt"
"os"
@@ -10,9 +11,23 @@
"github.com/emersion/go-smtp"
)
-var smtpServers = []string{
- "maddy.app-maddy.svc.cluster.local:587",
- "maddy.shveli-app-maddy.svc.cluster.local:587",
+var config = flag.String("config", "/etc/maddy/config/smtp-servers.conf", "Path to the configuration file with downstream SMTP server addresses per line.")
+
+func readConfig(path string) ([]string, error) {
+ inp, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer inp.Close()
+ lines := bufio.NewScanner(inp)
+ ret := make([]string, 0)
+ for lines.Scan() {
+ ret = append(ret, lines.Text())
+ }
+ if err := lines.Err(); err != nil {
+ return nil, err
+ }
+ return ret, nil
}
func auth(server, username, password string) (bool, error) {
@@ -30,6 +45,7 @@
}
func main() {
+ flag.Parse()
inp := bufio.NewReader(os.Stdin)
username, err := inp.ReadString('\n')
if err != nil {
@@ -43,6 +59,11 @@
os.Exit(2)
}
password = password[:len(password)-1]
+ smtpServers, err := readConfig(*config)
+ if err != nil {
+ fmt.Println(err.Error())
+ os.Exit(2)
+ }
for _, s := range smtpServers {
if ok, _ := auth(s, username, password); ok {
os.Exit(0)
diff --git a/charts/maddy/templates/install.yaml b/charts/maddy/templates/install.yaml
index dad1fa7..6605094 100644
--- a/charts/maddy/templates/install.yaml
+++ b/charts/maddy/templates/install.yaml
@@ -49,7 +49,7 @@
tls:
- hosts:
- mail.{{ .Values.ingress.private.domain }}
- secretName: cert-mail.{{ .Values.ingress.private.domain }}
+ secretName: cert-wildcard.{{ .Values.ingress.private.domain }}
rules:
- host: mail.{{ .Values.ingress.private.domain }}
http:
@@ -245,7 +245,7 @@
name: mta-sts.{{ .Values.ingress.public.domain }}
namespace: {{ .Release.Namespace }}
annotations:
- "helm.sh/resource-policy": keep
+ helm.sh/resource-policy: keep
spec:
dnsNames:
- 'mta-sts.{{ .Values.ingress.public.domain }}'
diff --git a/charts/mail-gateway/templates/config.yaml b/charts/mail-gateway/templates/config.yaml
new file mode 100644
index 0000000..457f524
--- /dev/null
+++ b/charts/mail-gateway/templates/config.yaml
@@ -0,0 +1,144 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: maddy
+ namespace: {{ .Release.Namespace }}
+data:
+ smtp-servers.conf: |
+ maddy.{{ .Values.domains.primary.namespace}}.svc.cluster.local:587
+ {{ range .Values.domains.others}}
+ maddy.{{ .namespace }}.svc.cluster.local:587
+ {{ end }}
+ maddy.conf: |
+ $(hostname) = {{ .Values.domains.primary.mx }}
+ $(primary_domain) = {{ .Values.domains.primary.name }}
+ $(local_domains) = {{ .Values.domains.primary.name }}{{ range .Values.domains.others }} {{ .name }}{{ end }}
+
+ tls file /etc/maddy/certs/tls.crt /etc/maddy/certs/tls.key
+
+ auth.external authsmtp {
+ helper /usr/bin/auth-smtp
+ perdomain yes
+ domains $(local_domains)
+ }
+
+ hostname $(hostname)
+
+ msgpipeline local_routing {
+ destination {{ .Values.domains.primary.name }} {
+ deliver_to &{{ .Values.domains.primary.name }}
+ }
+ {{ range .Values.domains.others }}
+ destination {{ .name }} {
+ deliver_to &{{ .name }}
+ }
+ {{ end }}
+ default_destination {
+ reject 550 5.1.1 "User doesn't exist"
+ }
+ }
+
+ smtp tcp://0.0.0.0:25 {
+ insecure_auth no
+
+ defer_sender_reject yes
+
+ limits {
+ # Up to 20 msgs/sec across max. 10 SMTP connections.
+ 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 $(local_domains) {
+ deliver_to &local_routing
+ }
+ default_destination {
+ reject 550 5.1.1 "User doesn't exist"
+ }
+ }
+ }
+
+ submission tls://0.0.0.0:465 tcp://0.0.0.0:587 {
+ auth &authsmtp
+ insecure_auth yes
+
+ defer_sender_reject yes
+
+ source $(local_domains) {
+ destination $(local_domains) {
+ deliver_to &local_routing
+ }
+ default_destination {
+ modify {
+ dkim $(primary_domain) $(local_domains) default
+ }
+ deliver_to &remote_queue
+ }
+ }
+ default_source {
+ reject 501 5.1.8 "Non-local sender domain"
+ }
+ }
+
+ target.smtp {{ .Values.domains.primary.name }} {
+ hostname $(hostname)
+ attempt_starttls false
+ require_tls no
+ auth off
+ targets tcp://maddy.{{ .Values.domains.primary.namespace }}.svc.cluster.local:25
+ }
+
+ {{ range .Values.domains.others }}
+ target.smtp {{ .name }} {
+ hostname mail.{{ .name }}
+ attempt_starttls false
+ require_tls no
+ auth off
+ targets tcp://maddy.{{ .namespace }}.svc.cluster.local:25
+ }
+ {{ end }}
+
+ 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"
+ }
+ }
+ }
+
+ target.remote outbound_delivery {
+ limits {
+ # Up to 20 msgs/sec across max. 10 SMTP connections
+ # for each recipient domain.
+ 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
+ }
+ }
+ }
diff --git a/charts/mail-gateway/templates/maddy.yaml b/charts/mail-gateway/templates/maddy.yaml
index c80fe90..d3469b7 100644
--- a/charts/mail-gateway/templates/maddy.yaml
+++ b/charts/mail-gateway/templates/maddy.yaml
@@ -1,143 +1,3 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: maddy
- namespace: {{ .Release.Namespace }}
-data:
- maddy.conf: |
- $(hostname) = {{ .Values.mxHostname }}
- $(primary_domain) = {{ .Values.domains.primary.name }}
- $(local_domains) = {{ .Values.domains.primary.name }}{{ range .Values.domains.others }} {{ .name }}{{ end }}
-
- tls file /etc/maddy/certs/tls.crt /etc/maddy/certs/tls.key
-
- auth.external authsmtp {
- helper /usr/bin/auth-smtp
- perdomain yes
- domains $(local_domains)
- }
-
- hostname $(hostname)
-
- msgpipeline local_routing {
- destination {{ .Values.domains.primary.name }} {
- deliver_to &{{ .Values.domains.primary.name }}
- }
- {{ range .Values.domains.others }}
- destination {{ .name }} {
- deliver_to &{{ .name }}
- }
- {{ end }}
- default_destination {
- reject 550 5.1.1 "User doesn't exist"
- }
- }
-
- smtp tcp://0.0.0.0:25 {
- insecure_auth no
-
- defer_sender_reject yes
-
- limits {
- # Up to 20 msgs/sec across max. 10 SMTP connections.
- 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 $(local_domains) {
- deliver_to &local_routing
- }
- default_destination {
- reject 550 5.1.1 "User doesn't exist"
- }
- }
- }
-
- submission tls://0.0.0.0:465 tcp://0.0.0.0:587 {
- auth &authsmtp
- insecure_auth yes
-
- defer_sender_reject yes
-
- source $(local_domains) {
- destination $(local_domains) {
- deliver_to &local_routing
- }
- default_destination {
- modify {
- dkim $(primary_domain) $(local_domains) default
- }
- deliver_to &remote_queue
- }
- }
- default_source {
- reject 501 5.1.8 "Non-local sender domain"
- }
- }
-
- target.smtp {{ .Values.domains.primary.name }} {
- hostname $(hostname)
- attempt_starttls false
- require_tls no
- auth off
- targets tcp://maddy.{{ .Values.domains.primary.namespace }}.svc.cluster.local:25
- }
-
- {{ range .Values.domains.others }}
- target.smtp {{ .name }} {
- hostname mail.{{ .name }}
- attempt_starttls false
- require_tls no
- auth off
- targets tcp://maddy.{{ .namespace }}.svc.cluster.local:25
- }
- {{ end }}
-
- 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"
- }
- }
- }
-
- target.remote outbound_delivery {
- limits {
- # Up to 20 msgs/sec across max. 10 SMTP connections
- # for each recipient domain.
- 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
- }
- }
- }
----
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -152,6 +12,8 @@
metadata:
labels:
app: maddy
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }}
spec:
volumes:
- name: config
@@ -159,7 +21,7 @@
name: maddy
- name: certs
secret:
- secretName: cert-{{ .Values.mxHostname }}
+ secretName: cert-{{ .Values.domains.primary.mx }}
- name: data
persistentVolumeClaim:
claimName: data
diff --git a/charts/mail-gateway/templates/mx-certificate.yaml b/charts/mail-gateway/templates/mx-certificate.yaml
new file mode 100644
index 0000000..c4012ae
--- /dev/null
+++ b/charts/mail-gateway/templates/mx-certificate.yaml
@@ -0,0 +1,14 @@
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ .Values.domains.primary.mx }}
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/resource-policy": keep
+spec:
+ dnsNames:
+ - {{ .Values.domains.primary.mx }}
+ issuerRef:
+ name: {{ .Values.domains.primary.certificateIssuer }}
+ kind: ClusterIssuer
+ secretName: cert-{{ .Values.domains.primary.mx }}
diff --git a/charts/mail-gateway/values.yaml b/charts/mail-gateway/values.yaml
index 1b066c9..4810334 100644
--- a/charts/mail-gateway/values.yaml
+++ b/charts/mail-gateway/values.yaml
@@ -1,8 +1,9 @@
-mxHostname: mx1.example.com
domains:
primary:
name: example.com
namespace: example-app-maddy
+ mx: mx1.example.com
+ certificateIssuer: public
others:
- name: other.com
namespace: other-app-maddy
diff --git a/helmfile/base/helmfile.yaml b/helmfile/base/helmfile.yaml
index 612760f..83d7097 100644
--- a/helmfile/base/helmfile.yaml
+++ b/helmfile/base/helmfile.yaml
@@ -173,11 +173,12 @@
chart: ../../charts/mail-gateway
namespace: {{ .Values.name }}-mail-gateway
values:
- - mxHostname: mx1.lekva.me
- domains:
primary:
name: lekva.me
- namespace: app-maddy
+ namespace: lekva-app-maddy
+ mx: mail.lekva.me
+ certificateIssuer: lekva-public
others:
- name: shve.li
namespace: shveli-app-maddy