initial commit
Signed-off-by: Jason Hall <imjasonh@gmail.com>
This commit is contained in:
commit
4dc1b58f2f
20 changed files with 1398 additions and 0 deletions
19
terraform/backups.tf
Normal file
19
terraform/backups.tf
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
resource "google_storage_bucket" "backups" {
|
||||
name = "${var.project_id}-forgejo-backups"
|
||||
location = var.region
|
||||
storage_class = "STANDARD"
|
||||
uniform_bucket_level_access = true
|
||||
|
||||
lifecycle_rule {
|
||||
condition {
|
||||
age = 30
|
||||
}
|
||||
action {
|
||||
type = "Delete"
|
||||
}
|
||||
}
|
||||
|
||||
versioning {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
9
terraform/dns.tf
Normal file
9
terraform/dns.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
resource "google_dns_record_set" "forgejo" {
|
||||
count = var.manage_dns ? 1 : 0
|
||||
|
||||
name = "${var.domain}."
|
||||
type = "A"
|
||||
ttl = 300
|
||||
managed_zone = var.dns_managed_zone
|
||||
rrdatas = [google_compute_address.forgejo.address]
|
||||
}
|
||||
32
terraform/iam.tf
Normal file
32
terraform/iam.tf
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
resource "google_service_account" "forgejo" {
|
||||
account_id = "forgejo-vm"
|
||||
display_name = "Forgejo VM service account"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "forgejo_secrets" {
|
||||
for_each = toset(["forgejo-secret-key", "forgejo-internal-token"])
|
||||
project = var.project_id
|
||||
secret_id = each.value
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.forgejo.email}"
|
||||
}
|
||||
|
||||
resource "google_storage_bucket_iam_member" "backups_writer" {
|
||||
bucket = google_storage_bucket.backups.name
|
||||
role = "roles/storage.objectAdmin"
|
||||
member = "serviceAccount:${google_service_account.forgejo.email}"
|
||||
}
|
||||
|
||||
resource "google_iap_tunnel_instance_iam_member" "ssh_admin" {
|
||||
project = var.project_id
|
||||
zone = var.zone
|
||||
instance = google_compute_instance.forgejo.name
|
||||
role = "roles/iap.tunnelResourceAccessor"
|
||||
member = "user:${var.admin_email}"
|
||||
}
|
||||
|
||||
resource "google_project_iam_member" "ssh_os_login" {
|
||||
project = var.project_id
|
||||
role = "roles/compute.osLogin"
|
||||
member = "user:${var.admin_email}"
|
||||
}
|
||||
62
terraform/main.tf
Normal file
62
terraform/main.tf
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
resource "google_compute_disk" "forgejo_data" {
|
||||
name = "forgejo-data"
|
||||
type = "pd-standard"
|
||||
size = 20
|
||||
zone = var.zone
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_instance" "forgejo" {
|
||||
name = "forgejo"
|
||||
machine_type = "e2-micro"
|
||||
zone = var.zone
|
||||
tags = ["forgejo"]
|
||||
|
||||
boot_disk {
|
||||
initialize_params {
|
||||
image = "cos-cloud/cos-stable"
|
||||
size = 10
|
||||
type = "pd-standard"
|
||||
}
|
||||
}
|
||||
|
||||
attached_disk {
|
||||
source = google_compute_disk.forgejo_data.id
|
||||
device_name = "forgejo-data"
|
||||
}
|
||||
|
||||
network_interface {
|
||||
network = "default"
|
||||
access_config {
|
||||
nat_ip = google_compute_address.forgejo.address
|
||||
}
|
||||
}
|
||||
|
||||
metadata = {
|
||||
user-data = templatefile("${path.module}/../cloud-init/user-data.yaml.tpl", {
|
||||
domain = var.domain
|
||||
forgejo_image = var.forgejo_image
|
||||
caddy_image = var.caddy_image
|
||||
gcs_backup_bucket = google_storage_bucket.backups.name
|
||||
project_id = var.project_id
|
||||
})
|
||||
google-logging-enabled = "true"
|
||||
cos-update-strategy = "update_enabled"
|
||||
enable-oslogin = "TRUE"
|
||||
}
|
||||
|
||||
service_account {
|
||||
email = google_service_account.forgejo.email
|
||||
scopes = ["cloud-platform"]
|
||||
}
|
||||
|
||||
allow_stopping_for_update = true
|
||||
|
||||
depends_on = [
|
||||
google_secret_manager_secret_iam_member.forgejo_secrets,
|
||||
google_storage_bucket_iam_member.backups_writer,
|
||||
]
|
||||
}
|
||||
32
terraform/network.tf
Normal file
32
terraform/network.tf
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
resource "google_compute_address" "forgejo" {
|
||||
name = "forgejo-ip"
|
||||
region = var.region
|
||||
}
|
||||
|
||||
resource "google_compute_firewall" "https" {
|
||||
name = "allow-https"
|
||||
network = "default"
|
||||
direction = "INGRESS"
|
||||
|
||||
allow {
|
||||
protocol = "tcp"
|
||||
ports = ["80", "443"]
|
||||
}
|
||||
|
||||
source_ranges = ["0.0.0.0/0"]
|
||||
target_tags = ["forgejo"]
|
||||
}
|
||||
|
||||
resource "google_compute_firewall" "iap_ssh" {
|
||||
name = "allow-iap-ssh"
|
||||
network = "default"
|
||||
direction = "INGRESS"
|
||||
|
||||
allow {
|
||||
protocol = "tcp"
|
||||
ports = ["22"]
|
||||
}
|
||||
|
||||
source_ranges = ["35.235.240.0/20"]
|
||||
target_tags = ["forgejo"]
|
||||
}
|
||||
14
terraform/outputs.tf
Normal file
14
terraform/outputs.tf
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
output "static_ip" {
|
||||
value = google_compute_address.forgejo.address
|
||||
description = "Point your domain's A record at this address"
|
||||
}
|
||||
|
||||
output "ssh_command" {
|
||||
value = "gcloud compute ssh forgejo --zone=${var.zone} --tunnel-through-iap"
|
||||
description = "Admin SSH via IAP tunnel"
|
||||
}
|
||||
|
||||
output "backup_bucket" {
|
||||
value = google_storage_bucket.backups.name
|
||||
description = "GCS bucket holding nightly backups"
|
||||
}
|
||||
10
terraform/secrets.tf
Normal file
10
terraform/secrets.tf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Secrets are created out-of-band by scripts/bootstrap-secrets.sh.
|
||||
# This file only declares them as data sources; the IAM bindings live in iam.tf.
|
||||
|
||||
data "google_secret_manager_secret" "secret_key" {
|
||||
secret_id = "forgejo-secret-key"
|
||||
}
|
||||
|
||||
data "google_secret_manager_secret" "internal_token" {
|
||||
secret_id = "forgejo-internal-token"
|
||||
}
|
||||
50
terraform/variables.tf
Normal file
50
terraform/variables.tf
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
variable "project_id" {
|
||||
type = string
|
||||
description = "GCP project ID"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
default = "us-central1"
|
||||
description = "GCP region (use us-west1, us-central1, or us-east1 for the always-free e2-micro)"
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
type = string
|
||||
default = "us-central1-a"
|
||||
description = "GCP zone within region"
|
||||
}
|
||||
|
||||
variable "domain" {
|
||||
type = string
|
||||
description = "Domain name for the Forgejo instance (e.g. git.example.com)"
|
||||
}
|
||||
|
||||
variable "admin_email" {
|
||||
type = string
|
||||
description = "Google account that gets IAP SSH access"
|
||||
}
|
||||
|
||||
variable "forgejo_image" {
|
||||
type = string
|
||||
default = "codeberg.org/forgejo/forgejo:11"
|
||||
description = "Forgejo container image, pinned to a major version"
|
||||
}
|
||||
|
||||
variable "caddy_image" {
|
||||
type = string
|
||||
default = "caddy:2-alpine"
|
||||
description = "Caddy container image, pinned to a major version"
|
||||
}
|
||||
|
||||
variable "manage_dns" {
|
||||
type = bool
|
||||
default = false
|
||||
description = "If true, manage an A record in Cloud DNS. Requires dns_managed_zone."
|
||||
}
|
||||
|
||||
variable "dns_managed_zone" {
|
||||
type = string
|
||||
default = ""
|
||||
description = "Cloud DNS managed zone name (only used when manage_dns = true)"
|
||||
}
|
||||
16
terraform/versions.tf
Normal file
16
terraform/versions.tf
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
terraform {
|
||||
required_version = ">= 1.6"
|
||||
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
zone = var.zone
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue