Host a static website

This page describes how to configure a Cloud Storage bucket to host a static website for a domain you own. Static web pages can contain client-side technologies such as HTML, CSS, and JavaScript. They cannot contain dynamic content such as server-side scripts like PHP.

Overview

Because Cloud Storage doesn't support custom domains with HTTPS on its own, this tutorial uses Cloud Storage with an external Application Load Balancer to serve content from a custom domain over HTTPS. For more ways to serve content from a custom domain over HTTPS, see troubleshooting for HTTPS serving. You can also use Cloud Storage to serve custom domain content over HTTP, which doesn't require a load balancer.

For examples and tips on static web pages, including how to host static assets for a dynamic website, see the Static Website page.

The instructions in this tutorial describe how to perform the following steps:

  • Upload and share your site's files.

  • Set up a load balancer and SSL certificate.

  • Connect your load balancer to your bucket.

  • Point your domain to your load balancer using an A record.

  • Test the website.

Pricing

The instructions in this tutorial use the following billable components of Google Cloud:

See the Monitoring your charges tip for details on what charges may be incurred when hosting a static website.

Access to bucket data

You can host a static website using a bucket whose objects are readable to the public. To host a static website using Cloud Storage, you can use any of the following methods:

The instructions in this tutorial show you how to make the data of an existing bucket public.

Before you begin

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Enable the Compute Engine API for your project.
  7. Have the following Identity and Access Management roles: Storage Admin and Compute Network Admin.
  8. Have a domain that you own or manage. If you don't have an existing domain, there are many services through which you can register a new domain, such as Cloud Domains.

    This tutorial uses the domain example.com.

  9. Have a few website files you want to serve. This tutorial works best if you have at least an index page (index.html) and a 404 page (404.html).
  10. Have a Cloud Storage bucket for storing the files you want to serve. If you don't currently have a bucket, create a bucket.
  11. (Optional) If you want your Cloud Storage bucket to have the same name as your domain, you must verify that you own or manage the domain that you will be using. Make sure you are verifying the top-level domain, such as example.com, and not a subdomain, such as www.example.com. If you purchased your domain through Cloud Domains, verification is automatic.

Upload your site's files

Add the files you want your website to serve to the bucket:

Console

  1. In the Google Cloud console, go to the Cloud Storage Buckets page.

    Go to Buckets

  2. In the list of buckets, click the name of the bucket that you created.

    The Bucket details page opens with the Objects tab selected.

  3. Click the Upload files button.

  4. In the file dialog, browse to the desired file and select it.

After the upload completes, you should see the filename along with file information displayed in the bucket.

To learn how to get detailed error information about failed Cloud Storage operations in the Google Cloud console, see Troubleshooting.

Command line

Use the gcloud storage cp command to copy files to your bucket. For example, to copy the file index.html from its current location Desktop to the bucket my-static-assets:

gcloud storage cp Desktop/index.html gs://my-static-assets

If successful, the response looks like the following example:

Completed files 1/1 | 164.3kiB/164.3kiB

Client libraries

C++

For more information, see the Cloud Storage C++ API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, see Set up authentication for client libraries.

namespace gcs = ::google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& file_name,
   std::string const& bucket_name, std::string const& object_name) {
  // Note that the client library automatically computes a hash on the
  // client-side to verify data integrity during transmission.
  StatusOr<gcs::ObjectMetadata> metadata = client.UploadFile(
      file_name, bucket_name, object_name, gcs::IfGenerationMatch(0));
  if (!metadata) throw std::move(metadata).status();

  std::cout << "Uploaded " << file_name << " to object " << metadata->name()
            << " in bucket " << metadata->bucket()
            << "\nFull metadata: " << *metadata << "\n";
}

C#

For more information, see the Cloud Storage C# API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, see Set up authentication for client libraries.


using Google.Cloud.Storage.V1;
using System;
using System.IO;

public class UploadFileSample
{
    public void UploadFile(
        string bucketName = "your-unique-bucket-name",
        string localPath = "my-local-path/my-file-name",
        string objectName = "my-file-name")
    {
        var storage = StorageClient.Create();
        using var fileStream = File.OpenRead(localPath);
        storage.UploadObject(bucketName, objectName, null, fileStream);
        Console.WriteLine($"Uploaded {objectName}.");
    }
}

Go

For more information, see the Cloud Storage Go API reference documentation.

To authenticate to Cloud Storage, set up Application Default Credentials. For more information, see Set up authentication for client libraries.

import (
	"context"
	"fmt"
	"io"
	"os"
	"time"

	"cloud.google.com/go/storage"
)

// uploadFile uploads an object.
func uploadFile(w io.Writer, bucket, object string) error {
	// bucket := "bucket-name"
	// object := "object-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

	// Open local file.
	f, err := os.Open("notes.txt")
	if err != nil {
		return fmt.Errorf("os.Open: %w", err)
	}
	defer f.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*50)
	defer cancel()

	o := client.Bucket(bucket).Object(object)

	// Optional: set a generation-match precondition to avoid potential race
	// conditions and data corruptions. The request to upload is aborted if the
	// object's generation number does not match your precondition.
	// For an object that does not yet exist, set the DoesNotExist precondition.
	o = o.If(storage.Conditions{DoesNotExist: true})
	// If the live object already exists in your bucket, set instead a
	// generation-match precondition using the live object's generation number.
	// attrs, err := o.Attrs(ctx)
	// if err != nil {
	// 	return fmt.Errorf("object.Attrs: %w", err)
	// }
	// o = o.If(storage.Conditions{GenerationMatch: attrs.Generation})

	// Upload an object with storage.Writer.
	wc := o.NewWriter(ctx)
	if _, err = io.Copy(wc, f); err != nil