Remove stage environment from GCP — staging is local only
This commit is contained in:
@@ -357,111 +357,3 @@ resource "google_cloud_run_v2_service" "prod_apac" {
|
|||||||
depends_on = [google_project_iam_member.marketing_secret_accessor]
|
depends_on = [google_project_iam_member.marketing_secret_accessor]
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Stage — us-central1 ───────────────────────────────────────────────────────
|
|
||||||
# min_instances=0 to save cost on staging.
|
|
||||||
# Cloudflare Access handles auth in front; Cloud Run itself is open so the LB
|
|
||||||
# health checks pass without credentials.
|
|
||||||
|
|
||||||
resource "google_cloud_run_v2_service" "stage" {
|
|
||||||
name = "marketing-stage"
|
|
||||||
location = "us-central1"
|
|
||||||
project = var.project_id
|
|
||||||
|
|
||||||
ingress = "INGRESS_TRAFFIC_ALL"
|
|
||||||
|
|
||||||
labels = merge(local.run_labels, {
|
|
||||||
"environment" = "stage"
|
|
||||||
})
|
|
||||||
|
|
||||||
template {
|
|
||||||
service_account = google_service_account.marketing.email
|
|
||||||
|
|
||||||
scaling {
|
|
||||||
min_instance_count = 0
|
|
||||||
max_instance_count = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
containers {
|
|
||||||
image = local.image
|
|
||||||
|
|
||||||
resources {
|
|
||||||
limits = {
|
|
||||||
cpu = "1"
|
|
||||||
memory = "512Mi"
|
|
||||||
}
|
|
||||||
cpu_idle = true
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "NODE_ENV"
|
|
||||||
value = "production"
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY"
|
|
||||||
value = local.stripe_publishable_key
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "STRIPE_SECRET_KEY"
|
|
||||||
value_source {
|
|
||||||
secret_key_ref {
|
|
||||||
secret = "stripe-secret-key"
|
|
||||||
version = "latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "STRIPE_WEBHOOK_SECRET"
|
|
||||||
value_source {
|
|
||||||
secret_key_ref {
|
|
||||||
secret = "stripe-webhook-secret"
|
|
||||||
version = "latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "STRIPE_PRICE_PROFESSIONAL"
|
|
||||||
value_source {
|
|
||||||
secret_key_ref {
|
|
||||||
secret = "stripe-price-professional"
|
|
||||||
version = "latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "STRIPE_PRICE_FOUNDING"
|
|
||||||
value_source {
|
|
||||||
secret_key_ref {
|
|
||||||
secret = "stripe-price-founding"
|
|
||||||
version = "latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ports {
|
|
||||||
container_port = 3000
|
|
||||||
name = "http1"
|
|
||||||
}
|
|
||||||
|
|
||||||
startup_probe {
|
|
||||||
http_get {
|
|
||||||
path = "/api/health"
|
|
||||||
port = 3000
|
|
||||||
}
|
|
||||||
initial_delay_seconds = 10
|
|
||||||
timeout_seconds = 5
|
|
||||||
period_seconds = 10
|
|
||||||
failure_threshold = 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
max_instance_request_concurrency = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
traffic {
|
|
||||||
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
|
|
||||||
percent = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
depends_on = [google_project_iam_member.marketing_secret_accessor]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -35,17 +35,6 @@ resource "google_compute_region_network_endpoint_group" "prod_apac" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_region_network_endpoint_group" "stage" {
|
|
||||||
name = "marketing-neg-stage"
|
|
||||||
network_endpoint_type = "SERVERLESS"
|
|
||||||
region = "us-central1"
|
|
||||||
project = var.project_id
|
|
||||||
|
|
||||||
cloud_run {
|
|
||||||
service = google_cloud_run_v2_service.stage.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Cloud Armor Security Policy ───────────────────────────────────────────────
|
# ── Cloud Armor Security Policy ───────────────────────────────────────────────
|
||||||
# Applied to the backend service. Rules evaluated top-down (lowest priority wins).
|
# Applied to the backend service. Rules evaluated top-down (lowest priority wins).
|
||||||
|
|
||||||
@@ -173,30 +162,6 @@ resource "google_compute_backend_service" "prod" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Stage Backend Service ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
resource "google_compute_backend_service" "stage" {
|
|
||||||
name = "marketing-backend-stage"
|
|
||||||
project = var.project_id
|
|
||||||
load_balancing_scheme = "EXTERNAL_MANAGED"
|
|
||||||
protocol = "HTTPS"
|
|
||||||
timeout_sec = 30
|
|
||||||
|
|
||||||
# Cloud Armor on stage too
|
|
||||||
security_policy = google_compute_security_policy.marketing.self_link
|
|
||||||
|
|
||||||
enable_cdn = false # CDN off for stage — we want fresh responses always
|
|
||||||
|
|
||||||
backend {
|
|
||||||
group = google_compute_region_network_endpoint_group.stage.self_link
|
|
||||||
}
|
|
||||||
|
|
||||||
log_config {
|
|
||||||
enable = true
|
|
||||||
sample_rate = 1.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── SSL Certificates ──────────────────────────────────────────────────────────
|
# ── SSL Certificates ──────────────────────────────────────────────────────────
|
||||||
# google_compute_managed_ssl_certificate — Google-managed, auto-renewed.
|
# google_compute_managed_ssl_certificate — Google-managed, auto-renewed.
|
||||||
# Provisioning requires DNS A records pointing to the LB IP (chicken-and-egg:
|
# Provisioning requires DNS A records pointing to the LB IP (chicken-and-egg:
|
||||||
@@ -214,15 +179,6 @@ resource "google_compute_managed_ssl_certificate" "prod" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_managed_ssl_certificate" "stage" {
|
|
||||||
name = "marketing-cert-stage"
|
|
||||||
project = var.project_id
|
|
||||||
|
|
||||||
managed {
|
|
||||||
domains = ["stage.neurontechnologies.ai"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Prod URL Map — host-based routing ────────────────────────────────────────
|
# ── Prod URL Map — host-based routing ────────────────────────────────────────
|
||||||
# One global IP handles all three services via Host header routing.
|
# One global IP handles all three services via Host header routing.
|
||||||
# - neurontechnologies.ai / www. → marketing (default)
|
# - neurontechnologies.ai / www. → marketing (default)
|
||||||
@@ -324,64 +280,3 @@ resource "google_compute_global_forwarding_rule" "prod_http" {
|
|||||||
load_balancing_scheme = "EXTERNAL_MANAGED"
|
load_balancing_scheme = "EXTERNAL_MANAGED"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Stage URL Map ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
resource "google_compute_url_map" "stage" {
|
|
||||||
name = "marketing-urlmap-stage"
|
|
||||||
project = var.project_id
|
|
||||||
default_service = google_compute_backend_service.stage.self_link
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Stage HTTPS Target Proxy ──────────────────────────────────────────────────
|
|
||||||
|
|
||||||
resource "google_compute_target_https_proxy" "stage" {
|
|
||||||
name = "marketing-https-proxy-stage"
|
|
||||||
project = var.project_id
|
|
||||||
url_map = google_compute_url_map.stage.self_link
|
|
||||||
ssl_certificates = [google_compute_managed_ssl_certificate.stage.self_link]
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Stage HTTP → HTTPS redirect ───────────────────────────────────────────────
|
|
||||||
|
|
||||||
resource "google_compute_url_map" "stage_http_redirect" {
|
|
||||||
name = "marketing-urlmap-stage-http-redirect"
|
|
||||||
project = var.project_id
|
|
||||||
|
|
||||||
default_url_redirect {
|
|
||||||
https_redirect = true
|
|
||||||
redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
|
|
||||||
strip_query = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_compute_target_http_proxy" "stage" {
|
|
||||||
name = "marketing-http-proxy-stage"
|
|
||||||
project = var.project_id
|
|
||||||
url_map = google_compute_url_map.stage_http_redirect.self_link
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Stage Global Forwarding Rules ─────────────────────────────────────────────
|
|
||||||
# Separate global IP for stage so DNS is independent.
|
|
||||||
|
|
||||||
resource "google_compute_global_address" "stage" {
|
|
||||||
name = "marketing-ip-stage"
|
|
||||||
project = var.project_id
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_compute_global_forwarding_rule" "stage_https" {
|
|
||||||
name = "marketing-fwd-stage-https"
|
|
||||||
project = var.project_id
|
|
||||||
target = google_compute_target_https_proxy.stage.self_link
|
|
||||||
ip_address = google_compute_global_address.stage.address
|
|
||||||
port_range = "443"
|
|
||||||
load_balancing_scheme = "EXTERNAL_MANAGED"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_compute_global_forwarding_rule" "stage_http" {
|
|
||||||
name = "marketing-fwd-stage-http"
|
|
||||||
project = var.project_id
|
|
||||||
target = google_compute_target_http_proxy.stage.self_link
|
|
||||||
ip_address = google_compute_global_address.stage.address
|
|
||||||
port_range = "80"
|
|
||||||
load_balancing_scheme = "EXTERNAL_MANAGED"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,19 +7,12 @@
|
|||||||
# www.neurontechnologies.ai → prod_lb_ip
|
# www.neurontechnologies.ai → prod_lb_ip
|
||||||
# api.neurontechnologies.ai → prod_lb_ip
|
# api.neurontechnologies.ai → prod_lb_ip
|
||||||
# accounts.neurontechnologies.ai → prod_lb_ip
|
# accounts.neurontechnologies.ai → prod_lb_ip
|
||||||
#
|
|
||||||
# Stage: stage.neurontechnologies.ai → stage_lb_ip (separate IP)
|
|
||||||
|
|
||||||
output "prod_lb_ip" {
|
output "prod_lb_ip" {
|
||||||
description = "Global anycast IP for all prod services (marketing, accounts, api)"
|
description = "Global anycast IP for all prod services (marketing, accounts, api)"
|
||||||
value = google_compute_global_address.prod.address
|
value = google_compute_global_address.prod.address
|
||||||
}
|
}
|
||||||
|
|
||||||
output "stage_lb_ip" {
|
|
||||||
description = "Global anycast IP for the staging load balancer"
|
|
||||||
value = google_compute_global_address.stage.address
|
|
||||||
}
|
|
||||||
|
|
||||||
output "prod_ssl_cert_name" {
|
output "prod_ssl_cert_name" {
|
||||||
description = "Marketing SSL cert (check provisioning status in GCP console)"
|
description = "Marketing SSL cert (check provisioning status in GCP console)"
|
||||||
value = google_compute_managed_ssl_certificate.prod.name
|
value = google_compute_managed_ssl_certificate.prod.name
|
||||||
@@ -35,11 +28,6 @@ output "api_ssl_cert_name" {
|
|||||||
value = google_compute_managed_ssl_certificate.api.name
|
value = google_compute_managed_ssl_certificate.api.name
|
||||||
}
|
}
|
||||||
|
|
||||||
output "stage_ssl_cert_name" {
|
|
||||||
description = "Stage SSL cert"
|
|
||||||
value = google_compute_managed_ssl_certificate.stage.name
|
|
||||||
}
|
|
||||||
|
|
||||||
output "marketing_service_account_email" {
|
output "marketing_service_account_email" {
|
||||||
description = "Marketing Cloud Run SA"
|
description = "Marketing Cloud Run SA"
|
||||||
value = google_service_account.marketing.email
|
value = google_service_account.marketing.email
|
||||||
@@ -76,7 +64,6 @@ output "cloud_run_services" {
|
|||||||
marketing_us = google_cloud_run_v2_service.prod_us.uri
|
marketing_us = google_cloud_run_v2_service.prod_us.uri
|
||||||
marketing_eu = google_cloud_run_v2_service.prod_eu.uri
|
marketing_eu = google_cloud_run_v2_service.prod_eu.uri
|
||||||
marketing_apac = google_cloud_run_v2_service.prod_apac.uri
|
marketing_apac = google_cloud_run_v2_service.prod_apac.uri
|
||||||
marketing_stage = google_cloud_run_v2_service.stage.uri
|
|
||||||
accounts_us = google_cloud_run_v2_service.accounts_us.uri
|
accounts_us = google_cloud_run_v2_service.accounts_us.uri
|
||||||
accounts_eu = google_cloud_run_v2_service.accounts_eu.uri
|
accounts_eu = google_cloud_run_v2_service.accounts_eu.uri
|
||||||
accounts_apac = google_cloud_run_v2_service.accounts_apac.uri
|
accounts_apac = google_cloud_run_v2_service.accounts_apac.uri
|
||||||
|
|||||||
@@ -79,15 +79,6 @@ resource "google_cloud_run_v2_service_iam_member" "prod_apac_public" {
|
|||||||
member = "allUsers"
|
member = "allUsers"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_cloud_run_v2_service_iam_member" "stage_public" {
|
|
||||||
project = var.project_id
|
|
||||||
location = "us-central1"
|
|
||||||
name = google_cloud_run_v2_service.stage.name
|
|
||||||
role = "roles/run.invoker"
|
|
||||||
member = "allUsers"
|
|
||||||
# Note: Cloudflare Access enforces auth in front of stage.
|
|
||||||
}
|
|
||||||
|
|
||||||
# Accounts
|
# Accounts
|
||||||
resource "google_cloud_run_v2_service_iam_member" "accounts_us_public" {
|
resource "google_cloud_run_v2_service_iam_member" "accounts_us_public" {
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
|
|||||||
Reference in New Issue
Block a user