Google Cloud · Learn by doing

A tiny page.
A new cloud to learn.

Create a learning project, store a public page, and open it over HTTPS. Then rebuild the bucket with Terraform and update the page with Ansible.

Beginner friendlyWindows + LinuxCopyable examplesCloud Storage HTTPS object

These are sample names, not our infrastructure. Before copying commands, read Customize the examples: paths, keys, IPs and names. Substitute your own authorized account and resources. Existing lab? Retain its original resource names, usernames and state; renamed samples can cause replacement. See the existing-lab warning before applying updated recipes.

A bucket, a file, and its HTTPS address

A Google Cloud project is the label on your toy box. Cloud Storage is the box. Each object is a toy with a name. For this lab, the toy is index.html, and its HTTPS address lets anyone read it.

Cloud Storage is the closest storage equivalent to S3 and Azure Blob Storage. It does not run a Windows or Linux server. This lab publishes one static HTML page; it cannot run a backend, database or user login.

Visitor's browserOpens the complete URL
storage.googleapis.comBuilt-in HTTPS endpoint
Public learning bucketHolds index.html
This is an HTTPS object address, not a full website front end. Use https://storage.googleapis.com/BUCKET/index.html, including the filename. It does not automatically provide a home page at a custom domain or directory-style website routing.

A full Cloud Storage website with a custom domain and HTTPS uses an HTTPS load balancer and certificate setup. That adds resources and potentially ongoing costs. We leave it out of this first inexpensive lab and explain it as a later service lesson.

Every file in this dedicated bucket will be public under the supplied policy, and object names can be listed. Store only the example page here. Terraform state, keys, screenshots and personal documents must stay outside it.

Google: HTTPS object endpointsFull website hosting architecturePublic data permissions

1. Open an account and a learning project

  1. Visit Google Cloud Free and sign in with a Google account you control. Enable two-step verification. Complete the eligibility and payment verification steps shown.
  2. Eligible new users can receive $300 Welcome credit for 90 days. Check your own credit balance and expiry in Billing. Trial restrictions apply; credits are not a permanent hosting allowance.
  3. A Free Trial account is not charged during the trial. Upgrading to paid billing allows charges beyond applicable credits and free allowances. Read the upgrade terms; do not upgrade just to make an unrelated tutorial work.
  4. Create a project such as Guidewell Learning and link it to your trial billing account. The display name is friendly; the project ID is unique and used by commands. Avoid personal information in IDs.
  5. Use a dedicated project for the manual and code versions of this lab. Do not put other workloads there. Your billing account can pay for multiple projects, so a project is not a separate credit wallet.

Google: signup and trial rulesTrial and free-service allowances

Choose the right access

The identity running this bucket lab needs Storage Admin on the learning project to create buckets and set their IAM policy, plus Service Usage Consumer for the project used by application credentials. An authorized project administrator can assign those roles in IAM. Enabling APIs or billing may need an administrator too.

Storage Admin covers all buckets in that project, so use it only for this isolated exercise. After setup, a content-only uploader can use a narrower object role on the specific bucket. Do not grant visitors Storage Admin; visitors receive only Storage Object Viewer.

Ready: two-step verification is enabled; your project is linked to the intended billing account; you know the project ID and trial expiry.

2. Watch the whole project, not just the bucket

A budget is a kitchen timer. It can ring when you reach a threshold, but it does not switch off the oven.

  1. Open Billing → Budgets & alerts → Create budget. Scope a monthly $5 budget to your learning project. Add actual-spend alerts at 50%, 80% and 100%, and a forecast alert if offered.
  2. Inspect the budget's credit filters. Exclude promotional credits if you want to see underlying usage even while trial credit covers the bill. Also inspect the separate trial credit balance.
  3. Keep billing emails enabled and check reports after every lab. A budget does not cap spend and reporting is delayed.
  4. Choose regional Standard storage in us-central1. Keep one tiny HTML page, no large downloads, no traffic generators and only a few test visits.
  5. For this disposable lab, disable object versioning and soft-delete retention if project policy allows it. The Terraform example sets retention to zero. Keep a local copy before changing retention or deleting content.
  6. Skip load balancers, Cloud CDN, custom domains, virtual machines and optional logging destinations for now. Those are separate services with separate costs.

