resource "kubernetes_secret" "mail_crypt_certs" { metadata { name = "mail-crypt-certs" namespace = kubernetes_namespace.mail.metadata[0].name } data = { "ecprivkey.pem" = var.mail_crypt_private_key "ecpubkey.pem" = var.mail_crypt_public_key } type = "Opaque" } resource "kubernetes_secret" "dovecot_users" { metadata { name = "dovecot-users" namespace = kubernetes_namespace.mail.metadata[0].name } data = { "users" = local.dovecot_users } } resource "kubernetes_config_map" "dovecot_config" { metadata { name = "dovecot-config" namespace = kubernetes_namespace.mail.metadata[0].name } data = { "dovecot.conf" = local.dovecot_config } } resource "kubernetes_config_map" "dovecot_sieve" { metadata { name = "dovecot-sieve" namespace = kubernetes_namespace.mail.metadata[0].name } data = { "sieve" = local.dovecot_sieve } } resource "kubernetes_deployment" "dovecot" { metadata { namespace = kubernetes_namespace.mail.metadata[0].name name = "dovecot" labels = { app = "dovecot" } } spec { replicas = 1 selector { match_labels = { app = "dovecot" } } strategy { type = var.dovecot_use_host_networking ? "Recreate" : "RollingUpdate" } template { metadata { labels = { app = "dovecot" } annotations = { "checksum/dovecot" = local.dovecot_config_checksum "checksum/sieve" = local.dovecot_sieve_checksum "checksum/stunnel" = local.dovecot_stunnel_config_checksum # Commented out to avoid unnecessary restarts # "checksum/users" = local.dovecot_users_checksum } } spec { service_account_name = kubernetes_service_account.mail_app.metadata[0].name container { name = "dovecot" image = "dovecot/dovecot:${var.dovecot_tag}" port { container_port = 31993 host_port = var.dovecot_use_host_networking ? 993 : null } port { name = "lmtp" container_port = 31024 } volume_mount { name = "email-storage" mount_path = "/var/mail" } volume_mount { name = "users" mount_path = "/etc/dovecot/users" sub_path = "users" read_only = true } volume_mount { name = "dovecot-config" mount_path = "/etc/dovecot/dovecot.conf" sub_path = "dovecot.conf" read_only = true } volume_mount { name = "dovecot-sieve" mount_path = "/etc/dovecot/sieve/default.sieve" sub_path = "sieve" read_only = true } volume_mount { name = "certs" mount_path = "/etc/letsencrypt" read_only = true } volume_mount { name = "mail-crypt-certs" mount_path = "/etc/mail-crypt" read_only = true } volume_mount { name = "dovecot-logs" mount_path = "/var/log/dovecot" read_only = false } volume_mount { name = "tmp" mount_path = "/tmp" } volume_mount { name = "dovecot-run" mount_path = "/var/run/dovecot" } } container { name = "stunnel" image = "chainguard/stunnel:${local.stunnel_tag}" args = ["/etc/conf/stunnel.conf"] volume_mount { name = "stunnel-config" mount_path = "/etc/conf" read_only = true } volume_mount { name = "stunnel-certs" mount_path = "/etc/ssl/certs/private" read_only = true } port { name = "auth" container_port = 31000 } } volume { name = "email-storage" host_path { path = local.mailboxes_path } } volume { name = "users" secret { secret_name = kubernetes_secret.dovecot_users.metadata[0].name } } volume { name = "dovecot-config" config_map { name = kubernetes_config_map.dovecot_config.metadata[0].name } } volume { name = "certs" secret { secret_name = "mail-tls" } } volume { name = "dovecot-sieve" config_map { name = kubernetes_config_map.dovecot_sieve.metadata[0].name } } volume { name = "mail-crypt-certs" secret { secret_name = kubernetes_secret.mail_crypt_certs.metadata[0].name } } volume { name = "stunnel-config" config_map { name = kubernetes_config_map.stunnel_dovecot.metadata[0].name } } volume { name = "stunnel-certs" secret { secret_name = kubernetes_manifest.stunnel_cert.manifest["metadata"]["name"] items { key = "tls.crt" path = "tls.crt" } items { key = "tls.key" path = "tls.key" } } } volume { name = "dovecot-logs" host_path { path = "/var/log/dovecot" } } volume { name = "tmp" empty_dir {} } volume { name = "dovecot-run" empty_dir {} } } } } depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app] lifecycle { ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]] } } resource "kubernetes_service" "dovecot" { metadata { namespace = kubernetes_namespace.mail.metadata[0].name name = "imap" } spec { selector = { app = "dovecot" } port { name = "imap" port = 993 target_port = 31993 } type = "ClusterIP" } lifecycle { ignore_changes = [ metadata[0].annotations ] } } resource "kubernetes_service" "dovecot_lmtp" { metadata { name = "lmtp" namespace = kubernetes_namespace.mail.metadata[0].name } spec { selector = { app = "dovecot" } port { name = "lmtp" port = 31024 target_port = 31024 } type = "ClusterIP" } } resource "kubernetes_service" "dovecot_auth" { metadata { name = "auth" namespace = kubernetes_namespace.mail.metadata[0].name } spec { selector = { app = "dovecot" } port { name = "auth" port = 31000 target_port = 31000 } type = "ClusterIP" } }