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: "${local.secrets.access}" readinessProbe: httpGet: path: /users port: http scheme: HTTP httpHeaders: - name: X-Access-Token value: "${local.secrets.access}" resources: {} volumeMounts: - name: tls mountPath: "/var/opt/certs" readOnly: true - name: configmap mountPath: /wildduck/config/default.toml subPath: default.toml - name: configmap mountPath: /wildduck/config/api.toml subPath: api.toml - name: configmap mountPath: /wildduck/config/dbs.toml subPath: dbs.toml - name: configmap mountPath: /wildduck/config/dkim.toml subPath: dkim.toml - name: configmap mountPath: /wildduck/config/imap.toml subPath: imap.toml - name: configmap mountPath: /wildduck/config/pop3.toml subPath: pop3.toml - name: configmap mountPath: /wildduck/config/sender.toml subPath: sender.toml volumes: - name: configmap configMap: name: "${var.instance}-wildduck" - name: tls secret: secretName: "${var.instance}-cert" EOF } resource "kubernetes_config_map_v1" "wildduck_config" { metadata { name = "${var.instance}-wildduck" namespace = "${var.namespace}" labels = local.wildduck-labels } data = yamldecode(<<-EOF 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 accessToken="${local.secrets.access}" [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/${var.component}" # 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="${var.component}" #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=false # 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="/var/opt/certs/tls.key" cert="/var/opt/certs/tls.crt" ## 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="/var/opt/certs/tls.key" cert="/var/opt/certs/tls.crt" [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 }