diff --git a/infra/tf/dns/dns.tf b/infra/tf/dns/dns.tf index 649cc3dba5..39c32ba5dd 100644 --- a/infra/tf/dns/dns.tf +++ b/infra/tf/dns/dns.tf @@ -46,6 +46,14 @@ locals { ]) } +locals { + main_record = var.ngrok_domain != null ? { type = "CNAME", value = var.ngrok_domain.api } : ( + var.deploy_method_local + ? { type = "A", value = data.terraform_remote_state.k8s_infra.outputs.traefik_external_ip } + : { type = "CNAME", value = data.terraform_remote_state.k8s_infra.outputs.traefik_external_ip } + ) +} + resource "cloudflare_record" "main" { for_each = { for record in local.records: @@ -55,8 +63,8 @@ resource "cloudflare_record" "main" { zone_id = each.value.zone_id name = each.value.name # Use local node's public IP if in local region - value = data.terraform_remote_state.k8s_infra.outputs.traefik_external_ip - type = var.deploy_method_local ? "A" : "CNAME" + value = local.main_record.value + type = local.main_record.type # TODO: Increase the unproxied TTL once we have proper floating IP support on all providers ttl = each.value.proxied ? 1 : 60 # 1 = automatic proxied = each.value.proxied diff --git a/infra/tf/dns/vars.tf b/infra/tf/dns/vars.tf index 126f421d2a..25fd85a591 100644 --- a/infra/tf/dns/vars.tf +++ b/infra/tf/dns/vars.tf @@ -41,6 +41,14 @@ variable "extra_dns" { })) } +# MARK: Ngrok +variable "ngrok_domain" { + type = object({ + api = string + }) + nullable = true +} + # MARK: Cloudflare variable "cloudflare_account_id" { type = string diff --git a/infra/tf/k8s_infra/main.tf b/infra/tf/k8s_infra/main.tf index 936025bec3..ebd62b9179 100644 --- a/infra/tf/k8s_infra/main.tf +++ b/infra/tf/k8s_infra/main.tf @@ -9,7 +9,7 @@ terraform { } locals { - entrypoints = var.tls_enabled ? { + entrypoints = var.dns_enabled ? { "web" = {} "websecure" = { tls = { diff --git a/infra/tf/k8s_infra/vars.tf b/infra/tf/k8s_infra/vars.tf index ae50b96c55..c4575c2dff 100644 --- a/infra/tf/k8s_infra/vars.tf +++ b/infra/tf/k8s_infra/vars.tf @@ -13,6 +13,10 @@ variable "public_ip" { } # MARK: DNS +variable "dns_enabled" { + type = bool +} + variable "domain_main" { type = string } @@ -34,10 +38,6 @@ variable "dns_deprecated_subdomains" { type = bool } -variable "tls_enabled" { - type = bool -} - variable "minio_port" { type = string nullable = true diff --git a/infra/tf/ngrok/main.tf b/infra/tf/ngrok/main.tf new file mode 100644 index 0000000000..2007a6519a --- /dev/null +++ b/infra/tf/ngrok/main.tf @@ -0,0 +1,72 @@ +terraform { + required_providers { + ngrok = { + source = "ngrok/ngrok" + version = "0.2.0" + } + docker = { + source = "kreuzwerker/docker" + version = "3.0.2" + } + } +} + +module "secrets" { + source = "../modules/secrets" + + keys = [ + "ngrok/api_key", + "ngrok/auth_token", + ] +} + +resource "ngrok_reserved_addr" "tunnel" { + description = "Rivet ${var.namespace} Tunnel" + region = var.ngrok_region +} + +resource "local_file" "ngrok_config_file" { + filename = "/etc/rivet/ngrok.yaml" + content = yamlencode({ + version = 2 + authtoken = module.secrets.values["ngrok/auth_token"] + tunnels = merge( + { + api = { + proto = "http" + addr = var.api_http_port + domain = var.ngrok_domain.api + } + tunnel = { + proto = "tcp" + addr = var.tunnel_port + remote_addr = ngrok_reserved_addr.tunnel.addr + } + }, + var.minio_port != null ? { + minio = { + proto = "http" + addr = var.minio_port + domain = var.ngrok_domain.minio + } + } : {} + ) + }) +} + +resource "docker_container" "ngrok" { + name = "rivet-ngrok" + image = "ngrok/ngrok:latest" + restart = "unless-stopped" + network_mode = "host" + command = [ + "start", + "--all", + "--config", + "/etc/ngrok.yaml" + ] + volumes { + container_path = "/etc/ngrok.yaml" + host_path = local_file.ngrok_config_file.filename + } +} diff --git a/infra/tf/ngrok/output.tf b/infra/tf/ngrok/output.tf new file mode 100644 index 0000000000..d9caba2312 --- /dev/null +++ b/infra/tf/ngrok/output.tf @@ -0,0 +1,3 @@ +output "tunnel_reserved_addr" { + value = ngrok_reserved_addr.tunnel.addr +} diff --git a/infra/tf/ngrok/providers.tf b/infra/tf/ngrok/providers.tf new file mode 100644 index 0000000000..33ac290f23 --- /dev/null +++ b/infra/tf/ngrok/providers.tf @@ -0,0 +1,3 @@ +provider "ngrok" { + api_key = module.secrets.values["ngrok/api_key"] +} diff --git a/infra/tf/ngrok/vars.tf b/infra/tf/ngrok/vars.tf new file mode 100644 index 0000000000..571f739ab1 --- /dev/null +++ b/infra/tf/ngrok/vars.tf @@ -0,0 +1,27 @@ +variable "namespace" { + type = string +} + +variable "ngrok_region" { + type = string + default = "us" +} + +variable "ngrok_domain" { + type = object({ + api = string + minio = string + }) +} + +variable "api_http_port" { + type = number +} + +variable "tunnel_port" { + type = number +} + +variable "minio_port" { + type = number +} diff --git a/infra/tf/tls/acme.tf b/infra/tf/tls/acme.tf index faf0eac4c6..231ac00287 100644 --- a/infra/tf/tls/acme.tf +++ b/infra/tf/tls/acme.tf @@ -1,17 +1,23 @@ # MARK: Private key resource "tls_private_key" "acme_account_key" { + count = var.dns_enabled ? 1 : 0 + algorithm = "RSA" } # MARK: Registration resource "acme_registration" "main" { - account_key_pem = tls_private_key.acme_account_key.private_key_pem + count = var.dns_enabled ? 1 : 0 + + account_key_pem = tls_private_key.acme_account_key[0].private_key_pem email_address = "letsencrypt@rivet.gg" } # MARK: Certificates resource "acme_certificate" "rivet_gg" { - account_key_pem = acme_registration.main.account_key_pem + count = var.dns_enabled ? 1 : 0 + + account_key_pem = acme_registration.main[0].account_key_pem common_name = var.domain_main subject_alternative_names = flatten([ "*.${var.domain_main}", @@ -41,7 +47,9 @@ resource "acme_certificate" "rivet_gg" { } resource "acme_certificate" "rivet_game" { - account_key_pem = acme_registration.main.account_key_pem + count = var.dns_enabled ? 1 : 0 + + account_key_pem = acme_registration.main[0].account_key_pem common_name = var.domain_cdn subject_alternative_names = ["*.${var.domain_cdn}"] @@ -63,7 +71,9 @@ resource "acme_certificate" "rivet_game" { } resource "acme_certificate" "rivet_job" { - account_key_pem = acme_registration.main.account_key_pem + count = var.dns_enabled ? 1 : 0 + + account_key_pem = acme_registration.main[0].account_key_pem common_name = var.domain_job subject_alternative_names = flatten([ # Add dedicated subdomains for each region diff --git a/infra/tf/tls/cloudflare.tf b/infra/tf/tls/cloudflare.tf index 7a12e956d2..da28b97bc0 100644 --- a/infra/tf/tls/cloudflare.tf +++ b/infra/tf/tls/cloudflare.tf @@ -43,11 +43,15 @@ locals { # MARK: Cloudflare origin cert (rivet.gg) # See https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull#zone-level--cloudflare-certificate resource "tls_private_key" "cf_origin_rivet_gg" { + count = var.dns_enabled ? 1 : 0 + algorithm = "RSA" } resource "tls_cert_request" "cf_origin_rivet_gg" { - private_key_pem = tls_private_key.cf_origin_rivet_gg.private_key_pem + count = var.dns_enabled ? 1 : 0 + + private_key_pem = tls_private_key.cf_origin_rivet_gg[0].private_key_pem subject { common_name = "" @@ -56,7 +60,9 @@ resource "tls_cert_request" "cf_origin_rivet_gg" { } resource "cloudflare_origin_ca_certificate" "rivet_gg" { - csr = tls_cert_request.cf_origin_rivet_gg.cert_request_pem + count = var.dns_enabled ? 1 : 0 + + csr = tls_cert_request.cf_origin_rivet_gg[0].cert_request_pem hostnames = ["*.${var.domain_main}", "${var.domain_main}", "*.api.${var.domain_main}", "api.${var.domain_main}"] request_type = "origin-rsa" requested_validity = 15 * 365 @@ -65,10 +71,14 @@ resource "cloudflare_origin_ca_certificate" "rivet_gg" { # Must be created in every namespace it is used in resource "kubernetes_secret" "ingress_tls_cert" { - for_each = toset(flatten([ - ["traefik", "imagor", "rivet-service"], - local.has_minio ? ["minio"] : [] - ])) + for_each = toset( + var.dns_enabled + ? flatten([ + ["traefik", "imagor", "rivet-service"], + local.has_minio ? ["minio"] : [] + ]) + : [] + ) metadata { name = "ingress-tls-cloudflare-cert" @@ -78,13 +88,13 @@ resource "kubernetes_secret" "ingress_tls_cert" { type = "kubernetes.io/tls" data = { - "tls.crt" = cloudflare_origin_ca_certificate.rivet_gg.certificate - "tls.key" = tls_private_key.cf_origin_rivet_gg.private_key_pem + "tls.crt" = cloudflare_origin_ca_certificate.rivet_gg[0].certificate + "tls.key" = tls_private_key.cf_origin_rivet_gg[0].private_key_pem } } resource "kubernetes_secret" "ingress_tls_ca_cert" { - for_each = toset(["traefik", "imagor", "rivet-service"]) + for_each = toset(var.dns_enabled ? [ "imagor", "rivet-service"] : []) metadata { name = "ingress-tls-cloudflare-ca-cert" diff --git a/infra/tf/tls/main.tf b/infra/tf/tls/main.tf index 9c752e0cf5..1da2194f14 100644 --- a/infra/tf/tls/main.tf +++ b/infra/tf/tls/main.tf @@ -19,6 +19,7 @@ terraform { module "secrets" { source = "../modules/secrets" + optional = true keys = [ "cloudflare/terraform/auth_token", diff --git a/infra/tf/tls/outputs.tf b/infra/tf/tls/outputs.tf index e0cfb7decf..f4365bac62 100644 --- a/infra/tf/tls/outputs.tf +++ b/infra/tf/tls/outputs.tf @@ -1,24 +1,24 @@ locals { - tls_cert_letsencrypt_rivet_gg = { + tls_cert_letsencrypt_rivet_gg = var.dns_enabled ? { # Build full chain by concatenating the certificate with issuer. # # See # https://registry.terraform.io/providers/vancluever/acme/latest/docs/resources/certificate#certificate_pem - cert_pem = "${acme_certificate.rivet_gg.certificate_pem}${acme_certificate.rivet_gg.issuer_pem}" - key_pem = acme_certificate.rivet_gg.private_key_pem - } + cert_pem = "${acme_certificate.rivet_gg[0].certificate_pem}${acme_certificate.rivet_gg[0].issuer_pem}" + key_pem = acme_certificate.rivet_gg[0].private_key_pem + } : null - tls_cert_letsencrypt_rivet_game = { + tls_cert_letsencrypt_rivet_game = var.dns_enabled ? { # See above - cert_pem = "${acme_certificate.rivet_game.certificate_pem}${acme_certificate.rivet_game.issuer_pem}" - key_pem = acme_certificate.rivet_game.private_key_pem - } + cert_pem = "${acme_certificate.rivet_game[0].certificate_pem}${acme_certificate.rivet_game[0].issuer_pem}" + key_pem = acme_certificate.rivet_game[0].private_key_pem + } : null - tls_cert_letsencrypt_rivet_job = { + tls_cert_letsencrypt_rivet_job = var.dns_enabled ? { # See above - cert_pem = "${acme_certificate.rivet_job.certificate_pem}${acme_certificate.rivet_job.issuer_pem}" - key_pem = acme_certificate.rivet_job.private_key_pem - } + cert_pem = "${acme_certificate.rivet_job[0].certificate_pem}${acme_certificate.rivet_job[0].issuer_pem}" + key_pem = acme_certificate.rivet_job[0].private_key_pem + } : null tls_cert_locally_signed_tunnel_server = { cert_pem = tls_locally_signed_cert.locally_signed_tunnel_server.cert_pem diff --git a/infra/tf/tls/providers.tf b/infra/tf/tls/providers.tf index 7840ea29db..a37f6f53fb 100644 --- a/infra/tf/tls/providers.tf +++ b/infra/tf/tls/providers.tf @@ -1,5 +1,6 @@ provider "cloudflare" { - api_token = module.secrets.values["cloudflare/terraform/auth_token"] + # Provide placeholder token if Cloudflare enabled + api_token = var.dns_enabled ? module.secrets.values["cloudflare/terraform/auth_token"] : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } provider "acme" { diff --git a/infra/tf/tls/vars.tf b/infra/tf/tls/vars.tf index 81e9074d52..8c8320258b 100644 --- a/infra/tf/tls/vars.tf +++ b/infra/tf/tls/vars.tf @@ -3,16 +3,23 @@ variable "namespace" { } # MARK: DNS +variable "dns_enabled" { + type = bool +} + variable "domain_main" { type = string + nullable = true } variable "domain_cdn" { type = string + nullable = true } variable "domain_job" { type = string + nullable = true } # MARK: Datacenters diff --git a/infra/tf/vector/vars.tf b/infra/tf/vector/vars.tf index 7d033488dc..cb2dd4ab7a 100644 --- a/infra/tf/vector/vars.tf +++ b/infra/tf/vector/vars.tf @@ -15,11 +15,6 @@ variable "clickhouse_port_https" { type = string } -# MARK: DNS -variable "tls_enabled" { - type = bool -} - # MARK: Services variable "services" { type = map(object({ diff --git a/lib/bolt/config/src/ns.rs b/lib/bolt/config/src/ns.rs index 678531ace2..ad284b5b32 100644 --- a/lib/bolt/config/src/ns.rs +++ b/lib/bolt/config/src/ns.rs @@ -45,6 +45,8 @@ pub struct Namespace { pub bolt: Bolt, #[serde(default)] pub better_uptime: Option, + #[serde(default)] + pub ngrok: Option, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -712,6 +714,10 @@ pub struct BetterUptime { pub company_subdomain: String, } +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +#[serde(deny_unknown_fields)] +pub struct Ngrok {} + fn default_docker_repo() -> String { "ghcr.io/rivet-gg/".to_string() } diff --git a/lib/bolt/core/src/context/project.rs b/lib/bolt/core/src/context/project.rs index 7fd3446626..3aeced35cd 100644 --- a/lib/bolt/core/src/context/project.rs +++ b/lib/bolt/core/src/context/project.rs @@ -10,7 +10,7 @@ use anyhow::*; use sha2::{Digest, Sha256}; use tokio::{fs, sync::Mutex}; -use crate::{config, context, utils::command_helper::CommandHelper}; +use crate::{config, context, dep::terraform, utils::command_helper::CommandHelper}; use super::{RunContext, ServiceContext}; @@ -710,6 +710,8 @@ impl ProjectContextData { pub fn host_api(&self) -> String { if let Some(domain_main_api) = self.domain_main_api() { domain_main_api + } else if self.ns().ngrok.is_some() { + self.ngrok_domain_api() } else if let config::ns::ClusterKind::SingleNode { public_ip, api_http_port, @@ -726,6 +728,8 @@ impl ProjectContextData { pub fn origin_api(&self) -> String { if let Some(domain_main_api) = self.domain_main_api() { format!("https://{domain_main_api}") + } else if self.ns().ngrok.is_some() { + format!("https://{}", self.ngrok_domain_api()) } else if let config::ns::ClusterKind::SingleNode { public_ip, api_http_port, @@ -740,7 +744,9 @@ impl ProjectContextData { /// Origin used to access Minio. Only applicable if Minio provider is specified. pub fn origin_minio(&self) -> String { - if let Some(domain_main) = self.domain_main() { + if self.ns().ngrok.is_some() { + format!("https://{}", self.ngrok_domain_minio()) + } else if let Some(domain_main) = self.domain_main() { format!("https://minio.{domain_main}") } else if let config::ns::ClusterKind::SingleNode { public_ip, @@ -778,8 +784,27 @@ impl ProjectContextData { }) } - pub fn tls_enabled(&self) -> bool { - self.ns().dns.is_some() + pub fn cluster_id_short(&self) -> String { + let uuid = self.ns().cluster.id.to_string(); + uuid[..8].to_string() + } + + pub fn ngrok_domain_api(&self) -> String { + format!("rivet-{}-api.ngrok.dev", self.cluster_id_short()) + } + + pub fn ngrok_domain_minio(&self) -> String { + format!("rivet-{}-minio.ngrok.dev", self.cluster_id_short()) + } + + pub async fn traefik_tunnel_external_host(self: &Arc) -> String { + if self.ns().ngrok.is_some() { + let ngrok = terraform::output::read_ngrok(self).await; + (*ngrok.tunnel_reserved_addr).clone() + } else { + let k8s_infra = terraform::output::read_k8s_infra(self).await; + format!("{}:5000", *k8s_infra.traefik_tunnel_external_ip) + } } } diff --git a/lib/bolt/core/src/context/service.rs b/lib/bolt/core/src/context/service.rs index 9f012b3fd0..3cbb46c757 100644 --- a/lib/bolt/core/src/context/service.rs +++ b/lib/bolt/core/src/context/service.rs @@ -1240,9 +1240,8 @@ impl ServiceContextData { )); } - if self.depends_on_infra() && project_ctx.tls_enabled() { + if self.depends_on_infra() { let tls = terraform::output::read_tls(&project_ctx).await; - let k8s_infra = terraform::output::read_k8s_infra(&project_ctx).await; env.push(( "TLS_CERT_LOCALLY_SIGNED_JOB_CERT_PEM".into(), @@ -1252,21 +1251,23 @@ impl ServiceContextData { "TLS_CERT_LOCALLY_SIGNED_JOB_KEY_PEM".into(), tls.tls_cert_locally_signed_job.key_pem.clone(), )); - env.push(( - "TLS_CERT_LETSENCRYPT_RIVET_JOB_CERT_PEM".into(), - tls.tls_cert_letsencrypt_rivet_job.cert_pem.clone(), - )); - env.push(( - "TLS_CERT_LETSENCRYPT_RIVET_JOB_KEY_PEM".into(), - tls.tls_cert_letsencrypt_rivet_job.key_pem.clone(), - )); + if let Some(cert) = tls.tls_cert_letsencrypt_rivet_job { + env.push(( + "TLS_CERT_LETSENCRYPT_RIVET_JOB_CERT_PEM".into(), + cert.cert_pem.clone(), + )); + env.push(( + "TLS_CERT_LETSENCRYPT_RIVET_JOB_KEY_PEM".into(), + cert.key_pem.clone(), + )); + } env.push(( "TLS_ROOT_CA_CERT_PEM".into(), (*tls.root_ca_cert_pem).clone(), )); env.push(( - "K8S_TRAEFIK_TUNNEL_EXTERNAL_IP".into(), - (*k8s_infra.traefik_tunnel_external_ip).clone(), + "TRAEFIK_TUNNEL_EXTERNAL_HOST".into(), + project_ctx.traefik_tunnel_external_host().await, )); } diff --git a/lib/bolt/core/src/dep/k8s/gen.rs b/lib/bolt/core/src/dep/k8s/gen.rs index a623530fa3..0223f73422 100644 --- a/lib/bolt/core/src/dep/k8s/gen.rs +++ b/lib/bolt/core/src/dep/k8s/gen.rs @@ -1009,7 +1009,7 @@ fn build_ingress_router( })); // Build secure router - if project_ctx.tls_enabled() { + if project_ctx.ns().dns.is_some() { specs.push(json!({ "apiVersion": "traefik.io/v1alpha1", "kind": "IngressRoute", @@ -1081,7 +1081,7 @@ fn build_ingress_router( } })); - if project_ctx.tls_enabled() { + if project_ctx.ns().dns.is_some() { specs.push(json!({ "apiVersion": "traefik.io/v1alpha1", "kind": "IngressRoute", diff --git a/lib/bolt/core/src/dep/terraform/gen.rs b/lib/bolt/core/src/dep/terraform/gen.rs index 87c33a5a45..c82dc79b30 100644 --- a/lib/bolt/core/src/dep/terraform/gen.rs +++ b/lib/bolt/core/src/dep/terraform/gen.rs @@ -199,6 +199,7 @@ async fn vars(ctx: &ProjectContext) { ); // Domains + vars.insert("dns_enabled".into(), json!(ctx.ns().dns.is_some())); vars.insert("domain_main".into(), json!(ctx.domain_main())); vars.insert("domain_cdn".into(), json!(ctx.domain_cdn())); vars.insert("domain_job".into(), json!(ctx.domain_job())); @@ -210,7 +211,6 @@ async fn vars(ctx: &ProjectContext) { .as_ref() .map_or(false, |x| x.deprecated_subdomains)), ); - vars.insert("tls_enabled".into(), json!(ctx.tls_enabled())); // Cloudflare if let Some(dns) = &config.dns { @@ -565,6 +565,17 @@ async fn vars(ctx: &ProjectContext) { // vars.insert("better_uptime".into(), json!(better_uptime.to_owned())); // } + // Ngrok + if ctx.ns().ngrok.is_some() { + vars.insert( + "ngrok_domain".into(), + json!({ + "api": ctx.ngrok_domain_api(), + "minio": ctx.ngrok_domain_minio(), + }), + ); + } + // Media presets vars.insert( "imagor_presets".into(), diff --git a/lib/bolt/core/src/dep/terraform/output.rs b/lib/bolt/core/src/dep/terraform/output.rs index 6994f13da7..4b835e72cb 100644 --- a/lib/bolt/core/src/dep/terraform/output.rs +++ b/lib/bolt/core/src/dep/terraform/output.rs @@ -22,6 +22,11 @@ pub struct Cert { pub key_pem: String, } +#[derive(Debug, Clone, Deserialize)] +pub struct Ngrok { + pub tunnel_reserved_addr: TerraformOutputValue, +} + #[derive(Debug, Clone, Deserialize)] pub struct K8sInfra { pub traefik_tunnel_external_ip: TerraformOutputValue, @@ -29,7 +34,7 @@ pub struct K8sInfra { #[derive(Debug, Clone, Deserialize)] pub struct Tls { - pub tls_cert_letsencrypt_rivet_job: TerraformOutputValue, + pub tls_cert_letsencrypt_rivet_job: Option>, pub tls_cert_locally_signed_tunnel_server: TerraformOutputValue, pub tls_cert_locally_signed_job: TerraformOutputValue, pub tls_cert_locally_signed_gg: TerraformOutputValue, @@ -73,6 +78,10 @@ pub struct Redis { pub port: TerraformOutputValue>, } +pub async fn read_ngrok(ctx: &ProjectContext) -> Ngrok { + read_plan::(ctx, "ngrok").await +} + pub async fn read_k8s_infra(ctx: &ProjectContext) -> K8sInfra { read_plan::(ctx, "k8s_infra").await } diff --git a/lib/bolt/core/src/tasks/infra/mod.rs b/lib/bolt/core/src/tasks/infra/mod.rs index 8925e12433..615c742088 100644 --- a/lib/bolt/core/src/tasks/infra/mod.rs +++ b/lib/bolt/core/src/tasks/infra/mod.rs @@ -104,6 +104,17 @@ pub fn build_plan( ) -> Result> { let mut plan = Vec::new(); + // Ngrok + if ctx.ns().ngrok.is_some() { + plan.push(PlanStep { + name_id: "ngrok", + kind: PlanStepKind::Terraform { + plan_id: "ngrok".into(), + needs_destroy: true, + }, + }); + } + // Infra match ctx.ns().kubernetes.provider { ns::KubernetesProvider::K3d { .. } => { @@ -135,16 +146,14 @@ pub fn build_plan( }, }); - if ctx.tls_enabled() { - // TLS - plan.push(PlanStep { - name_id: "tls", - kind: PlanStepKind::Terraform { - plan_id: "tls".into(), - needs_destroy: true, - }, - }); - } + // TLS + plan.push(PlanStep { + name_id: "tls", + kind: PlanStepKind::Terraform { + plan_id: "tls".into(), + needs_destroy: true, + }, + }); // Redis match ctx.ns().redis.provider { diff --git a/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/components.rs b/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/components.rs index 16d9f3ab86..09173a66e8 100644 --- a/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/components.rs +++ b/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/components.rs @@ -273,7 +273,7 @@ pub fn traefik_tunnel() -> GlobalResult { name: "tunnel".into(), static_config: tunnel_traefik_static_config(), dynamic_config: tunnel_traefik_dynamic_config(&util::env::var( - "K8S_TRAEFIK_TUNNEL_EXTERNAL_IP", + "TRAEFIK_TUNNEL_EXTERNAL_HOST", )?), tls_certs: Default::default(), tcp_server_transports, @@ -301,7 +301,7 @@ fn tunnel_traefik_static_config() -> String { config } -fn tunnel_traefik_dynamic_config(tunnel_external_ip: &str) -> String { +fn tunnel_traefik_dynamic_config(tunnel_external_host: &str) -> String { let mut config = String::new(); for TunnelService { name, .. } in TUNNEL_SERVICES.iter() { config.push_str(&formatdoc!( @@ -315,7 +315,7 @@ fn tunnel_traefik_dynamic_config(tunnel_external_ip: &str) -> String { serversTransport = "{name}" [[tcp.services.{name}.loadBalancer.servers]] - address = "{tunnel_external_ip}:5000" + address = "{tunnel_external_host}" tls = true "# )) diff --git a/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/mod.rs b/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/mod.rs index 694dc34016..3dfc7cb601 100644 --- a/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/mod.rs +++ b/svc/pkg/cluster/worker/src/workers/server_install/install_scripts/mod.rs @@ -86,16 +86,24 @@ pub async fn gen_initialize(pool_type: backend::cluster::PoolType) -> GlobalResu ); } backend::cluster::PoolType::Gg => { + let mut tls_certs = HashMap::new(); + if let (Some(cert_pem), Some(key_pem)) = ( + util::env::var("TLS_CERT_LETSENCRYPT_RIVET_JOB_CERT_PEM").ok(), + util::env::var("TLS_CERT_LETSENCRYPT_RIVET_JOB_KEY_PEM").ok(), + ) { + tls_certs.insert( + "letsencrypt_rivet_job".into(), + components::TlsCert { cert_pem, key_pem }, + ); + } else { + tracing::warn!("missing gg certs required for https & tcp+tls routes") + }; + script.push(components::traefik_instance(components::TraefikInstance { name: "game_guard".into(), static_config: gg_traefik_static_config().await?, dynamic_config: String::new(), - tls_certs: hashmap! { - "letsencrypt_rivet_job".into() => components::TlsCert { - cert_pem: util::env::var("TLS_CERT_LETSENCRYPT_RIVET_JOB_CERT_PEM")?, - key_pem: util::env::var("TLS_CERT_LETSENCRYPT_RIVET_JOB_KEY_PEM")?, - }, - }, + tls_certs, tcp_server_transports: Default::default(), }));