# Install nginx-ingress-controller via Helm resource "helm_release" "nginx_ingress" { count = var.ingress_enabled ? 1 : 0 name = "ingress-nginx" repository = "https://kubernetes.github.io/ingress-nginx" chart = "ingress-nginx" version = "4.11.3" namespace = "ingress-nginx" create_namespace = true set { name = "controller.service.type" value = "LoadBalancer" } set { name = "controller.service.annotations.service\\.beta\\.kubernetes\\.io/azure-load-balancer-health-probe-request-path" value = "/healthz" } set { name = "controller.metrics.enabled" value = "true" } set { name = "controller.podAnnotations.prometheus\\.io/scrape" value = "true" } set { name = "controller.podAnnotations.prometheus\\.io/port" value = "10254" } # Resource limits set { name = "controller.resources.requests.cpu" value = "100m" } set { name = "controller.resources.requests.memory" value = "128Mi" } set { name = "controller.resources.limits.cpu" value = "500m" } set { name = "controller.resources.limits.memory" value = "512Mi" } # Enable rate limiting set { name = "controller.config.limit-req-status-code" value = "429" } timeout = 600 } # Wait for nginx-ingress to be ready and get LoadBalancer IP data "kubernetes_service" "ingress_nginx" { count = var.ingress_enabled ? 1 : 0 metadata { name = "ingress-nginx-controller" namespace = "ingress-nginx" } depends_on = [ helm_release.nginx_ingress ] } # Install cert-manager for SSL/TLS (optional) resource "helm_release" "cert_manager" { count = var.ssl_enabled ? 1 : 0 name = "cert-manager" repository = "https://charts.jetstack.io" chart = "cert-manager" version = "v1.16.2" namespace = "cert-manager" create_namespace = true set { name = "crds.enabled" value = "true" } set { name = "global.leaderElection.namespace" value = "cert-manager" } timeout = 600 } # ClusterIssuer for Let's Encrypt (production) resource "kubernetes_manifest" "letsencrypt_prod" { count = var.ssl_enabled && var.ssl_issuer_email != "" ? 1 : 0 manifest = { apiVersion = "cert-manager.io/v1" kind = "ClusterIssuer" metadata = { name = "letsencrypt-prod" } spec = { acme = { server = "https://acme-v02.api.letsencrypt.org/directory" email = var.ssl_issuer_email privateKeySecretRef = { name = "letsencrypt-prod" } solvers = [ { http01 = { ingress = { class = "nginx" } } } ] } } } depends_on = [ helm_release.cert_manager ] } # ClusterIssuer for Let's Encrypt (staging) - for testing resource "kubernetes_manifest" "letsencrypt_staging" { count = var.ssl_enabled && var.ssl_issuer_email != "" ? 1 : 0 manifest = { apiVersion = "cert-manager.io/v1" kind = "ClusterIssuer" metadata = { name = "letsencrypt-staging" } spec = { acme = { server = "https://acme-staging-v02.api.letsencrypt.org/directory" email = var.ssl_issuer_email privateKeySecretRef = { name = "letsencrypt-staging" } solvers = [ { http01 = { ingress = { class = "nginx" } } } ] } } } depends_on = [ helm_release.cert_manager ] } # Kubernetes Ingress for Laravel Application resource "kubernetes_ingress_v1" "app" { count = var.ingress_enabled ? 1 : 0 metadata { name = "${var.app_name}-ingress" namespace = kubernetes_namespace.app.metadata[0].name labels = local.common_labels annotations = merge( { "kubernetes.io/ingress.class" = "nginx" "nginx.ingress.kubernetes.io/rewrite-target" = "/" "nginx.ingress.kubernetes.io/ssl-redirect" = var.ssl_enabled ? "true" : "false" }, var.ssl_enabled && var.ingress_host != "" ? { "cert-manager.io/cluster-issuer" = "letsencrypt-prod" } : {} ) } spec { dynamic "tls" { for_each = var.ssl_enabled && var.ingress_host != "" ? [1] : [] content { hosts = [var.ingress_host] secret_name = "${var.app_name}-tls" } } rule { host = var.ingress_host != "" ? var.ingress_host : null http { path { path = "/" path_type = "Prefix" backend { service { name = kubernetes_service.app.metadata[0].name port { number = 80 } } } } } } } depends_on = [ helm_release.nginx_ingress, kubernetes_service.app ] }