Add GCS backup bucket + dual-destination hourly backup (R2 + GCS)

Provision Google Cloud Storage bucket for neuron prod DB backups via Terraform.
Create dedicated backup service account with objectAdmin on the bucket.
Update neuron-prod backup CronJob to run restic against both R2 and GCS hourly —
R2 as primary, GCS as secondary, independent credentials and repositories.
This commit is contained in:
Will Anderson
2026-04-25 15:23:51 -05:00
parent 491d00fd1a
commit a37deca724
3 changed files with 130 additions and 11 deletions
+70
View File
@@ -0,0 +1,70 @@
# Google Cloud Storage — neuron backup bucket + dedicated service account
# Paired with: k8s/neuron-technologies/prod/backup-cronjob.yaml (restic → GCS)
# k8s/backup/cronjob.yaml (restic → GCS for Gitea/Postgres)
variable "gcp_project_id" {
description = "Google Cloud project ID"
type = string
default = "neuron-785695"
}
provider "google" {
project = var.gcp_project_id
credentials = fileexists("${path.module}/vault-gcp-sa.json") ? file("${path.module}/vault-gcp-sa.json") : null
}
# ── Neuron prod DB backup bucket ──────────────────────────────────────────────
resource "google_storage_bucket" "neuron_backup" {
name = "neuron-backup-${var.gcp_project_id}"
location = "US"
force_destroy = false
uniform_bucket_level_access = true
versioning {
enabled = false
}
lifecycle_rule {
condition { age = 90 }
action { type = "Delete" }
}
labels = {
managed-by = "terraform"
service = "neuron"
purpose = "backup"
tier = "prod"
}
}
# ── Dedicated service account for backup writes ───────────────────────────────
resource "google_service_account" "neuron_backup" {
account_id = "neuron-backup"
display_name = "Neuron Backup"
description = "Used by k8s restic CronJobs to write hourly backups to GCS"
project = var.gcp_project_id
}
resource "google_storage_bucket_iam_member" "neuron_backup_writer" {
bucket = google_storage_bucket.neuron_backup.name
role = "roles/storage.objectAdmin"
member = "serviceAccount:${google_service_account.neuron_backup.email}"
}
resource "google_service_account_key" "neuron_backup" {
service_account_id = google_service_account.neuron_backup.name
# After first apply: copy the base64 key into Vault:
# vault kv put secret/data/gcs neuron_backup_sa_key="$(terraform output -raw neuron_backup_sa_key_base64 | base64 -d)"
}
output "neuron_backup_gcs_bucket" {
value = google_storage_bucket.neuron_backup.name
description = "GCS bucket name for use in RESTIC_REPOSITORY_GCS"
}
output "neuron_backup_sa_key_base64" {
value = google_service_account_key.neuron_backup.private_key
sensitive = true
description = "Base64-encoded SA key JSON — store in Vault: secret/data/gcs.neuron_backup_sa_key"
}