Free storage allowances have location, usage and account restrictions. Do not assume a service is free because you can create it. In the pricing calculator try 0.01 GB of Standard regional storage, 1,000 reads, 100 writes and 0.1 GB outgoing data per month; inspect the chosen region and destination. These are estimates, not usage limits.

Google: budgets are alerts, not capsCloud Storage pricingGoogle Cloud calculatorSoft-delete storage retention

3. Build once in the console

A. Save a public example page

Save this as UTF-8 index.html. On Windows choose “All files” in Notepad; make sure it is not index.html.txt. The page has no external images or scripts, so there are no extra hosting dependencies.

B. Create a bucket for public content

  1. In the Google Cloud console, select your learning project. Open Cloud Storage → Buckets → Create.
  2. Use a unique name such as contoso-lab-blue-kite-7f3a-manual. Choose Region → us-central1, Standard storage and uniform bucket-level access. Do not use personal information in the name.
  3. For this intentionally public learning bucket, do not enforce Public Access Prevention at bucket level. If an organization/project policy enforces it, stop; use a permitted sandbox or keep the bucket private. Do not weaken your organization's policy to follow this guide.
  4. Disable object versioning and soft-delete retention for these disposable files if permitted. Keep Google-managed encryption. Create the bucket.
  5. Upload only index.html at the bucket root. Set Content-Type to text/html; charset=utf-8 and Cache-Control to public, max-age=60 in object metadata.
  6. Open the bucket's Permissions tab, grant principal allUsers the role Storage Object Viewer, and review the public-access warning before saving. This allows anyone to read and list this bucket's objects.
  7. Open https://storage.googleapis.com/YOUR-BUCKET/index.html in a private/signed-out browser. Do not use storage.cloud.google.com, which is a different authenticated endpoint.
Prove it: a signed-out browser displays the page over HTTPS. Do not expect a custom domain or omission of index.html to behave like the Azure or AWS lab.

Google: public-read setupPublic Access Prevention

4. Windows and Linux setup

Install the Google Cloud CLI for Windows and Terraform using official instructions. Open a new PowerShell window. Install Ubuntu in WSL for Ansible using administrator PowerShell, then finish Ubuntu's initial setup.

PowerShell · tool checks / WSL installation
gcloud version
terraform version
wsl --install -d Ubuntu

Use an empty local Terraform folder such as C:\Labs\contoso-gcp. For Ansible, place the playbook and HTML together in Ubuntu, for example ~/contoso-gcp-ansible. Install gcloud inside Ubuntu and sign in there too; Windows login sessions are separate from WSL sessions.

Two logins, two jobs

gcloud auth login lets the CLI upload files. gcloud auth application-default login supplies Application Default Credentials (ADC) for Terraform. These are separate credential stores. Both can use your interactive sign-in without downloading service-account keys.

PowerShell or Linux · sign in to the learning project
gcloud auth login
gcloud config set project YOUR-PROJECT-ID
gcloud auth application-default login
gcloud auth application-default set-quota-project YOUR-PROJECT-ID
gcloud services enable storage.googleapis.com --project YOUR-PROJECT-ID
gcloud config get-value project

Replace every project placeholder. An authorized administrator must enable the API if your identity cannot. Keep the ADC files outside your project and source control; never upload them to the bucket.

Google: Terraform authenticationApplication Default CredentialsWSL setup

5. Write the bucket recipe in Terraform

Terraform builds the box and attaches a “public reading” label. The page itself is added afterward.

This creates another bucket with a different name in your existing learning project. It does not import the manual bucket, create a project or set up billing. Review the public-read IAM change carefully before applying it.

Save main.tf beside your local index.html. This configuration uses regional Standard storage, uniform permissions and zero soft-delete retention. Public Access Prevention is inherited, so an enforced organization policy can still block the public grant.

Create terraform.tfvars using your real project ID and a new globally unique bucket name. Save .gitignore before committing anything.

terraform.tfvars
project_id  = "YOUR-PROJECT-ID"
bucket_name = "contoso-lab-blue-kite-7f3a-code"
PowerShell or Linux · review then build
terraform init
terraform fmt
terraform validate
terraform plan -out=lab.tfplan
# Review the new bucket and deliberate allUsers object-viewer grant.
terraform apply lab.tfplan
terraform output

