Adding wildduck for testing
This commit is contained in:
187
share/wildduck/haraka.tf
Normal file
187
share/wildduck/haraka.tf
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
locals {
|
||||||
|
haraka-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "haraka"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "haraka_deploy" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-haraka"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.haraka-labels)}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: ${jsonencode(local.haraka-labels)}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: ${jsonencode(local.haraka-labels)}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: wildduck
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
image: "${var.images.haraka.registry}/${var.images.haraka.repository}:${var.images.haraka.tag}"
|
||||||
|
imagePullPolicy: "${var.images.haraka.pullPolicy}"
|
||||||
|
ports:
|
||||||
|
- name: smtp
|
||||||
|
containerPort: 25
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: smtp
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: smtp
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 30
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /app/config
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: "${var.instance}-haraka"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "haraka_config" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-haraka"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.haraka-labels)}
|
||||||
|
data:
|
||||||
|
me: |-
|
||||||
|
${var.sub-domain}.${var.domain-name}
|
||||||
|
host_list: |-
|
||||||
|
# add hosts in here we want to accept mail for
|
||||||
|
${var.sub-domain}.${var.domain-name}
|
||||||
|
${var.domain-name}
|
||||||
|
${join("\n ",var.additional-domains)}
|
||||||
|
rspamd.ini: |-
|
||||||
|
host = ${var.instance}-rspamd.${var.namespace}.svc.cluster.local
|
||||||
|
port = 11333
|
||||||
|
add_headers = always
|
||||||
|
[dkim]
|
||||||
|
enabled = true
|
||||||
|
[header]
|
||||||
|
bar = X-Rspamd-Bar
|
||||||
|
report = X-Rspamd-Report
|
||||||
|
score = X-Rspamd-Score
|
||||||
|
spam = X-Rspamd-Spam
|
||||||
|
[check]
|
||||||
|
authenticated=true
|
||||||
|
private_ip=true
|
||||||
|
[reject]
|
||||||
|
spam = false
|
||||||
|
[soft_reject]
|
||||||
|
enabled = true
|
||||||
|
[rmilter_headers]
|
||||||
|
enabled = true
|
||||||
|
[spambar]
|
||||||
|
positive = +
|
||||||
|
negative = -
|
||||||
|
neutral = /'
|
||||||
|
wildduck.yaml: |-
|
||||||
|
## Connect to a master instance or Redis
|
||||||
|
redis:
|
||||||
|
port: 6379
|
||||||
|
host: "${var.instance}-${var.component}-redis.${var.namespace}.svc"
|
||||||
|
db: 3
|
||||||
|
mongo:
|
||||||
|
# connection string for main messages database
|
||||||
|
url: 'mongodb://${var.component}:${local.mongo-password}@${var.instance}-${var.component}-mongo-svc.${var.namespace}.svc:27017/wildduck'
|
||||||
|
## database name or connection string for the users db
|
||||||
|
#users: "users"
|
||||||
|
## database name or connection string for the attachments db
|
||||||
|
#gridfs: "attachments"
|
||||||
|
## database name or connection string for the outbound queue
|
||||||
|
sender: 'mongodb://${var.component}:${local.mongo-password}@${var.instance}-${var.component}-mongo-svc.${var.namespace}.svc:27017/zone-mta'
|
||||||
|
sender:
|
||||||
|
# Push messages to ZoneMTA queue for delivery
|
||||||
|
# if `false` then no messages are sent
|
||||||
|
enabled: true
|
||||||
|
# which ZoneMTA queue to use by default. This mostly affects forwarded messages
|
||||||
|
zone: 'default'
|
||||||
|
# Collection name for GridFS storage
|
||||||
|
gfs: 'mail'
|
||||||
|
# Collection name for the queue
|
||||||
|
# see [dbs].sender option for choosing correct database to use for ZoneMTA queues
|
||||||
|
# by default the main wildduck database is used
|
||||||
|
collection: 'zone-queue'
|
||||||
|
# Hashing secret for loop detection
|
||||||
|
# Must be shared with wildduck
|
||||||
|
# If not set then looping is not tracked
|
||||||
|
loopSecret: '${local.secrets.srs}'
|
||||||
|
srs:
|
||||||
|
# must be shared with ZoneMTA SRS config, otherwise messages sent from ZoneMTA are not recognized by Haraka
|
||||||
|
secret: 'secret value'
|
||||||
|
attachments:
|
||||||
|
type: 'gridstore'
|
||||||
|
bucket: 'attachments'
|
||||||
|
decodeBase64: true
|
||||||
|
log:
|
||||||
|
authlogExpireDays: 30
|
||||||
|
limits:
|
||||||
|
windowSize: 3600 # 1 hour
|
||||||
|
rcptIp: 100 # allowed messages for the same recipient from same IP during window size
|
||||||
|
rcptWindowSize: 60 # 1 minute
|
||||||
|
rcpt: 60 # allowed messages for the same recipient during window size
|
||||||
|
gelf:
|
||||||
|
enabled: false
|
||||||
|
component: 'mx'
|
||||||
|
options:
|
||||||
|
graylogPort: 12201
|
||||||
|
graylogHostname: '127.0.0.1'
|
||||||
|
connection: 'lan'
|
||||||
|
rspamd:
|
||||||
|
# do not process forwarding addresses for messages with the following spam score
|
||||||
|
forwardSkip: 10
|
||||||
|
# if a message has one of the tags listed here with positive score, the message will be rejected
|
||||||
|
blacklist:
|
||||||
|
- DMARC_POLICY_REJECT
|
||||||
|
# if a message has one of the tags listed here with positive score, the message will be soft rejected
|
||||||
|
softlist:
|
||||||
|
- RBL_ZONE
|
||||||
|
# define special responses
|
||||||
|
responses:
|
||||||
|
DMARC_POLICY_REJECT: "Unauthenticated email from {host} is not accepted due to domain's DMARC policy"
|
||||||
|
RBL_ZONE: '[{host}] was found from Zone RBL'
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "haraka_service" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-haraka"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.haraka-labels)}
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
ports:
|
||||||
|
- port: 25
|
||||||
|
targetPort: smtp
|
||||||
|
protocol: TCP
|
||||||
|
name: smtp
|
||||||
|
selector: ${jsonencode(local.haraka-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
252
share/wildduck/index.yaml
Normal file
252
share/wildduck/index.yaml
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
---
|
||||||
|
apiVersion: vinyl.solidite.fr/v1beta1
|
||||||
|
kind: Component
|
||||||
|
category: share
|
||||||
|
metadata:
|
||||||
|
name: wildduck
|
||||||
|
description: null
|
||||||
|
options:
|
||||||
|
domain-name:
|
||||||
|
default: your_company.com
|
||||||
|
examples:
|
||||||
|
- your_company.com
|
||||||
|
type: string
|
||||||
|
domain:
|
||||||
|
default: your-company
|
||||||
|
examples:
|
||||||
|
- your-company
|
||||||
|
type: string
|
||||||
|
issuer:
|
||||||
|
default: letsencrypt-prod
|
||||||
|
examples:
|
||||||
|
- letsencrypt-prod
|
||||||
|
type: string
|
||||||
|
ingress-class:
|
||||||
|
default: traefik
|
||||||
|
examples:
|
||||||
|
- traefik
|
||||||
|
type: string
|
||||||
|
images:
|
||||||
|
default:
|
||||||
|
haraka:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-haraka
|
||||||
|
tag: 3.0.2
|
||||||
|
rspamd:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-rspamd
|
||||||
|
tag: 3.18.3
|
||||||
|
webmail:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck-webmail
|
||||||
|
tag: 1.0.1
|
||||||
|
wildduck:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck
|
||||||
|
tag: 1.39.10
|
||||||
|
zonemta:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-zonemta
|
||||||
|
tag: 3.4.0
|
||||||
|
examples:
|
||||||
|
- haraka:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-haraka
|
||||||
|
tag: 3.0.2
|
||||||
|
rspamd:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-rspamd
|
||||||
|
tag: 3.18.3
|
||||||
|
webmail:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck-webmail
|
||||||
|
tag: 1.0.1
|
||||||
|
wildduck:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck
|
||||||
|
tag: 1.39.10
|
||||||
|
zonemta:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-zonemta
|
||||||
|
tag: 3.4.0
|
||||||
|
properties:
|
||||||
|
haraka:
|
||||||
|
default:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-haraka
|
||||||
|
tag: 3.0.2
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
default: IfNotPresent
|
||||||
|
type: string
|
||||||
|
registry:
|
||||||
|
default: docker.io
|
||||||
|
type: string
|
||||||
|
repository:
|
||||||
|
default: sebt3/wildduck-haraka
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
default: 3.0.2
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
operator:
|
||||||
|
default: null
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
enum:
|
||||||
|
- Always
|
||||||
|
- Never
|
||||||
|
- IfNotPresent
|
||||||
|
rspamd:
|
||||||
|
default:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-rspamd
|
||||||
|
tag: 3.18.3
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
default: IfNotPresent
|
||||||
|
type: string
|
||||||
|
registry:
|
||||||
|
default: docker.io
|
||||||
|
type: string
|
||||||
|
repository:
|
||||||
|
default: sebt3/wildduck-rspamd
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
default: 3.18.3
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
webmail:
|
||||||
|
default:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck-webmail
|
||||||
|
tag: 1.0.1
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
default: IfNotPresent
|
||||||
|
type: string
|
||||||
|
registry:
|
||||||
|
default: docker.io
|
||||||
|
type: string
|
||||||
|
repository:
|
||||||
|
default: nodemailer/wildduck-webmail
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
default: 1.0.1
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
wildduck:
|
||||||
|
default:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: nodemailer/wildduck
|
||||||
|
tag: 1.39.10
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
default: IfNotPresent
|
||||||
|
type: string
|
||||||
|
registry:
|
||||||
|
default: docker.io
|
||||||
|
type: string
|
||||||
|
repository:
|
||||||
|
default: nodemailer/wildduck
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
default: 1.39.10
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
zonemta:
|
||||||
|
default:
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
registry: docker.io
|
||||||
|
repository: sebt3/wildduck-zonemta
|
||||||
|
tag: 3.4.0
|
||||||
|
properties:
|
||||||
|
pullPolicy:
|
||||||
|
default: IfNotPresent
|
||||||
|
type: string
|
||||||
|
registry:
|
||||||
|
default: docker.io
|
||||||
|
type: string
|
||||||
|
repository:
|
||||||
|
default: sebt3/wildduck-zonemta
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
default: 3.4.0
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
redis:
|
||||||
|
default:
|
||||||
|
exporter:
|
||||||
|
enabled: true
|
||||||
|
image: quay.io/opstree/redis-exporter:v1.44.0
|
||||||
|
image: quay.io/opstree/redis:v7.0.5
|
||||||
|
storage: 2Gi
|
||||||
|
examples:
|
||||||
|
- exporter:
|
||||||
|
enabled: true
|
||||||
|
image: quay.io/opstree/redis-exporter:v1.44.0
|
||||||
|
image: quay.io/opstree/redis:v7.0.5
|
||||||
|
storage: 2Gi
|
||||||
|
properties:
|
||||||
|
exporter:
|
||||||
|
default:
|
||||||
|
enabled: true
|
||||||
|
image: quay.io/opstree/redis-exporter:v1.44.0
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
image:
|
||||||
|
default: quay.io/opstree/redis-exporter:v1.44.0
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
image:
|
||||||
|
default: quay.io/opstree/redis:v7.0.5
|
||||||
|
type: string
|
||||||
|
storage:
|
||||||
|
default: 2Gi
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
additional-domains:
|
||||||
|
default: []
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
sub-domain:
|
||||||
|
default: mail
|
||||||
|
examples:
|
||||||
|
- mail
|
||||||
|
type: string
|
||||||
|
dependencies:
|
||||||
|
- dist: null
|
||||||
|
category: dbo
|
||||||
|
component: mongo
|
||||||
|
- dist: null
|
||||||
|
category: dbo
|
||||||
|
component: redis
|
||||||
|
- dist: null
|
||||||
|
category: core
|
||||||
|
component: secret-generator
|
||||||
|
providers:
|
||||||
|
kubernetes: true
|
||||||
|
authentik: null
|
||||||
|
kubectl: true
|
||||||
|
postgresql: null
|
||||||
|
restapi: null
|
||||||
|
http: null
|
||||||
|
tfaddtype: null
|
||||||
76
share/wildduck/ingress.tf
Normal file
76
share/wildduck/ingress.tf
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
locals {
|
||||||
|
dns-names = ["${var.sub-domain}.${var.domain-name}"]
|
||||||
|
cert-names = concat(local.dns-names, ["${var.domain-name}"])
|
||||||
|
middlewares = ["${var.instance}-https"]
|
||||||
|
service = {
|
||||||
|
"name" = "${var.instance}-webmail"
|
||||||
|
"port" = {
|
||||||
|
"number" = 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rules = [ for v in local.dns-names : {
|
||||||
|
"host" = "${v}"
|
||||||
|
"http" = {
|
||||||
|
"paths" = [{
|
||||||
|
"backend" = {
|
||||||
|
"service" = local.service
|
||||||
|
}
|
||||||
|
"path" = "/"
|
||||||
|
"pathType" = "Prefix"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "prj_certificate" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "cert-manager.io/v1"
|
||||||
|
kind: "Certificate"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
spec:
|
||||||
|
secretName: "${var.instance}-cert"
|
||||||
|
dnsNames: ${jsonencode(local.cert-names)}
|
||||||
|
issuerRef:
|
||||||
|
name: "${var.issuer}"
|
||||||
|
kind: "ClusterIssuer"
|
||||||
|
group: "cert-manager.io"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "prj_https_redirect" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "traefik.containo.us/v1alpha1"
|
||||||
|
kind: "Middleware"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-https"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
spec:
|
||||||
|
redirectScheme:
|
||||||
|
scheme: "https"
|
||||||
|
permanent: true
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "prj_ingress" {
|
||||||
|
force_conflicts = true
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "networking.k8s.io/v1"
|
||||||
|
kind: "Ingress"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
annotations:
|
||||||
|
"traefik.ingress.kubernetes.io/router.middlewares": "${join(",", [for m in local.middlewares : format("%s-%s@kubernetescrd", var.namespace, m)])}"
|
||||||
|
spec:
|
||||||
|
ingressClassName: "${var.ingress-class}"
|
||||||
|
rules: ${jsonencode(local.rules)}
|
||||||
|
tls:
|
||||||
|
- hosts: ${jsonencode(local.dns-names)}
|
||||||
|
secretName: "${var.instance}-cert"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
101
share/wildduck/mongo.tf
Normal file
101
share/wildduck/mongo.tf
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
locals {
|
||||||
|
mongo-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "mongo"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_mongo_secret" {
|
||||||
|
ignore_fields = ["metadata.annotations"]
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "secretgenerator.mittwald.de/v1alpha1"
|
||||||
|
kind: "StringSecret"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-${var.component}-mongo"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.mongo-labels)}
|
||||||
|
spec:
|
||||||
|
forceRegenerate: false
|
||||||
|
fields:
|
||||||
|
- fieldName: "password"
|
||||||
|
length: "16"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
data "kubernetes_secret_v1" "prj_mongo_secret" {
|
||||||
|
depends_on = [ kubectl_manifest.prj_mongo_secret ]
|
||||||
|
metadata {
|
||||||
|
name = "${var.instance}-${var.component}-mongo"
|
||||||
|
namespace = var.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locals {
|
||||||
|
mongo-password = data.kubernetes_secret_v1.prj_mongo_secret.data["password"]
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_mongo" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: mongodbcommunity.mongodb.com/v1
|
||||||
|
kind: MongoDBCommunity
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-${var.component}-mongo"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.mongo-labels)}
|
||||||
|
spec:
|
||||||
|
members: 1
|
||||||
|
type: ReplicaSet
|
||||||
|
version: "4.4.0"
|
||||||
|
security:
|
||||||
|
authentication:
|
||||||
|
modes: ["SCRAM"]
|
||||||
|
users:
|
||||||
|
- db: ${var.component}
|
||||||
|
name: ${var.component}
|
||||||
|
passwordSecretRef:
|
||||||
|
name: "${var.instance}-${var.component}-mongo"
|
||||||
|
roles:
|
||||||
|
- db: ${var.component}
|
||||||
|
name: readWrite
|
||||||
|
scramCredentialsSecretName: "${var.instance}-${var.component}-mongo-scram"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_mongo_sa" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: "mongodb-database"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.mongo-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_mongo_role" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: "mongodb-database"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.mongo-labels)}
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["secrets"]
|
||||||
|
verbs: ["get"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["patch", "delete", "get"]
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_mongo_rb" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: "mongodb-database"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.mongo-labels)}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: mongodb-database
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: mongodb-database
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
EOF
|
||||||
|
}
|
||||||
32
share/wildduck/redis.tf
Normal file
32
share/wildduck/redis.tf
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
locals {
|
||||||
|
redis-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "redis"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resource "kubectl_manifest" "prj_redis" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "redis.redis.opstreelabs.in/v1beta1"
|
||||||
|
kind: "Redis"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-${var.component}-redis"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.redis-labels)}
|
||||||
|
spec:
|
||||||
|
kubernetesConfig:
|
||||||
|
image: "${var.redis.image}"
|
||||||
|
imagePullPolicy: "IfNotPresent"
|
||||||
|
storage:
|
||||||
|
volumeClaimTemplate:
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: "${var.redis.storage}"
|
||||||
|
redisExporter:
|
||||||
|
enabled: ${var.redis.exporter.enabled}
|
||||||
|
image: "${var.redis.exporter.image}"
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
EOF
|
||||||
|
}
|
||||||
106
share/wildduck/rspamd.tf
Normal file
106
share/wildduck/rspamd.tf
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
locals {
|
||||||
|
rspamd-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "rspamd"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "rspamd_deploy" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-rspamd"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.rspamd-labels)}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: ${jsonencode(local.rspamd-labels)}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: ${jsonencode(local.rspamd-labels)}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 101
|
||||||
|
containers:
|
||||||
|
- name: wildduck
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 100
|
||||||
|
image: "${var.images.rspamd.registry}/${var.images.rspamd.repository}:${var.images.rspamd.tag}"
|
||||||
|
imagePullPolicy: "${var.images.rspamd.pullPolicy}"
|
||||||
|
ports:
|
||||||
|
- name: rspamd
|
||||||
|
containerPort: 11333
|
||||||
|
protocol: TCP
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /app/rspamd/worker-normal.conf
|
||||||
|
subPath: worker-normal.conf
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/rspamd/override.d/dmarc.conf
|
||||||
|
subPath: dmarc.conf
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/rspamd/override.d/redis.conf
|
||||||
|
subPath: redis.conf
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: "${var.instance}-rspamd"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "rspamd_config" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-rspamd"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.rspamd-labels)}
|
||||||
|
data:
|
||||||
|
worker-normal.conf: |-
|
||||||
|
# Included from top-level .conf file
|
||||||
|
|
||||||
|
worker "normal" {
|
||||||
|
bind_socket = "*:11333";
|
||||||
|
.include "$CONFDIR/worker-normal.inc"
|
||||||
|
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/worker-normal.inc"
|
||||||
|
.include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/worker-normal.inc"
|
||||||
|
}
|
||||||
|
dmarc.conf: |-
|
||||||
|
actions = {
|
||||||
|
quarantine = "add_header";
|
||||||
|
reject = "reject";
|
||||||
|
}
|
||||||
|
redis.conf: |-
|
||||||
|
servers = "${var.instance}-${var.component}-redis.${var.namespace}.svc:6379";
|
||||||
|
db = "4";
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "rspamd_service" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-rspamd"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.rspamd-labels)}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 11333
|
||||||
|
targetPort: rspamd
|
||||||
|
protocol: TCP
|
||||||
|
name: rspamd
|
||||||
|
selector: ${jsonencode(local.rspamd-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
40
share/wildduck/secret.tf
Normal file
40
share/wildduck/secret.tf
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
resource "kubectl_manifest" "wildduck_secret" {
|
||||||
|
ignore_fields = ["metadata.annotations"]
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: "secretgenerator.mittwald.de/v1alpha1"
|
||||||
|
kind: "StringSecret"
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.common-labels)}
|
||||||
|
spec:
|
||||||
|
forceRegenerate: false
|
||||||
|
fields:
|
||||||
|
- fieldName: "srs"
|
||||||
|
length: "32"
|
||||||
|
- fieldName: "zonemta"
|
||||||
|
length: "32"
|
||||||
|
- fieldName: "webmail"
|
||||||
|
length: "32"
|
||||||
|
- fieldName: "totp"
|
||||||
|
length: "32"
|
||||||
|
- fieldName: "dkim"
|
||||||
|
length: "32"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
data "kubernetes_secret_v1" "wildduck" {
|
||||||
|
depends_on = [ kubectl_manifest.wildduck_secret ]
|
||||||
|
metadata {
|
||||||
|
name = var.instance
|
||||||
|
namespace = var.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locals {
|
||||||
|
secrets = {
|
||||||
|
srs = data.kubernetes_secret_v1.wildduck.data["srs"]
|
||||||
|
zonemta = data.kubernetes_secret_v1.wildduck.data["zonemta"]
|
||||||
|
webmail = data.kubernetes_secret_v1.wildduck.data["webmail"]
|
||||||
|
totp = data.kubernetes_secret_v1.wildduck.data["totp"]
|
||||||
|
dkim = data.kubernetes_secret_v1.wildduck.data["dkim"]
|
||||||
|
}
|
||||||
|
}
|
||||||
177
share/wildduck/webmail.tf
Normal file
177
share/wildduck/webmail.tf
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
locals {
|
||||||
|
webmail-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "webmail"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "webmail_deploy" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-webmail"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: ${jsonencode(local.webmail-labels)}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: webmail
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
image: "${var.images.webmail.registry}/${var.images.webmail.repository}:${var.images.webmail.tag}"
|
||||||
|
imagePullPolicy: "${var.images.webmail.pullPolicy}"
|
||||||
|
args:
|
||||||
|
- "--config=./config/webmail.toml"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /app/config/webmail.toml
|
||||||
|
subPath: webmail.toml
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: "${var.instance}-webmail"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "webmail_config" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-webmail"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
data:
|
||||||
|
webmail.toml: |-
|
||||||
|
name="Wild Duck Mail"
|
||||||
|
|
||||||
|
title="wildduck-www"
|
||||||
|
|
||||||
|
[service]
|
||||||
|
# email domain for new users
|
||||||
|
domain="${var.domain-name}"
|
||||||
|
# default quotas for new users
|
||||||
|
quota=1024
|
||||||
|
recipients=2000
|
||||||
|
forwards=2000
|
||||||
|
identities=10
|
||||||
|
allowIdentityEdit=true
|
||||||
|
allowJoin=true
|
||||||
|
enableSpecial=false # if true the allow creating addresses with special usernames
|
||||||
|
# allowed domains for new addresses
|
||||||
|
domains=["${var.domain-name}"]
|
||||||
|
|
||||||
|
generalNotification="" # static notification to show on top of the page
|
||||||
|
|
||||||
|
[service.sso.http]
|
||||||
|
enabled = false
|
||||||
|
header = "X-UserName" # value from this header is treated as logged in username
|
||||||
|
authRedirect = "http:/127.0.0.1:3000/login" # URL to redirect non-authenticated users
|
||||||
|
logoutRedirect = "http:/127.0.0.1:3000/logout" # URL to redirect when user clicks on "log out"
|
||||||
|
|
||||||
|
[api]
|
||||||
|
url="http://wildduck.vynil-mail.svc.cluster.local:80"
|
||||||
|
accessToken="wildduck1234"
|
||||||
|
|
||||||
|
[dbs]
|
||||||
|
# mongodb connection string for the main database
|
||||||
|
mongo="mongodb://${var.component}:${local.mongo-password}@${var.instance}-${var.component}-mongo-svc.${var.namespace}.svc:27017/wildduck-webmail"
|
||||||
|
|
||||||
|
# redis connection string for Express sessions
|
||||||
|
redis="redis://${var.instance}-${var.component}-redis.${var.namespace}.svc:6379/5"
|
||||||
|
|
||||||
|
[www]
|
||||||
|
host=false
|
||||||
|
port=80
|
||||||
|
proxy=false
|
||||||
|
postsize="5MB"
|
||||||
|
log="dev"
|
||||||
|
secret="${local.secrets.webmail}"
|
||||||
|
secure=false
|
||||||
|
listSize=20
|
||||||
|
|
||||||
|
[recaptcha]
|
||||||
|
enabled=false
|
||||||
|
siteKey=""
|
||||||
|
secretKey=""
|
||||||
|
|
||||||
|
[totp]
|
||||||
|
# Issuer name for TOTP, defaults to config.name
|
||||||
|
issuer=false
|
||||||
|
# once setup do not change as it would invalidate all existing 2fa sessions
|
||||||
|
secret="${local.secrets.totp}"
|
||||||
|
|
||||||
|
[u2f]
|
||||||
|
# set to false if not using HTTPS
|
||||||
|
enabled=true
|
||||||
|
# must be https url or use default
|
||||||
|
appId="https://${var.domain-name}"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
level="silly"
|
||||||
|
mail=true
|
||||||
|
|
||||||
|
[setup]
|
||||||
|
# these values are shown in the configuration help page
|
||||||
|
[setup.imap]
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
port=143
|
||||||
|
[setup.pop3]
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
port=110
|
||||||
|
[setup.smtp]
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
port=25
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "webmail_service" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-webmail"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.webmail-labels)}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector: ${jsonencode(local.webmail-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
402
share/wildduck/wildduck.tf
Normal file
402
share/wildduck/wildduck.tf
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
locals {
|
||||||
|
wildduck-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "wildduck"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "wildduck_deploy" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-wildduck"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: wildduck
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
image: "${var.images.wildduck.registry}/${var.images.wildduck.repository}:${var.images.wildduck.tag}"
|
||||||
|
imagePullPolicy: "${var.images.wildduck.pullPolicy}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8000
|
||||||
|
protocol: TCP
|
||||||
|
- name: imap
|
||||||
|
containerPort: 1430
|
||||||
|
protocol: TCP
|
||||||
|
- name: pop3
|
||||||
|
containerPort: 1100
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /users
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
httpHeaders:
|
||||||
|
- name: X-Access-Token
|
||||||
|
value: wildduck1234
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /users
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
httpHeaders:
|
||||||
|
- name: X-Access-Token
|
||||||
|
value: wildduck1234
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: wildduck-config-volume
|
||||||
|
mountPath: /wildduck/config
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: "${var.instance}-wildduck"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "wildduck_config" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-wildduck"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
data:
|
||||||
|
default.toml: |-
|
||||||
|
# Uncomment if you start the app as root and want to downgrade
|
||||||
|
# once all privileged actions are completed
|
||||||
|
# If you do not use privileged ports then you can start the app already under required user account
|
||||||
|
#user="wildduck"
|
||||||
|
#group="wildduck"
|
||||||
|
# process title
|
||||||
|
ident="wildduck"
|
||||||
|
# how many processes to start
|
||||||
|
processes=1
|
||||||
|
# default quota storage in MB (can be overriden per user)
|
||||||
|
maxStorage=1024
|
||||||
|
# default smtp recipients for 24h (can be overriden per user)
|
||||||
|
maxRecipients=2000
|
||||||
|
# default forwarded messages for 24h (can be overriden per user)
|
||||||
|
maxForwards=2000
|
||||||
|
# If usernames are not email addresses then use this domain as hostname part
|
||||||
|
#emailDomain="mydomain.info"
|
||||||
|
[dbs]
|
||||||
|
# @include "dbs.toml"
|
||||||
|
[totp]
|
||||||
|
# If enabled then encrypt TOTP seed tokens with the secret password. By default TOTP seeds
|
||||||
|
# are not encrypted and stored as cleartext. Once set up do not change these values,
|
||||||
|
# otherwise decrypting totp seeds is going to fail
|
||||||
|
cipher="aes192"
|
||||||
|
secret="${local.secrets.totp}"
|
||||||
|
[u2f]
|
||||||
|
# Fully qualified URL of your website (must use HTTPS!)
|
||||||
|
appId="https://localhost:3000"
|
||||||
|
[attachments]
|
||||||
|
# @include "attachments.toml"
|
||||||
|
[log]
|
||||||
|
level="debug"
|
||||||
|
skipFetchLog=false # if true, then does not output individual * FETCH responses to log
|
||||||
|
# delete authentication log entries after 30 days
|
||||||
|
# changing this value only affects new entries
|
||||||
|
# set to false to not log authentication events
|
||||||
|
# set to 0 to keep the logs infinitely
|
||||||
|
authlogExpireDays=30
|
||||||
|
[log.gelf]
|
||||||
|
enabled=false
|
||||||
|
hostname=false # defaults to os.hostname()
|
||||||
|
component="wildduck"
|
||||||
|
[log.gelf.options]
|
||||||
|
graylogPort=12201
|
||||||
|
graylogHostname="127.0.0.1"
|
||||||
|
connection="lan"
|
||||||
|
[imap]
|
||||||
|
# @include "imap.toml"
|
||||||
|
[tls]
|
||||||
|
# @include "tls.toml"
|
||||||
|
[lmtp]
|
||||||
|
# @include "lmtp.toml"
|
||||||
|
[pop3]
|
||||||
|
# @include "pop3.toml"
|
||||||
|
[api]
|
||||||
|
# @include "api.toml"
|
||||||
|
[sender]
|
||||||
|
# @include "sender.toml"
|
||||||
|
[dkim]
|
||||||
|
# @include "dkim.toml"
|
||||||
|
[acme]
|
||||||
|
# @include "acme.toml"
|
||||||
|
[plugins]
|
||||||
|
# @include "plugins/*.toml"
|
||||||
|
[tasks]
|
||||||
|
# if enabled then process jobs like deleting expired messages etc
|
||||||
|
enabled=true
|
||||||
|
[smtp.setup]
|
||||||
|
# Public configuration for SMTP MDA, needed for mobileconfig files
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
port=465
|
||||||
|
[webhooks]
|
||||||
|
# At least one server must have webhook processing enabled,
|
||||||
|
# otherwise events would pile up in the Redis queue.
|
||||||
|
enabled = true
|
||||||
|
api.toml: |-
|
||||||
|
enabled=true
|
||||||
|
port=8000
|
||||||
|
# by default bind to localhost only
|
||||||
|
host="0.0.0.0"
|
||||||
|
# Use `true` (HTTPS) for port 443 and `false` (HTTP) for 80
|
||||||
|
secure=false
|
||||||
|
# If set requires all API calls to have accessToken query argument with that value
|
||||||
|
# http://localhost:8080/users?accessToken=somesecretvalue
|
||||||
|
accessToken="wildduck1234"
|
||||||
|
[accessControl]
|
||||||
|
# If true then require a valid access token to perform API calls
|
||||||
|
# If a client provides a token then it is validated even if using a token is not required
|
||||||
|
enabled=false
|
||||||
|
# Secret for HMAC
|
||||||
|
# Changing this value invalidates all tokens
|
||||||
|
secret="a secret cat"
|
||||||
|
# Generated access token TTL in seconds. Token TTL gets extended by this value every time the token is used. Defaults to 14 days
|
||||||
|
#tokenTTL=1209600
|
||||||
|
# Generated access token max lifetime in seconds. Defaults to 180 days
|
||||||
|
#tokenLifetime=15552000
|
||||||
|
[roles]
|
||||||
|
# @include "roles.json"
|
||||||
|
[tls]
|
||||||
|
# If certificate path is not defined, use global or built-in self-signed certs
|
||||||
|
#key="/path/to/server/key.pem"
|
||||||
|
#cert="/path/to/server/cert.pem"
|
||||||
|
[mobileconfig]
|
||||||
|
# plist configuration for OSX/iOS profile files that are generated with Application Specific Passwords
|
||||||
|
# Use {email} in the description strings to replace it with account email address
|
||||||
|
# A reverse-DNS style identifier (com.example.myprofile, for example) that identifies the profile.
|
||||||
|
# This string is used to determine whether a new profile should replace an existing one or should be added. Username is prepended to this value.
|
||||||
|
identifier="com.email.wildduck"
|
||||||
|
# A human-readable name for the profile. This value is displayed on the Detail screen. It does not have to be unique.
|
||||||
|
displayName="WildDuck Mail"
|
||||||
|
# A human-readable string containing the name of the organization that provided the profile.
|
||||||
|
organization="WildDuck Mail Services"
|
||||||
|
# A description of the profile, shown on the Detail screen for the profile. This should be descriptive enough to help the user decide whether to install the profile.
|
||||||
|
displayDescription="Install this profile to setup {email}"
|
||||||
|
# A user-visible description of the email account, shown in the Mail and Settings applications.
|
||||||
|
accountDescription="WildDuck ({email})"
|
||||||
|
[mobileconfig.tls]
|
||||||
|
# If certificate path is not defined, use global or built-in self-signed certs
|
||||||
|
#key="/path/to/server/key.pem"
|
||||||
|
#cert="/path/to/server/cert.pem"
|
||||||
|
[cors]
|
||||||
|
origins = ["*"]
|
||||||
|
dbs.toml: |-
|
||||||
|
# mongodb connection string for the main database
|
||||||
|
mongo="mongodb://${var.component}:${local.mongo-password}@${var.instance}-${var.component}-mongo-svc.${var.namespace}.svc:27017/wildduck"
|
||||||
|
# redis connection string to connect to a single master (see below for Sentinel example)
|
||||||
|
redis="redis://${var.instance}-${var.component}-redis.${var.namespace}.svc:6379/3"
|
||||||
|
# WildDuck allows using different kind of data in different databases
|
||||||
|
# If you do not provide a database config value, then main database connection
|
||||||
|
# is used for everything
|
||||||
|
# You can either use a database name (uses shared connection) or a configutaion
|
||||||
|
# url (creates a separate connection) for each databases
|
||||||
|
|
||||||
|
# Optional database name or connection url for GridFS if you do not want to
|
||||||
|
# use the main db for storing attachments. Useful if you want
|
||||||
|
# to use a different mount folder or storage engine
|
||||||
|
#gridfs="wildduck"
|
||||||
|
|
||||||
|
# Optional database name or connection url for users collection if you do not want to
|
||||||
|
# use the main db for storing user/address data. Useful if you want
|
||||||
|
# to use a different mount folder or storage engine
|
||||||
|
#users="wildduck"
|
||||||
|
|
||||||
|
# Optional database name or connection url for ZoneMTA queue database. This is
|
||||||
|
# used to push outbound emails to the sending queue
|
||||||
|
sender="zone-mta"
|
||||||
|
|
||||||
|
#queued="mail"
|
||||||
|
dkim.toml: |-
|
||||||
|
# If enabled then encrypt DKIM keys with the secret password. By default DKIM keys
|
||||||
|
# are not encrypted and stored as cleartext. Once set up do not change these values,
|
||||||
|
# otherwise decrypting DKIM keys is going to fail
|
||||||
|
cipher="aes192"
|
||||||
|
secret="${local.secrets.dkim}"
|
||||||
|
# If true then spwans openssl command line executable for generating DKIM keys
|
||||||
|
# Otherwise forge library is used which is cross-environment but slower
|
||||||
|
useOpenSSL=true
|
||||||
|
# Define path to openssl if not in default path
|
||||||
|
#pathOpenSSL="/usr/local/bin/openssl"
|
||||||
|
# If true then also adds a signature for the outbound domain
|
||||||
|
# Affects WildDuck ZoneMTA plugin only
|
||||||
|
signTransportDomain=false
|
||||||
|
# do not change this
|
||||||
|
hashAlgo="sha256"
|
||||||
|
imap.toml: |-
|
||||||
|
# If enabled then WildDuck exposes an IMAP interface for listing and fetching emails
|
||||||
|
enabled=true
|
||||||
|
port=1430
|
||||||
|
host="0.0.0.0"
|
||||||
|
# Use `true` for port 993 and `false` for 143. If connection is not secured
|
||||||
|
# on connection then WildDuck enables STARTTLS extension
|
||||||
|
secure=false
|
||||||
|
# Max size for messages uploaded via APPEND
|
||||||
|
maxMB=25
|
||||||
|
# delete messages from \Trash and \Junk after retention days
|
||||||
|
retention=30
|
||||||
|
# Default max donwload bandwith per day in megabytes
|
||||||
|
maxDownloadMB=10000
|
||||||
|
# Default max upload bandwith per day in megabytes
|
||||||
|
maxUploadMB=10000
|
||||||
|
# Default max concurrent connections per service per client
|
||||||
|
maxConnections=15
|
||||||
|
# if `true` then do not autodelete expired messages
|
||||||
|
disableRetention=false
|
||||||
|
# If true, then disables STARTTLS support
|
||||||
|
disableSTARTTLS=true
|
||||||
|
# If true, then advertises COMPRESS=DEFLATE capability
|
||||||
|
enableCompression=false
|
||||||
|
# If true, then expect HAProxy PROXY header as the first line of data
|
||||||
|
useProxy=false
|
||||||
|
# useProxy=true # expect PROXY from all conections
|
||||||
|
# useProxy=['*'] # expect PROXY from all conections
|
||||||
|
# useProxy=['1.2.3.4', '1.2.3.5'] # expect PROXY only from connections from listed IP addresses
|
||||||
|
# an array of IP addresses to ignore (not logged)
|
||||||
|
ignoredHosts=[]
|
||||||
|
#name="WildDuck IMAP"
|
||||||
|
#version="1.0.0"
|
||||||
|
#vendor="WildDuck"
|
||||||
|
# Add extra IMAP interfaces
|
||||||
|
#[[interface]]
|
||||||
|
#enabled=true
|
||||||
|
#port=9143
|
||||||
|
#host="0.0.0.0"
|
||||||
|
#secure=false
|
||||||
|
#ignoreSTARTTLS=true
|
||||||
|
# If true then EXPUNGE is called after a message gets a \Deleted flag set
|
||||||
|
autoExpunge=true
|
||||||
|
[setup]
|
||||||
|
# Public configuration for IMAP
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
# port defaults to imap.port
|
||||||
|
port=9930
|
||||||
|
[tls]
|
||||||
|
## If certificate path is not defined, use global or built-in self-signed certs
|
||||||
|
#key="/path/to/server/key.pem"
|
||||||
|
#cert="/path/to/server/cert.pem"
|
||||||
|
## You can also define extra options for specific TLS settings:
|
||||||
|
#ciphers="ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"
|
||||||
|
#secureProtocol="SSLv23_server_method"
|
||||||
|
## constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_TLSv1 => 100663296
|
||||||
|
#secureOptions=100663296
|
||||||
|
#[[interface]]
|
||||||
|
#enabled=true
|
||||||
|
#port=9143
|
||||||
|
#host="0.0.0.0"
|
||||||
|
#secure=false
|
||||||
|
#ignoreSTARTTLS=false
|
||||||
|
pop3.toml: |-
|
||||||
|
# If enabled then WildDuck exposes a limited POP3 interface for listing and fetching emails
|
||||||
|
enabled=true
|
||||||
|
port=1100
|
||||||
|
# by default bind to localhost only
|
||||||
|
host="0.0.0.0"
|
||||||
|
# If true, then disables STARTTLS support
|
||||||
|
disableSTARTTLS=true
|
||||||
|
# Use `true` for port 995 and `false` for 110
|
||||||
|
secure=false
|
||||||
|
# If true, then do not show server info in CAPA response
|
||||||
|
disableVersionString=false
|
||||||
|
# How many latest messages to list for LIST and UIDL
|
||||||
|
# POP3 server never lists all messages but only a limited length list
|
||||||
|
maxMessages=250
|
||||||
|
# Max donwload bandwith per day in megabytes
|
||||||
|
maxDownloadMB=10000
|
||||||
|
# If true, then expect HAProxy PROXY header as the first line of data
|
||||||
|
useProxy=false
|
||||||
|
# an array of IP addresses to ignore (not logged)
|
||||||
|
ignoredHosts=[]
|
||||||
|
#name="WildDuck POP3"
|
||||||
|
#version="1.0.0"
|
||||||
|
[tls]
|
||||||
|
# If certificate path is not defined, use global or built-in self-signed certs
|
||||||
|
#key="/path/to/server/key.pem"
|
||||||
|
#cert="/path/to/server/cert.pem"
|
||||||
|
[setup]
|
||||||
|
# Public configuration for POP3
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
secure=true
|
||||||
|
# port defaults to pop3.port
|
||||||
|
port=995
|
||||||
|
sender.toml: |-
|
||||||
|
# which ZoneMTA queue to use by default
|
||||||
|
zone="default"
|
||||||
|
# Collection name for GridFS storage
|
||||||
|
gfs="mail"
|
||||||
|
# Collection name for the queue
|
||||||
|
# see [dbs].sender option for choosing correct database to use for ZoneMTA queues
|
||||||
|
# by default the main wildduck database is used
|
||||||
|
collection="zone-queue"
|
||||||
|
# Hashing secret for loop detection
|
||||||
|
# Must be shared with haraka-plugin-wildduck
|
||||||
|
# If not set then looping is not tracked
|
||||||
|
loopSecret="${local.secrets.srs}"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "wildduck_service_api" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-wildduck-api"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector: ${jsonencode(local.wildduck-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "wildduck_service" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-wildduck-mail"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.wildduck-labels)}
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
ports:
|
||||||
|
- port: 143
|
||||||
|
targetPort: imap
|
||||||
|
protocol: TCP
|
||||||
|
name: imap
|
||||||
|
- port: 110
|
||||||
|
targetPort: pop3
|
||||||
|
protocol: TCP
|
||||||
|
name: pop3
|
||||||
|
selector: ${jsonencode(local.wildduck-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
197
share/wildduck/zonemta.tf
Normal file
197
share/wildduck/zonemta.tf
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
locals {
|
||||||
|
zonemta-labels = merge(local.common-labels, {
|
||||||
|
"app.kubernetes.io/component" = "zonemta"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "zonemta_deploy" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-zonemta"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.zonemta-labels)}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels: ${jsonencode(local.zonemta-labels)}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: ${jsonencode(local.zonemta-labels)}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: wildduck
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
image: "${var.images.zonemta.registry}/${var.images.zonemta.repository}:${var.images.zonemta.tag}"
|
||||||
|
imagePullPolicy: "${var.images.zonemta.pullPolicy}"
|
||||||
|
ports:
|
||||||
|
- name: smtp
|
||||||
|
containerPort: 5870
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: smtp
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: smtp
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 30
|
||||||
|
resources:
|
||||||
|
{}
|
||||||
|
volumeMounts:
|
||||||
|
- name: tls
|
||||||
|
mountPath: "/var/opt/certs"
|
||||||
|
readOnly: true
|
||||||
|
- name: config
|
||||||
|
mountPath: /app/config
|
||||||
|
- name: wildduck-zonemta-interfaces-config-volume
|
||||||
|
mountPath: /app/config/interfaces
|
||||||
|
- name: wildduck-zonemta-plugins-config-volume
|
||||||
|
mountPath: /app/config/plugins
|
||||||
|
- name: wildduck-zonemta-zones-config-volume
|
||||||
|
mountPath: /app/config/zones
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: "${var.instance}-zonemta"
|
||||||
|
- name: tls
|
||||||
|
secret:
|
||||||
|
secretName: "${var.instance}-cert"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "zonemta_config" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-zonemta"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.zonemta-labels)}
|
||||||
|
data:
|
||||||
|
feeder.toml: |-
|
||||||
|
# Default SMTP interface for accepting mail for delivery
|
||||||
|
[feeder]
|
||||||
|
enabled=true
|
||||||
|
# How many worker processes to spawn
|
||||||
|
processes=1
|
||||||
|
# Maximum allowed message size 30MB
|
||||||
|
maxSize=31457280
|
||||||
|
# Local IP and port to bind to
|
||||||
|
host="0.0.0.0"
|
||||||
|
port=5870
|
||||||
|
# Set to true to require authentication
|
||||||
|
# If authentication is enabled then you need to use a plugin with an authentication hook
|
||||||
|
authentication=true
|
||||||
|
# How many recipients to allow per message
|
||||||
|
maxRecipients=1000
|
||||||
|
# Set to true to enable STARTTLS. Do not forget to change default TLS keys
|
||||||
|
starttls=true
|
||||||
|
# set to true to start in TLS mode if using port 465
|
||||||
|
# this probably does not work as TLS support with 465 in ZoneMTA is a bit buggy
|
||||||
|
secure=false
|
||||||
|
# define keys for STARTTLS/TLS. These paths are relative to CWD
|
||||||
|
# NB! Keys must be accessible by process user or SMTP authentication will fail.
|
||||||
|
key="/var/opt/certs/tls.key"
|
||||||
|
cert="/var/opt/certs/tls.crt"
|
||||||
|
dbs-production.toml: |-
|
||||||
|
# Database configuration
|
||||||
|
# this file is loaded when NODE_ENV=production
|
||||||
|
# MongoDB connection string
|
||||||
|
mongo="mongodb://${var.component}:${local.mongo-password}@${var.instance}-${var.component}-mongo-svc.${var.namespace}.svc:27017/wildduck"
|
||||||
|
# Redis connection string
|
||||||
|
redis="redis://${var.instance}-${var.component}-redis.${var.namespace}.svc:6379/2"
|
||||||
|
# Database name for ZoneMTA data in MongoDB. In most cases it should be the same as in the connection string
|
||||||
|
sender="wildduck"
|
||||||
|
# Database name for Wild Duck users
|
||||||
|
# users="wildduck"
|
||||||
|
# Database name for Wild Duck attachments
|
||||||
|
# gridfs="wildduck"
|
||||||
|
pools.toml: |-
|
||||||
|
# List local IP addresses that can be used for outbound tcp connections
|
||||||
|
# Server process must be able to locally bind to these addresses
|
||||||
|
[[default]]
|
||||||
|
address="0.0.0.0"
|
||||||
|
name="${var.sub-domain}.${var.domain-name}"
|
||||||
|
#
|
||||||
|
#[[default]]
|
||||||
|
#address="1.2.3.5"
|
||||||
|
#name="ip-2.hostname"
|
||||||
|
loop-breaker.toml: |-
|
||||||
|
["modules/zonemta-loop-breaker"]
|
||||||
|
enabled="sender"
|
||||||
|
secret="${local.secrets.zonemta}"
|
||||||
|
algo="md5"
|
||||||
|
wildduck.toml: |-
|
||||||
|
["modules/zonemta-wildduck"]
|
||||||
|
enabled=["receiver", "sender"]
|
||||||
|
# to which SMTP interfaces this plugin applies to. Use "*" for all interfaces
|
||||||
|
interfaces=["feeder"]
|
||||||
|
# optional hostname to be used in headers
|
||||||
|
# defaults to os.hostname()
|
||||||
|
hostname="${var.sub-domain}.${var.domain-name}"
|
||||||
|
# How long to keep auth records in log
|
||||||
|
authlogExpireDays=30
|
||||||
|
# default smtp recipients for 24h (can be overriden per user)
|
||||||
|
maxRecipients=2000
|
||||||
|
disableUploads=false # if true then messages are not uploaded to Sent Mail folder
|
||||||
|
uploadAll=false # if false then messages from Outlook are not uploaded to Sent Mail folder
|
||||||
|
# SRS settings for forwarded emails
|
||||||
|
# ---------------------------------
|
||||||
|
["modules/zonemta-wildduck".srs]
|
||||||
|
# Handle rewriting of forwarded emails. If false then SRS is not used
|
||||||
|
# Only affect messages that have interface set to "forwarder"
|
||||||
|
enabled=true
|
||||||
|
# SRS secret value. Must be the same as in the MX side
|
||||||
|
secret="${local.secrets.srs}"
|
||||||
|
# SRS domain, must resolve back to MX
|
||||||
|
rewriteDomain="${var.domain-name}"
|
||||||
|
# DKIM Settings
|
||||||
|
# -------------
|
||||||
|
["modules/zonemta-wildduck".dkim]
|
||||||
|
# If true then also adds a signature for the outbound domain
|
||||||
|
signTransportDomain=false
|
||||||
|
# If set then decrypt encrypted DKIM keys using this password
|
||||||
|
#secret="a secret cat"
|
||||||
|
# Cipher to use to decrypt encrypted DKIM keys
|
||||||
|
#cipher="aes192"
|
||||||
|
["modules/zonemta-wildduck".gelf]
|
||||||
|
enabled=false
|
||||||
|
component="mta"
|
||||||
|
["modules/zonemta-wildduck".gelf.options]
|
||||||
|
graylogPort=12201
|
||||||
|
graylogHostname='127.0.0.1'
|
||||||
|
connection='lan'
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubectl_manifest" "zonemta_service" {
|
||||||
|
yaml_body = <<-EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: "${var.instance}-zonemta"
|
||||||
|
namespace: "${var.namespace}"
|
||||||
|
labels: ${jsonencode(local.zonemta-labels)}
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
ports:
|
||||||
|
- port: 587
|
||||||
|
targetPort: smtp
|
||||||
|
protocol: TCP
|
||||||
|
name: smtp
|
||||||
|
selector: ${jsonencode(local.zonemta-labels)}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user