resource "kubernetes_namespace" "stunnel" { metadata { name = "stunnel" annotations = { name = "stunnel" } labels = { name = "stunnel" } } } resource "kubernetes_service_account" "stunnel_service_account" { metadata { name = "stunnel-app-sa" namespace = kubernetes_namespace.stunnel.metadata[0].name } automount_service_account_token = false } resource "kubernetes_config_map" "wireguard_config" { count = local.wireguard_config != "null" ? 1 : 0 metadata { name = "wireguard-config" namespace = kubernetes_namespace.stunnel.metadata[0].name } data = { "wireguard.conf" = local.wireguard_config } } resource "kubernetes_config_map" "stunnel_config" { metadata { name = "stunnel-config" namespace = kubernetes_namespace.stunnel.metadata[0].name } data = { "stunnel.conf" = local.stunnel_config } } resource "kubernetes_deployment" "stunnel" { metadata { name = "stunnel" namespace = kubernetes_namespace.stunnel.metadata[0].name annotations = { "security.alpha.kubernetes.io/unsafe-sysctls" = "net.ipv4.conf.all.src_valid_mark=1" } } spec { replicas = 1 selector { match_labels = { app = "stunnel" } } strategy { type = "Recreate" } template { metadata { labels = { app = "stunnel" } annotations = { "checksum/stunnel" = local.stunnel_config_checksum "checksum/wireguard" = local.wireguard_config_checksum } } spec { dynamic "container" { for_each = nonsensitive(local.wireguard_config) != "null" ? [1] : [] content { name = "wireguard" image = "linuxserver/wireguard:${local.wireguard_version}" resources { requests = { memory = "64Mi" } } liveness_probe { exec { command = [ "/bin/sh", "-c", "wg show | grep -q transfer" ] } initial_delay_seconds = 90 period_seconds = 90 } security_context { privileged = true capabilities { add = ["NET_ADMIN"] } read_only_root_filesystem = true } env { name = "PUID" value = "1000" } env { name = "PGID" value = "1000" } env { name = "TZ" value = "Europe/Berlin" } volume_mount { name = "wireguard-config" mount_path = "/config/wg_confs" read_only = true } volume_mount { name = "lib-modules" mount_path = "/lib/modules" read_only = true } volume_mount { name = "wireguard-run" mount_path = "/run" } } } container { name = "stunnel" image = "chainguard/stunnel:${local.stunnel_version}" 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 } dynamic "port" { for_each = var.remote_targets content { container_port = port.value.listen_port name = substr(replace(port.key, ".", "-"), 0, 15) protocol = coalesce(upper(port.value.protocol), "TCP") } } } dynamic "volume" { for_each = nonsensitive(local.wireguard_config) != "null" ? [1] : [] content { name = "wireguard-config" config_map { name = nonsensitive(kubernetes_config_map.wireguard_config[0].metadata[0].name) } } } dynamic "volume" { for_each = nonsensitive(local.wireguard_config) != "null" ? [1] : [] content { name = "lib-modules" host_path { path = "/lib/modules" } } } dynamic "volume" { for_each = nonsensitive(local.wireguard_config) != "null" ? [1] : [] content { name = "wireguard-run" empty_dir { medium = "Memory" } } } volume { name = "stunnel-config" config_map { name = kubernetes_config_map.stunnel_config.metadata[0].name } } volume { name = "stunnel-certs" secret { secret_name = "remote-targets-cert" } } } } } lifecycle { ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]] } } resource "kubernetes_manifest" "remote_targets_cert" { manifest = { apiVersion = "cert-manager.io/v1" kind = "Certificate" metadata = { name = "remote-targets-cert" namespace = kubernetes_namespace.stunnel.metadata[0].name } spec = { secretName = "remote-targets-cert" issuerRef = { name = var.issuer_name kind = "ClusterIssuer" } commonName = "stunnel.remote_targets.internal" dnsNames = flatten([ for k, v in var.remote_targets : "${k}.stunnel.svc.cluster.local" ]) } } } resource "kubernetes_manifest" "local_targets_cert" { manifest = { apiVersion = "cert-manager.io/v1" kind = "Certificate" metadata = { name = "local-targets-cert" namespace = kubernetes_namespace.stunnel.metadata[0].name } spec = { secretName = "local-targets-cert" issuerRef = { name = var.issuer_name kind = "ClusterIssuer" } commonName = "stunnel.local_targets.internal" dnsNames = flatten([ for _, v in var.local_targets : v.target_host ]) } } } resource "kubernetes_service" "services" { for_each = var.remote_targets metadata { name = format("%s", replace(each.key, ".", "-")) namespace = kubernetes_namespace.stunnel.metadata[0].name } spec { port { name = substr(format("%s", replace(each.key, ".", "-")), 0, 15) port = each.value.listen_port target_port = substr(format("%s", replace(each.key, ".", "-")), 0, 15) } selector = { app = "stunnel" } type = "ClusterIP" } }