ops: scale down all non-critical services — dedicate resources to Neuron

Scaled to replicas: 0: fornax (coordinator/ui/workers), jellyfin via media,
overseerr, plex, radarr, sonarr, bazarr, prowlarr, flaresolverr, ollama,
harmonic-wordpress, docuseal, listmonk, memos, plane, redpanda, wp-coordinator
This commit is contained in:
Will Anderson
2026-04-24 20:07:41 -05:00
parent 6160e8e6b8
commit 91bfc42989
31 changed files with 1022 additions and 27 deletions
+467
View File
@@ -0,0 +1,467 @@
# ── Cloud Run v2 Services ─────────────────────────────────────────────────────
# Three prod regions + one stage region.
# All services use INGRESS_TRAFFIC_ALL so the global LB can reach them.
# Secrets are mounted as env vars via Secret Manager volume references.
locals {
run_labels = {
"managed-by" = "terraform"
"project" = "neuron-marketing"
}
}
# ── Prod — us-central1 ────────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "prod_us" {
name = "marketing-prod-us"
location = "us-central1"
project = var.project_id
# Allow the global HTTP(S) load balancer to reach this service
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.run_labels
template {
service_account = google_service_account.marketing.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
# cpu_idle = false keeps CPU allocated at all times (no throttling between requests)
cpu_idle = false
}
# ── Static env vars ───────────────────────────────────────────────────
env {
name = "NODE_ENV"
value = "production"
}
env {
name = "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY"
value = local.stripe_publishable_key
}
# ── Secret env vars from Secret Manager ───────────────────────────────
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 = 5
timeout_seconds = 5
period_seconds = 10
failure_threshold = 3
}
liveness_probe {
http_get {
path = "/api/health"
port = 3000
}
initial_delay_seconds = 15
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_project_iam_member.marketing_secret_accessor]
}
# ── Prod — europe-west1 ───────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "prod_eu" {
name = "marketing-prod-eu"
location = "europe-west1"
project = var.project_id
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.run_labels
template {
service_account = google_service_account.marketing.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
cpu_idle = false
}
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 = 5
timeout_seconds = 5
period_seconds = 10
failure_threshold = 3
}
liveness_probe {
http_get {
path = "/api/health"
port = 3000
}
initial_delay_seconds = 15
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_project_iam_member.marketing_secret_accessor]
}
# ── Prod — asia-northeast1 ────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "prod_apac" {
name = "marketing-prod-apac"
location = "asia-northeast1"
project = var.project_id
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.run_labels
template {
service_account = google_service_account.marketing.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
cpu_idle = false
}
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 = 5
timeout_seconds = 5
period_seconds = 10
failure_threshold = 3
}
liveness_probe {
http_get {
path = "/api/health"
port = 3000
}
initial_delay_seconds = 15
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
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 = 5
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]
}
+349
View File
@@ -0,0 +1,349 @@
# ── Serverless NEGs ───────────────────────────────────────────────────────────
# One NEG per Cloud Run service. NEGs for Cloud Run must use SERVERLESS type
# and reference the Cloud Run service by name + region.
resource "google_compute_region_network_endpoint_group" "prod_us" {
name = "marketing-neg-us"
network_endpoint_type = "SERVERLESS"
region = "us-central1"
project = var.project_id
cloud_run {
service = google_cloud_run_v2_service.prod_us.name
}
}
resource "google_compute_region_network_endpoint_group" "prod_eu" {
name = "marketing-neg-eu"
network_endpoint_type = "SERVERLESS"
region = "europe-west1"
project = var.project_id
cloud_run {
service = google_cloud_run_v2_service.prod_eu.name
}
}
resource "google_compute_region_network_endpoint_group" "prod_apac" {
name = "marketing-neg-apac"
network_endpoint_type = "SERVERLESS"
region = "asia-northeast1"
project = var.project_id
cloud_run {
service = google_cloud_run_v2_service.prod_apac.name
}
}
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 ───────────────────────────────────────────────
# Applied to the backend service. Rules evaluated top-down (lowest priority wins).
resource "google_compute_security_policy" "marketing" {
name = "marketing-armor"
project = var.project_id
description = "Cloud Armor policy for neurontechnologies.ai marketing site"
# ── Rule 1000: SQLi protection ────────────────────────────────────────────
rule {
action = "deny(403)"
priority = 1000
description = "Block SQLi attacks (OWASP CRS sqli-v33-stable)"
match {
expr {
expression = "evaluatePreconfiguredWaf('sqli-v33-stable', {'sensitivity': 1})"
}
}
}
# ── Rule 1001: XSS protection ─────────────────────────────────────────────
rule {
action = "deny(403)"
priority = 1001
description = "Block XSS attacks (OWASP CRS xss-v33-stable)"
match {
expr {
expression = "evaluatePreconfiguredWaf('xss-v33-stable', {'sensitivity': 1})"
}
}
}
# ── Rule 2000: Rate limiting ───────────────────────────────────────────────
# Throttle any single IP exceeding 1000 req/min (≈17 req/s).
rule {
action = "throttle"
priority = 2000
description = "Rate limit: 1000 req/min per IP"
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["*"]
}
}
rate_limit_options {
conform_action = "allow"
exceed_action = "deny(429)"
rate_limit_threshold {
count = 1000
interval_sec = 60
}
enforce_on_key = "IP"
}
}
# ── Default rule: allow all ───────────────────────────────────────────────
rule {
action = "allow"
priority = 2147483647
description = "Default: allow"
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["*"]
}
}
}
}
# ── Prod Backend Service ──────────────────────────────────────────────────────
# EXTERNAL_MANAGED scheme is required for Cloud CDN + global LB.
# All three regional NEGs are attached with equal weight.
resource "google_compute_backend_service" "prod" {
name = "marketing-backend-prod"
project = var.project_id
load_balancing_scheme = "EXTERNAL_MANAGED"
protocol = "HTTPS"
timeout_sec = 30
# Cloud Armor
security_policy = google_compute_security_policy.marketing.self_link
# Cloud CDN
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
default_ttl = 3600
max_ttl = 86400
client_ttl = 3600
negative_caching = true
serve_while_stale = 86400
cache_key_policy {
include_host = true
include_protocol = true
include_query_string = true
}
}
backend {
group = google_compute_region_network_endpoint_group.prod_us.self_link
}
backend {
group = google_compute_region_network_endpoint_group.prod_eu.self_link
}
backend {
group = google_compute_region_network_endpoint_group.prod_apac.self_link
}
log_config {
enable = true
sample_rate = 1.0
}
}
# ── 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 ──────────────────────────────────────────────────────────
# google_compute_managed_ssl_certificate — Google-managed, auto-renewed.
# Provisioning requires DNS A records pointing to the LB IP (chicken-and-egg:
# apply the Terraform, get the IP from outputs, update DNS, then cert provisions).
resource "google_compute_managed_ssl_certificate" "prod" {
name = "marketing-cert-prod"
project = var.project_id
managed {
domains = [
"neurontechnologies.ai",
"www.neurontechnologies.ai",
]
}
}
resource "google_compute_managed_ssl_certificate" "stage" {
name = "marketing-cert-stage"
project = var.project_id
managed {
domains = ["stage.neurontechnologies.ai"]
}
}
# ── Prod URL Map ──────────────────────────────────────────────────────────────
resource "google_compute_url_map" "prod" {
name = "marketing-urlmap-prod"
project = var.project_id
default_service = google_compute_backend_service.prod.self_link
}
# ── Prod HTTPS Target Proxy ───────────────────────────────────────────────────
resource "google_compute_target_https_proxy" "prod" {
name = "marketing-https-proxy-prod"
project = var.project_id
url_map = google_compute_url_map.prod.self_link
ssl_certificates = [google_compute_managed_ssl_certificate.prod.self_link]
}
# ── Prod HTTP → HTTPS redirect ────────────────────────────────────────────────
# Separate URL map that redirects all HTTP traffic to HTTPS.
resource "google_compute_url_map" "prod_http_redirect" {
name = "marketing-urlmap-prod-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" "prod" {
name = "marketing-http-proxy-prod"
project = var.project_id
url_map = google_compute_url_map.prod_http_redirect.self_link
}
# ── Prod Global Forwarding Rules ──────────────────────────────────────────────
# Both rules share the same global anycast IP.
resource "google_compute_global_address" "prod" {
name = "marketing-ip-prod"
project = var.project_id
}
resource "google_compute_global_forwarding_rule" "prod_https" {
name = "marketing-fwd-prod-https"
project = var.project_id
target = google_compute_target_https_proxy.prod.self_link
ip_address = google_compute_global_address.prod.address
port_range = "443"
load_balancing_scheme = "EXTERNAL_MANAGED"
}
resource "google_compute_global_forwarding_rule" "prod_http" {
name = "marketing-fwd-prod-http"
project = var.project_id
target = google_compute_target_http_proxy.prod.self_link
ip_address = google_compute_global_address.prod.address
port_range = "80"
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"
}
+37
View File
@@ -0,0 +1,37 @@
terraform {
required_version = ">= 1.5"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "legion-terraform-state"
key = "gcp/terraform.tfstate"
region = "auto"
endpoint = "https://651161e0a3d321561b4c90b5bcd5f15b.r2.cloudflarestorage.com"
# R2 is S3-compatible but not AWS — skip AWS-specific checks
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
force_path_style = true
}
}
provider "google" {
project = var.project_id
region = "us-central1"
}
provider "google-beta" {
project = var.project_id
region = "us-central1"
}
+44
View File
@@ -0,0 +1,44 @@
# ── Outputs ───────────────────────────────────────────────────────────────────
# After `terraform apply`, use these IPs to update Cloudflare DNS A records.
#
# Prod: neurontechnologies.ai + www.neurontechnologies.ai → prod_lb_ip
# Stage: stage.neurontechnologies.ai → stage_lb_ip
#
# In the Legion Terraform (dns-neurontechnologies.tf), replace the tunnel CNAMEs
# for neurontechnologies.ai, www, and stage with A records pointing to these IPs.
# Set proxied=true in Cloudflare to keep CDN/DDoS protection layered in front.
output "prod_lb_ip" {
description = "Global anycast IP for the production load balancer (neurontechnologies.ai + www)"
value = google_compute_global_address.prod.address
}
output "stage_lb_ip" {
description = "Global anycast IP for the staging load balancer (stage.neurontechnologies.ai)"
value = google_compute_global_address.stage.address
}
output "prod_ssl_cert_name" {
description = "Name of the Google-managed SSL cert for prod (check provisioning status in GCP console)"
value = google_compute_managed_ssl_certificate.prod.name
}
output "stage_ssl_cert_name" {
description = "Name of the Google-managed SSL cert for stage"
value = google_compute_managed_ssl_certificate.stage.name
}
output "marketing_service_account_email" {
description = "Service account email for Cloud Run services"
value = google_service_account.marketing.email
}
output "cloud_run_services" {
description = "Cloud Run service URLs per region"
value = {
prod_us = google_cloud_run_v2_service.prod_us.uri
prod_eu = google_cloud_run_v2_service.prod_eu.uri
prod_apac = google_cloud_run_v2_service.prod_apac.uri
stage = google_cloud_run_v2_service.stage.uri
}
}
+54
View File
@@ -0,0 +1,54 @@
# ── Service Account ───────────────────────────────────────────────────────────
resource "google_service_account" "marketing" {
account_id = "neuron-marketing-sa"
display_name = "Neuron Marketing Cloud Run SA"
description = "Service account for the neurontechnologies.ai marketing site on Cloud Run"
}
# ── IAM — Secret Manager accessor ─────────────────────────────────────────────
# Grant the SA access to read all marketing secrets from Secret Manager.
resource "google_project_iam_member" "marketing_secret_accessor" {
project = var.project_id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.marketing.email}"
}
# ── IAM — Public (unauthenticated) invocation for prod services ───────────────
# Cloud Run v2: allow-unauthenticated is set per-service via google_cloud_run_v2_service_iam_member.
resource "google_cloud_run_v2_service_iam_member" "prod_us_public" {
project = var.project_id
location = "us-central1"
name = google_cloud_run_v2_service.prod_us.name
role = "roles/run.invoker"
member = "allUsers"
}
resource "google_cloud_run_v2_service_iam_member" "prod_eu_public" {
project = var.project_id
location = "europe-west1"
name = google_cloud_run_v2_service.prod_eu.name
role = "roles/run.invoker"
member = "allUsers"
}
resource "google_cloud_run_v2_service_iam_member" "prod_apac_public" {
project = var.project_id
location = "asia-northeast1"
name = google_cloud_run_v2_service.prod_apac.name
role = "roles/run.invoker"
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 authentication in front of stage.
# Cloud Run itself allows allUsers so the LB health checks pass.
}
+1
View File
@@ -0,0 +1 @@
cloudflare_zone_id_neurontechnologies = "e844374f203dca4944d77d40ca0710ae"
+43
View File
@@ -0,0 +1,43 @@
variable "project_id" {
description = "GCP project ID"
type = string
default = "neuron-785695"
}
variable "image_tag" {
description = "Docker image tag to deploy"
type = string
default = "latest"
}
variable "cloudflare_zone_id_neurontechnologies" {
description = "Cloudflare zone ID for neurontechnologies.ai (look up from Legion Terraform state or Cloudflare dashboard)"
type = string
# Set this in terraform.tfvars — do not hardcode here.
# To find: cloudflare_zone.neurontechnologies_ai.id in the Legion Terraform state,
# or: curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=neurontechnologies.ai" -H "X-Auth-Email: andersonwilliam85@gmail.com" -H "X-Auth-Key: <key>"
}
locals {
project_id = var.project_id
image = "us-central1-docker.pkg.dev/${var.project_id}/neuron-marketing/marketing:${var.image_tag}"
# Production secrets from GCP Secret Manager
secrets = [
"stripe-secret-key",
"stripe-webhook-secret",
"stripe-price-professional",
"stripe-price-founding",
]
# Env var names for each secret (uppercase, hyphen → underscore)
secret_env_map = {
"stripe-secret-key" = "STRIPE_SECRET_KEY"
"stripe-webhook-secret" = "STRIPE_WEBHOOK_SECRET"
"stripe-price-professional" = "STRIPE_PRICE_PROFESSIONAL"
"stripe-price-founding" = "STRIPE_PRICE_FOUNDING"
}
# Static publishable key (not sensitive — lives in source)
stripe_publishable_key = "pk_live_51TPoHnJg9Fv1D3AUPMXnYyOJIVhn1FyH56zCMNnATo9tR7pO9lNDbXncp6VeDxm38qSdBHZPfqEBipUh3GZsWNyd00jvIO97E6"
}
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
labels:
app: ollama
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -4,7 +4,7 @@ metadata:
name: docuseal
namespace: docuseal
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: docuseal
@@ -6,7 +6,7 @@ metadata:
labels:
app: fornax-coordinator
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: fornax-coordinator
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
labels:
app: fornax-ui
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: fornax-ui
@@ -8,7 +8,7 @@ metadata:
app.kubernetes.io/part-of: fornax
app.kubernetes.io/component: worker
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: fornax-worker-WORKER_ID
@@ -6,7 +6,7 @@ metadata:
labels:
app: mysql
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
@@ -83,7 +83,7 @@ metadata:
labels:
app: wordpress
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -5,7 +5,7 @@ metadata:
name: listmonk
namespace: listmonk
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: listmonk
+1 -1
View File
@@ -114,7 +114,7 @@ metadata:
labels:
app: bazarr
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -9,7 +9,7 @@ metadata:
labels:
app: flaresolverr
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: flaresolverr
+2 -2
View File
@@ -15,7 +15,7 @@ metadata:
fornax-role: worker
fornax-server: us-tx-253
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
@@ -276,7 +276,7 @@ metadata:
fornax-role: worker
fornax-server: us-tx-34
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -133,7 +133,7 @@ metadata:
labels:
app: overseerr
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -17,7 +17,7 @@ metadata:
labels:
app: jellyfin
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -15,7 +15,7 @@ metadata:
labels:
app: prowlarr
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -10,7 +10,7 @@ metadata:
labels:
app: radarr
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -11,7 +11,7 @@ metadata:
labels:
app: sonarr
spec:
replicas: 1
replicas: 0
strategy:
type: Recreate
selector:
+1 -1
View File
@@ -5,7 +5,7 @@ metadata:
name: memos
namespace: memos
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: memos
+1 -1
View File
@@ -5,7 +5,7 @@ metadata:
name: plane-api
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-api
+1 -1
View File
@@ -4,7 +4,7 @@ metadata:
name: plane-beat
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-beat
+1 -1
View File
@@ -17,7 +17,7 @@ metadata:
name: plane-postgres
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-postgres
+1 -1
View File
@@ -5,7 +5,7 @@ metadata:
name: plane-redis
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-redis
+1 -1
View File
@@ -5,7 +5,7 @@ metadata:
name: plane-web
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-web
+1 -1
View File
@@ -4,7 +4,7 @@ metadata:
name: plane-worker
namespace: plane
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: plane-worker
+2 -2
View File
@@ -6,7 +6,7 @@ metadata:
labels:
app: redpanda
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: redpanda
@@ -105,7 +105,7 @@ metadata:
labels:
app: redpanda-console
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: redpanda-console
@@ -6,7 +6,7 @@ metadata:
labels:
app: wp-coordinator
spec:
replicas: 1
replicas: 0
selector:
matchLabels:
app: wp-coordinator