The saved plan applies without another confirmation prompt. Keep state and saved plans private. Keep the generated lockfile so later runs use the same provider version. Do not upload any Terraform files as website content.

PowerShell · upload the first page
$labBucket = terraform output -raw bucket_name
gcloud storage cp ./index.html "gs://$labBucket/index.html" --content-type 'text/html; charset=utf-8' --cache-control 'public, max-age=60'
terraform output -raw site_url
Prove it: the output HTTPS URL displays index.html. Run terraform plan again; without infrastructure edits, expect no changes.

Terraform: bucket resourceTerraform: bucket IAMgcloud upload flags

6. Let Ansible publish your edit

Use Ubuntu, including WSL on Windows. Terraform owns the bucket and permissions; Ansible owns the page upload. This example uses Ansible's built-in command module and your existing gcloud login, so no Google service-account key is needed.

Ubuntu / WSL · install the toolbox
sudo apt update
sudo apt install -y python3 python3-venv
python3 -m venv ~/.venvs/contoso-gcp
source ~/.venvs/contoso-gcp/bin/activate
python -m pip install ansible-core
gcloud auth login
gcloud config set project YOUR-PROJECT-ID

Save this playbook beside index.html. Change a sentence, then pass the bucket name from Terraform's output. The playbook publishes only that one file.

Ubuntu / WSL · publish
ansible-playbook update-site.yml --syntax-check
ansible-playbook update-site.yml -e 'bucket_name=contoso-lab-blue-kite-7f3a-code'

This intentionally uploads every run and reports a change, even if the file is identical. It does not compare remote contents. Ansible --check is not a reliable upload preview for this command task. File-comparison logic can be a later automation lesson.

Prove it: wait for the previous cache lifetime, refresh the complete HTTPS URL and see your edit. Terraform still reports no infrastructure changes.

Ansible: command module

7. Clean up the buckets and credentials

The manual copy

In Cloud Storage, verify the exact manual bucket name, remove its objects and delete the bucket. These steps permanently remove this lab's content because retention was disabled. Keep the HTML locally first.

The Terraform copy

Terraform refuses to delete a nonempty bucket in this example. Print the exact bucket name, verify that it belongs to this disposable lab, then remove its objects before destroying the infrastructure. The recursive command deletes every object in that bucket.

PowerShell · remove only the code lab
$labBucket = terraform output -raw bucket_name
$labBucket
# Stop if the name is not your disposable contoso-lab- bucket.
gcloud storage rm --recursive "gs://$labBucket/**"
terraform plan -destroy -out=cleanup.tfplan
# Read the deletions before applying.
terraform apply cleanup.tfplan

If the bucket is already empty, skip the object deletion and proceed with the destroy plan. If you enabled versioning or retention outside this guide, inspect retained versions and policies; do not assume this command removes every retained copy.

PowerShell or Linux · revoke local sessions after cleanup
gcloud auth application-default revoke
gcloud auth revoke
  1. Confirm both buckets are gone and no load balancers, reserved addresses or other experiments remain.
  2. If the project was created exclusively for this lab and is now empty, you may shut it down in the console. Terraform here does not manage the project; do not shut down a shared project or billing account.
  3. Remove temporary role grants if appropriate, keep budget alerts and inspect Billing after usage data catches up. Cleanup does not erase earlier charges.

When something goes wrong

SymptomTry this
Public grant rejectedCheck Public Access Prevention and organization sharing constraints. Use an authorized sandbox; do not bypass them.
Terraform cannot authenticateRenew application-default login in the environment running Terraform; the CLI's auth login is separate.
Quota-project errorCheck Service Usage Consumer on the intended project and set the ADC quota project.
Page returns 403Confirm the exact bucket, allUsers object-viewer grant and signed-out URL. Allow time for permissions to propagate.
Page downloads instead of displayingRe-upload with text/html content type. Include index.html in the URL.
Old page appearsWait for the previous cache lifetime, refresh and check which bucket received the upload.
Destroy says not emptyInspect the exact bucket, remaining objects and any retained versions before retrying.

You have now compared storage, account boundaries, identity, HTTPS delivery and automation across AWS, Azure and Google Cloud.