Wire Forge-native release infrastructure
Some checks failed
Cache: Publish Nix / Publish Nix Cache (push) Waiting to run
Build Rust / Cargo Test (push) Successful in 4m14s
Build Site / Next.js Build (push) Failing after 6s
Infra: OpenTofu / OpenTofu (grafana) (push) Successful in 5s
Lint Governance / BEP Metadata (push) Successful in 0s
Build: Android / Android Rust Core Stub (push) Failing after 23s

This commit is contained in:
Conrad Kramer 2026-06-07 05:51:12 -07:00
parent 97c569fb35
commit 002bd382e9
199 changed files with 14268 additions and 185 deletions

5
infra/releases/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.terraform/
*.tfstate
*.tfstate.*
backend.hcl
terraform.tfvars

20
infra/releases/.terraform.lock.hcl generated Normal file
View file

@ -0,0 +1,20 @@
# This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates.
provider "registry.opentofu.org/hashicorp/google" {
version = "6.50.0"
constraints = ">= 5.40.0, < 7.0.0"
hashes = [
"h1:MAAe4zFFdqS9M5rpmJK/vKgdb6ZMD/s/0Xd97yTDipA=",
"zh:1d4695f807d998f11fcdcfa174766287b82a8093513af857bcdad2d81c642480",
"zh:3173ac5df0294624d113812e49e2a55714aff7db617488168cecdf4168df9e29",
"zh:34d2b3d44c23bd6354fc4ab5917b302872ea1ab8de107034567f955b1717fa5b",
"zh:3a77f3cc2f3664cd5aaeeef4d044e6ec1695a079588fffec3ca03953664e5f04",
"zh:6b444e4b629ea8dc8cb112a39dde098dc5584d26d6de4177558f556a9a226696",
"zh:96545c8cd4d3a57069c5d1799eab5aedd887e16d98b5559a195f6d2c2d9bc674",
"zh:ba464caafde95ee16671d6b5ec90f053ed77a9d06c567456db6efd9160fa3165",
"zh:d876938e5b0d3f57a984d9be72467995f87fef6569968623415dc51d9f54d30b",
"zh:dfd908d873e314ab807d0abc9cfd42d2611cd06dc1b9ec719ebdbb738e8e68d6",
"zh:f9f16819a7738d564afd45fd169ba61004ec4e4e7089d2a4950cb8895be1fe1f",
]
}

54
infra/releases/README.md Normal file
View file

@ -0,0 +1,54 @@
# Burrow Release Storage
This OpenTofu stack owns Google Cloud Storage buckets used as Burrow's first
release-storage backup target.
Garage is the required S3-compatible primary target. CI uses repo-owned storage
wrappers: they upload to Garage first, then mirror to GCS unless the backup is
explicitly disabled.
The host activation point is `services.burrow.garage`, enabled by the forge
host. It creates the initial single-node Garage layout and buckets from
host-local runtime secrets.
It may manage:
- the release artifact bucket served by `releases.burrow.net`
- the signed package repository bucket served by `packages.burrow.net`
- the private Nix cache backup bucket for `nix.burrow.net`
- public object-read IAM for download buckets
- object-admin IAM for the Burrow Forgejo runner service account
It must not manage:
- Google service-account JSON keys
- release signing keys
- package repository metadata
- DNS or CDN cutover
GCS access is keyless. Forgejo jobs run `Scripts/ci/google-wif-auth.sh` to
trade an Authentik-issued OIDC token for the Google runner service account in
project `project-88c23ce9-918a-470a-b33`, then use `gcloud storage` against the
managed backup buckets. The normal release path does not use rclone or Google
service-account JSON keys.
The Nix cache backup bucket defaults to private. Attic remains the public cache
surface at `nix.burrow.net`; GCS is only a backup target for the Garage `attic`
bucket.
## Run
```sh
Scripts/releases-tofu.sh init -backend-config=backend.hcl
Scripts/releases-tofu.sh plan -var-file=terraform.tfvars
```
For local syntax work without remote state:
```sh
Scripts/releases-tofu.sh init -backend=false
Scripts/releases-tofu.sh validate
```
Start with `manage_google = false`. Import existing buckets before enabling
management if they already exist.

View file

@ -0,0 +1,3 @@
bucket = "burrow-opentofu-state"
key = "releases/releases.tfstate"
region = "us-west-2"

29
infra/releases/outputs.tf Normal file
View file

@ -0,0 +1,29 @@
output "google_release_bucket_name" {
description = "GCS bucket used for release artifacts."
value = try(google_storage_bucket.release_storage["releases"].name, var.google_release_bucket_name)
}
output "google_package_bucket_name" {
description = "GCS bucket used for signed package repositories."
value = try(google_storage_bucket.release_storage["packages"].name, var.google_package_bucket_name)
}
output "google_nix_cache_bucket_name" {
description = "GCS bucket used for Nix cache backups."
value = try(google_storage_bucket.release_storage["nix-cache"].name, var.google_nix_cache_bucket_name)
}
output "google_release_bucket_uri" {
description = "GCS URI for release artifacts."
value = "gs://${try(google_storage_bucket.release_storage["releases"].name, var.google_release_bucket_name)}"
}
output "google_package_bucket_uri" {
description = "GCS URI for signed package repositories."
value = "gs://${try(google_storage_bucket.release_storage["packages"].name, var.google_package_bucket_name)}"
}
output "google_nix_cache_bucket_uri" {
description = "GCS URI for Nix cache backups."
value = "gs://${try(google_storage_bucket.release_storage["nix-cache"].name, var.google_nix_cache_bucket_name)}"
}

