Skip to content

Instantly share code, notes, and snippets.

@pcostesi
Last active August 19, 2021 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcostesi/877171b8985f2113284f8063d57a5a39 to your computer and use it in GitHub Desktop.
Save pcostesi/877171b8985f2113284f8063d57a5a39 to your computer and use it in GitHub Desktop.
Terraforming the Blog
resource "google_cloudbuild_trigger" "site_trigger" {
provider = google-beta
name = "site-trigger"
project = var.project
github {
push {
branch = "master"
}
owner = "pcostesi"
name = "pcostesi.dev"
}
filename = "cloudbuild.yaml"
}
# Global IP, needed for the load balancer (maybe this should go to `routing.tf`)
resource "google_compute_global_address" "static_sites" {
provider = google
name = "static-sites"
count = var.use_cloudflare ? 0 : 1
}
# Managed DNS zone
data "google_dns_managed_zone" "main_site" {
provider = google
name = var.project
count = var.use_cloudflare ? 0 : 1
}
# Bind IP to the DNS
resource "google_dns_record_set" "static_site" {
provider = google
name = "${var.static_site}."
type = "A"
ttl = 300
managed_zone = data.google_dns_managed_zone.main_site[0].name
rrdatas = [google_compute_global_address.static_sites[0].address]
count = var.use_cloudflare ? 0 : 1
}
# Site verification
resource "google_dns_record_set" "static_site_txt" {
provider = google
name = "${var.static_site}."
type = "TXT"
ttl = 300
managed_zone = data.google_dns_managed_zone.main_site[0].name
rrdatas = ["google-site-verification=KNrjsg5IVfr7ivKz94SoZ06U7nTtfOsmuzZRncbXpRI"]
count = var.use_cloudflare ? 0 : 1
}
resource "cloudflare_zone" "main_site" {
zone = var.static_site
count = var.use_cloudflare ? 1 : 0
}
resource "cloudflare_zone_settings_override" "main_site" {
zone_id = cloudflare_zone.main_site[0].id
settings {
ssl = "full"
always_use_https = "on"
automatic_https_rewrites = "on"
}
count = var.use_cloudflare ? 1 : 0
}
resource "cloudflare_record" "static_site" {
zone_id = cloudflare_zone.main_site[0].id
name = "${var.static_site}."
value = "c.storage.googleapis.com"
type = "CNAME"
ttl = 1
proxied = true
count = var.use_cloudflare ? 1 : 0
}
resource "cloudflare_record" "static_site_txt" {
zone_id = cloudflare_zone.main_site[0].id
name = "${var.static_site}."
type = "TXT"
ttl = 300
value = "google-site-verification=${var.google_site_verification}"
count = var.use_cloudflare ? 1 : 0
}
terraform {
required_providers {
google = {
source = "hashicorp/google"
}
google-beta = {
source = "hashicorp/google-beta"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 2.0"
}
}
backend "gcs"{
bucket = "terraform-static-state"
prefix = "blog"
credentials = "../credentials.json"
}
}
provider "google" {
credentials = file(var.credentials)
project = var.project
region = var.region
zone = var.zone
}
provider "google-beta" {
credentials = file(var.credentials)
project = var.project
region = var.region
zone = var.zone
}
provider "cloudflare" {
email = var.email_address
api_key = var.cf_api
}
resource "google_monitoring_notification_channel" "basic" {
display_name = "Main Notification Channel"
type = "email"
project = var.project
provider = google-beta
labels = {
email_address = var.email_address
}
}
resource "google_monitoring_uptime_check_config" "static_site_https" {
provider = google-beta
display_name = "static-site-https-uptime-check"
timeout = "60s"
project = var.project
http_check {
path = "/"
port = "443"
use_ssl = true
validate_ssl = true
}
monitored_resource {
type = "uptime_url"
labels = {
project_id = var.project
host = var.static_site
}
}
}
resource "google_monitoring_alert_policy" "static_site_alert_policy" {
display_name = "Static Site Alert Policy"
combiner = "OR"
conditions {
display_name = "SSL certificate expiring soon"
condition_threshold {
filter = "metric.type=\"monitoring.googleapis.com/uptime_check/time_until_ssl_cert_expires\" AND resource.type=\"uptime_url\""
duration = "600s"
comparison = "COMPARISON_LT"
threshold_value = 15
trigger {
count = 1
}
aggregations {
alignment_period = "1200s"
per_series_aligner = "ALIGN_NEXT_OLDER"
cross_series_reducer = "REDUCE_MEAN"
group_by_fields = ["resource.label.*"]
}
}
}
user_labels = {
"uptime" = "ssl_cert_expiration"
"version" = "1"
}
notification_channels = [ google_monitoring_notification_channel.basic.name ]
}
# Add the bucket as a CDN backend
resource "google_compute_backend_bucket" "static_site" {
provider = google
name = "static-site-backend"
description = "Contains files needed by the website"
bucket_name = google_storage_bucket.static_site.name
enable_cdn = true
depends_on = [google_dns_record_set.static_site_txt]
count = var.use_cloudflare ? 0 : 1
}
# HTTPS certificate
resource "google_compute_managed_ssl_certificate" "static_site" {
provider = google-beta
name = "static-site-cert"
managed {
domains = [google_dns_record_set.static_site[0].name]
}
count = var.use_cloudflare ? 0 : 1
}
# GCP URL MAP (frontend config)
resource "google_compute_url_map" "static_site" {
provider = google
name = "static-site-url-map"
default_service = google_compute_backend_bucket.static_site[0].self_link
count = var.use_cloudflare ? 0 : 1
}
# GCP proxy (load balancer)
resource "google_compute_target_https_proxy" "static_site" {
provider = google
name = "static-site-target-proxy"
url_map = google_compute_url_map.static_site[0].self_link
ssl_certificates = [google_compute_managed_ssl_certificate.static_site[0].self_link]
count = var.use_cloudflare ? 0 : 1
}
# GCP forwarding rule (IP <-> Load Balancer mapping)
resource "google_compute_global_forwarding_rule" "default" {
provider = google
name = "static-site-forwarding-rule"
load_balancing_scheme = "EXTERNAL"
ip_address = google_compute_global_address.static_sites[0].address
ip_protocol = "TCP"
port_range = "443"
target = google_compute_target_https_proxy.static_site[0].self_link
count = var.use_cloudflare ? 0 : 1
}
resource "google_storage_bucket" "static_site" {
name = var.static_site
force_destroy = true
uniform_bucket_level_access = false
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
cors {
origin = ["https://${var.static_site}"]
method = ["GET", "HEAD", "PUT", "POST", "DELETE"]
response_header = ["*"]
max_age_seconds = 3600
}
}
resource "google_storage_default_object_acl" "static_site_read" {
bucket = google_storage_bucket.static_site.name
role_entity = ["READER:allUsers"]
}
variable "project" {
default = "pcostesi-dev"
}
variable "credentials" {
default = "../credentials.json"
}
variable "region" {
default = "us-central1"
}
variable "zone" {
default = "us-central1-c"
}
variable "name" {
default = "main"
}
variable "static_site" {
default = "pcostesi.dev"
}
variable "google_site_verification" {
default = "KNrjsg5IVfr7ivKz94SoZ06U7nTtfOsmuzZRncbXpRI"
}
variable "use_cloudflare" {
default = true
}
variable "email_address" {}
variable "cf_api" {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment