Overview
This page explains how to build a static page site with Google Cloud Storage.
The system includes resources in the following and the structure diagram is below.
- VPC network is to manage network access by a firewall or cloud armor or something.
- Cloud Storage is used to store HTML/CSS/JS static files.
- Load Balancer is to allow access to static pages via your domain.
Prerequisite
- Prepare the Domain to publish static pages
- Register the payment card info or something to Google Platform
NOTE
This system takes a cost for the network transfer
How to build the Static Pages Site
- Enable API
- Set up network
- Create a Bucket of Google Cloud Storage
- Set up a Load balancer to publish pages
1. Enable API
To use the Cloud DNS service and manage the resource by the Tofu or Terraform or something, a developer need to enable the Cloud DNS service.
1// Variable for GCP
2variable "gcp_project" {
3 type = object({
4 project = string // The gcp project name
5 region = string // The region of gcp project
6 })
7}
8
9variable "gcp_services" {
10 type = list(string) // Enabling the service name of api
11}
12
13// Enable APIs
14resource "google_project_service" "api_enable" {
15 for_each = toset(var.gcp_services)
16 project = var.gcp_project.project
17 service = each.value
18}
2. Networking
To expose the static content, set up a VPC network and DNS.
1// VPC Network
2resource "google_compute_network" "content" {
3 name = "content"
4 auto_create_subnetworks = false
5}
6
7
8// DNS zone
9resource "google_dns_managed_zone" "content" {
10 project = var.gcp_project.project
11 name = "content-media"
12 dns_name = local.content_domain
13 description = "Media Service"
14 labels = {
15 domain = "media"
16 }
17}
18
19// DNS A Records
3. Cloud Storage
This part shows how to create Google Cloud Storage to store the static website content files, access control configuration, and network components.
1# Create Cloud Storage Bucket suffix name
2resource "random_id" "bucket_prefix" {
3 for_each = var.buckets
4 byte_length = 16
5}
6
7# Create Cloud Storage Bucket
8resource "google_storage_bucket" "web_content" {
9 depends_on = [random_id.bucket_prefix]
10 for_each = var.buckets
11 location = var.gcp_project.region
12 name = "${random_id.bucket_prefix[each.key].hex}-${each.value.name}"
13 uniform_bucket_level_access = true
14 storage_class = "STANDARD"
15 // delete bucket and contents on destroy.
16 force_destroy = true
17}
18
19# Create Backend Service
20resource "google_compute_backend_bucket" "backend" {
21 depends_on = [google_storage_bucket.web_content]
22 for_each = var.buckets
23 name = format("bsrv-%s", each.value.name)
24 description = "${each.value.name} Static Content Service"
25 bucket_name = google_storage_bucket.web_content[each.key].name
26}
4. Load balancer
This part explains how to set up the network component to allow traffic between the internet and the prepared the content and backend service at previous section.
1resource "google_compute_global_address" "ip" {
2 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "default_service") }
3 name = format("%s_%s_addr", local.resource_base_name, each.key)
4}
5
6resource "google_compute_managed_ssl_certificate" "ssl" {
7 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "default_service") }
8 name = format("%s_%s_ssl", local.resource_base_name, each.key)
9 managed {
10 domains = [local.content_domain]
11 }
12}
13
14resource "google_compute_url_map" "umap" {
15 depends_on = [google_compute_backend_bucket.backend, google_compute_network.content]
16 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "default_service") }
17 name = format("umap-lb-%s", local.resource_base_name)
18 default_service = google_compute_backend_bucket.backend[each.key].id
19
20 host_rule {
21 hosts = [each.value.default_service.domain]
22 path_matcher = each.value.default_service.path_matcher_name
23 }
24
25 path_matcher {
26 name = each.value.default_service.path_matcher_name
27 default_service = google_compute_backend_bucket.backend[each.key].id
28
29 dynamic "path_rule" {
30 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "path_matcher") }
31 content {
32 paths = [path_rule.value.path]
33 service = google_compute_backend_bucket.backend[path_rule.key]
34 }
35 }
36 }
37}
38
39resource "google_compute_target_https_proxy" "proxy" {
40 depends_on = [google_compute_managed_ssl_certificate.ssl]
41 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "default_service") }
42 name = format("%s-%s-https-proxy", local.resource_base_name, each.key)
43 url_map = google_compute_url_map.umap[each.key].id
44 ssl_certificates = [google_compute_managed_ssl_certificate.ssl[each.key].id]
45}
46
47resource "google_compute_global_forwarding_rule" "default" {
48 depends_on = [google_compute_url_map.umap, google_compute_target_https_proxy.proxy]
49 for_each = { for k, v in var.buckets : k => v if contains(keys(v), "default_service") }
50 name = format("%s-%s-https-lb-forwarding", local.resource_base_name, each.key)
51 ip_protocol = "TCP"
52 load_balancing_scheme = "EXTERNAL_MANAGED"
53 port_range = "443"
54 target = google_compute_target_https_proxy.proxy[each.key].id
55 ip_address = google_compute_global_address.ip[each.key].id
56}