View file

@ -0,0 +1,3 @@
provider "google" {
project = var.google_project_id
}

116
infra/releases/storage.tf Normal file
View file

@ -0,0 +1,116 @@
locals {
google_required_services = toset([
"storage.googleapis.com",
])
release_storage_buckets = {
releases = {
name = var.google_release_bucket_name
description = "Burrow release artifacts"
public = var.google_release_public_read
}
packages = {
name = var.google_package_bucket_name
description = "Burrow signed package repositories"
public = var.google_package_public_read
}
nix-cache = {
name = var.google_nix_cache_bucket_name
description = "Burrow Nix cache backups"
public = var.google_nix_cache_public_read
}
}
release_storage_writer_members = setunion(
var.google_release_extra_writer_members,
toset(["serviceAccount:${var.google_runner_service_account_email}"]),
)
release_storage_writer_grants = var.manage_google ? {
for grant in flatten([
for bucket_key in keys(local.release_storage_buckets) : [
for member in local.release_storage_writer_members : {
id = "${bucket_key}|${member}"
bucket_key = bucket_key
member = member
}
]
]) : grant.id => grant
} : {}
release_storage_public_grants = var.manage_google ? {
for bucket_key, bucket in local.release_storage_buckets : bucket_key => bucket
if bucket.public
} : {}
}
resource "google_project_service" "release_storage" {
for_each = var.manage_google ? local.google_required_services : toset([])
project = var.google_project_id
service = each.value
disable_on_destroy = false
}
resource "google_storage_bucket" "release_storage" {
for_each = var.manage_google ? local.release_storage_buckets : {}
project = var.google_project_id
name = each.value.name
location = var.google_storage_location
uniform_bucket_level_access = true
public_access_prevention = each.value.public ? "inherited" : "enforced"
force_destroy = false
labels = merge(
{
project = "burrow"
component = "release-storage"
managed_by = "opentofu"
bucket = each.key
},
var.tags,
)
versioning {
enabled = true
}
cors {
origin = var.google_storage_cors_origins
method = ["GET", "HEAD", "OPTIONS"]
response_header = ["Content-Type", "Content-Length", "ETag", "Cache-Control"]
max_age_seconds = 3600
}
lifecycle_rule {
condition {
age = 30
with_state = "ARCHIVED"
num_newer_versions = 5
matches_storage_class = ["STANDARD"]
}
action {
type = "Delete"
}
}
depends_on = [google_project_service.release_storage]
}
resource "google_storage_bucket_iam_member" "release_storage_public_viewer" {
for_each = local.release_storage_public_grants
bucket = google_storage_bucket.release_storage[each.key].name
role = "roles/storage.objectViewer"
member = "allUsers"
}
resource "google_storage_bucket_iam_member" "release_storage_writer" {
for_each = local.release_storage_writer_grants
bucket = google_storage_bucket.release_storage[each.value.bucket_key].name
role = "roles/storage.objectAdmin"
member = each.value.member
}

View file

@ -0,0 +1,12 @@
manage_google = false
google_project_id = "project-88c23ce9-918a-470a-b33"
google_storage_location = "US"
google_runner_service_account_email = "burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com"
google_release_bucket_name = "burrow-net-releases"
google_package_bucket_name = "burrow-net-packages"
google_nix_cache_bucket_name = "burrow-net-nix-cache"
google_release_public_read = true
google_package_public_read = true
google_nix_cache_public_read = false
google_release_extra_writer_members = []

View file

@ -0,0 +1,81 @@
variable "manage_google" {
description = "Manage Google Cloud release storage resources."
type = bool
default = false
}
variable "google_project_id" {
description = "Google Cloud project id for Burrow release storage."
type = string
default = "project-88c23ce9-918a-470a-b33"
}
variable "google_storage_location" {
description = "Google Cloud Storage bucket location for release, package, and cache backup buckets."
type = string
default = "US"
}
variable "google_runner_service_account_email" {
description = "Forgejo runner service account email allowed to publish release, package, and cache backup objects."
type = string
default = "burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com"
}
variable "google_release_bucket_name" {
description = "GCS bucket for release artifacts served by releases.burrow.net."
type = string
default = "burrow-net-releases"
}
variable "google_package_bucket_name" {
description = "GCS bucket for signed package repositories served by packages.burrow.net."
type = string
default = "burrow-net-packages"
}
variable "google_nix_cache_bucket_name" {
description = "GCS backup bucket for the Garage-backed Burrow Nix cache."
type = string
default = "burrow-net-nix-cache"
}
variable "google_release_public_read" {
description = "Grant allUsers objectViewer on the release artifact bucket."
type = bool
default = true
}
variable "google_package_public_read" {
description = "Grant allUsers objectViewer on the package repository bucket."
type = bool
default = true
}
variable "google_nix_cache_public_read" {
description = "Grant allUsers objectViewer on the Nix cache backup bucket."
type = bool
default = false
}
variable "google_release_extra_writer_members" {
description = "Additional IAM members allowed to write release, repository, and cache backup objects."
type = set(string)
default = []
}
variable "google_storage_cors_origins" {
description = "Allowed origins for public release/package downloads."
type = list(string)
default = [
"https://burrow.net",
"https://releases.burrow.net",
"https://packages.burrow.net",
]
}
variable "tags" {
description = "Additional labels applied to supported Google resources."
type = map(string)
default = {}
}

View file

@ -0,0 +1,12 @@
terraform {
required_version = ">= 1.8.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 5.40.0, < 7.0"
}
}
backend "s3" {}
}