resource "kubernetes_namespace" "m3uproxy" { metadata { annotations = { name = "m3uproxy" } labels = { name = "m3uproxy" } name = "m3uproxy" } } resource "kubernetes_secret" "m3uproxy_admin_credentials" { metadata { name = "m3uproxy-credentials" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } data = { username = "tv_admin" password = var.admin_password } type = "Opaque" } resource "kubernetes_service_account" "m3uproxy_service_account" { metadata { name = "m3uproxy-app-sa" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } automount_service_account_token = false } resource "kubernetes_secret" "m3uproxy_config" { metadata { name = "m3uproxy-config" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } data = { "m3uproxy.json" = local.m3uproxy_config } type = "Opaque" } resource "kubernetes_config_map" "m3uproxy_playlist" { metadata { name = "m3uproxy-playlist" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } data = { "playlist.m3u8" = local.m3uproxy_playlist } } resource "kubernetes_deployment" "m3uproxy" { metadata { name = "m3uproxy" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } spec { replicas = 1 selector { match_labels = { app = "m3uproxy" } } strategy { type = "RollingUpdate" } template { metadata { labels = { app = "m3uproxy" } annotations = { "checksum/m3uproxy" = local.m3uproxy_config_checksum "checksum/playlist" = local.m3uproxy_playlist_checksum } } spec { service_account_name = kubernetes_service_account.m3uproxy_service_account.metadata[0].name container { name = "m3uproxy" image = "a13labs/m3uproxy:${local.m3uproxy_version}" image_pull_policy = "Always" resources { requests = { memory = "256Mi" } } port { container_port = 8080 name = "http" } readiness_probe { http_get { path = "/health" port = "http" } initial_delay_seconds = 5 period_seconds = 10 failure_threshold = 10 } env { name = "USERNAME" value_from { secret_key_ref { name = kubernetes_secret.m3uproxy_admin_credentials.metadata[0].name key = "username" } } } env { name = "PASSWORD" value_from { secret_key_ref { name = kubernetes_secret.m3uproxy_admin_credentials.metadata[0].name key = "password" } } } security_context { allow_privilege_escalation = false run_as_user = 1000 run_as_group = 1000 } volume_mount { name = "m3uproxy-config" mount_path = "/app/conf/m3uproxy.json" sub_path = "m3uproxy.json" read_only = true } volume_mount { name = "m3uproxy-playlist" mount_path = "/app/conf/playlist.m3u8" sub_path = "playlist.m3u8" read_only = true } volume_mount { name = "m3uproxy-app-cache" mount_path = "/app/cache" } volume_mount { name = "geoip-db" mount_path = "/app/GeoIP" read_only = true } } volume { name = "m3uproxy-config" secret { secret_name = kubernetes_secret.m3uproxy_config.metadata[0].name items { key = "m3uproxy.json" path = "m3uproxy.json" } } } volume { name = "m3uproxy-playlist" config_map { name = kubernetes_config_map.m3uproxy_playlist.metadata[0].name items { key = "playlist.m3u8" path = "playlist.m3u8" } } } volume { name = "m3uproxy-app-cache" host_path { path = local.m3uproxy_cache_path } } volume { name = "geoip-db" host_path { path = local.geoip_path } } } } } lifecycle { ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]] } } resource "kubernetes_service" "m3uproxy" { metadata { name = "http" namespace = kubernetes_namespace.m3uproxy.metadata[0].name } spec { selector = { app = "m3uproxy" } port { port = 8080 target_port = "http" } cluster_ip = "None" } } resource "kubernetes_ingress_v1" "m3uproxy_ingress_http" { metadata { name = "m3uproxy-ingress" namespace = kubernetes_namespace.m3uproxy.metadata[0].name annotations = { "kubernetes.io/ingress.class" = "public" "cert-manager.io/cluster-issuer" = "letsencrypt-prod" "kubernetes.io/tls-acme" = "true" "nginx.ingress.kubernetes.io/ssl-redirect" = "true" } } spec { tls { hosts = [local.m3uproxy_fqdn] secret_name = "m3uproxy-tls" } rule { host = local.m3uproxy_fqdn http { path { backend { service { name = "http" port { number = 8080 } } } } } } } }