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