Hide
Cloud Storage

Configuring a Bucket as a Website

This topic describes how you can configure a Google Cloud Storage bucket as a static website. Static web pages can contain client-side technologies such as HTML, CSS, and JavaScript.

If you are looking to host static assets for a dynamic website hosted, for example, in Google App Engine or in Google Compute Engine, you can also follow the steps here. For more information, see Hosting static assets for a dynamic website.

In this tutorial, we'll use the domain example.com. You can follow the steps using an existing domain that you own or manage, or you can register a new domain.

Contents

  1. Prerequisites
  2. Step 1: Verify you own or manage the domain
  3. Step 2: Create a CNAME record
  4. Step 3: Create a bucket and add content
  5. Step 4: Configure an index page and a custom error page
  6. Step 5: Test the website
  7. Troubleshooting a bucket configured as a website
  8. Tips for working with a bucket configured as a website

Prerequisites

Before configuring a bucket as a website, we recommend that:

Step 1: Verify you own or manage the domain

To demonstrate that you are an owner or manager of a domain, use the Google Webmaster Tools verification process. The Webmaster Tools verification process provides a number of ways to demonstrate ownership of a site or domain. For more information, see Bucket Name Verification

If you own the domain you are associating to a bucket, then you may have already performed this step. If you just created a new domain, then you will have to verify it.

If you try to create the bucket before you verify the domain, you'll receive a warning that you'll need to verify the domain.

Step 2: Create a CNAME record

In this step, you will configure your DNS records to provide a CNAME alias to c.storage.googleapis.com. A CNAME alias is a DNS record that lets you use a URL from your own domain to access resources (bucket and objects) in Google Cloud Storage using your custom domain URL. For example, for example.com, the CNAME record contains the following information:

NAME                  TYPE     DATA
www                   CNAME    c.storage.googleapis.com

SSL is not currently supported. You can only use a CNAME redirect with HTTP, not with HTTPS. Therefore, you should serve content from your bucket that does not contain sensitive or private data. For more information about CNAME redirects, see URI for CNAME aliasing.

Your domain registration service should have a way that you can administer your domain, including adding a CNAME record.

If you are using Google Cloud DNS to publish and manage DNS records, then:

  1. Follow the steps in Getting started with Google Cloud DNS and create a managed zone for your domain.
  2. Within the zone, create a CNAME DNS record that points to c.storage.googleapis.com.
  3. Use the list of name servers hosting your managed zone to update the NS records for the domain with your registrar. For more information, see Updating your domain's name servers.

Step 3: Create a bucket and add content

Create a bucket with a name that matches the CNAME you created for your domain. For example, if you registered example.com, verified the domain, and then added a CNAME record pointing www.example.com to c.storage.googleapis.com, then create the bucket with the name "www.example.com".

Add objects to the bucket that will be the content served for your website. For example, you can use the Google Developers Console or gsutil. If you are migrating an existing website or a large number of files, use gsutil rsync to move your content, which has an -R option to recursively copy directory trees. For example, to synchronize a local directory local-dir of web content with a bucket, you can use:

gsutil rsync -R local-dir gs://www.example.com

The following example shows a bucket with two objects "index.html" and "404.html" as they appear in the Developers Console:

Bucket website example.
Example of a bucket configured as a website.

For objects in the bucket that you want to serve, share those objects publicly. For an example of how to do this in the Google Developers Console, see Sharing Data Publicly. You can also share multiple objects publicly using gsutil acl ch as follows:

gsutil acl ch -u AllUsers:R gs://www.example.com/index.html gs://www.example.com/404.html

Step 4: Configure an index page and a custom error page

The index page (also called the webserver directory index), for a static website served from a Google Cloud Storage bucket, is the object returned when a site visitor requests the top level directory, (e.g., http://www.example.com) instead of an actual object in the bucket. You can configure an index page and a custom error page by configuring the Website Configuration for the bucket. By setting the Website Configuration of a bucket, you can improve the experience of site visitors to your website.

The Website Configuration of a bucket involves setting the following properties:

MainPageSuffix

Specifies the object to serve when just the domain name is requested, for example, if a site visitor requests http://www.example.com or http://www.example.com/ (with the trailing slash).

The MainPageSuffix will only affect requests directed to CNAME aliases of c.storage.googleapis.com. For example, only requests to www.example.com will show the index page. This preserves existing API behavior, such as bucket listing, for requests using a Google Cloud Storage domain. For more information, see Listing objects for a bucket configured as a static website.

NotFoundPage

Specifies the object to serve when site visitors request a resource that does not exist.

The NotFoundPage applies regardless of the implied directory structure of the object. For example, requests for the following nonexistent objects www.example.com/missing.html and www.example.com/dir1/dir2/missing.html return NotFoundPage, if it is configured. See Test the website for more examples.


In the following examples, we use www.example.com. Substitute your domain name in the commands and code. We show how to set website configuration with gsutil, the JSON API via the Java client library, and the XML API. For a list of other client libraries you can use to access Google Cloud Storage, see Overview of Client Libraries for Google Cloud Storage.

To set website configuration:

Developers Console

  1. In the Developers Console, select Storage > Storage browser to see a list of buckets.
  2. Click the more actions More actions icon. next to the bucket and select Edit website configuration.
  3. In the Configure website dialog specify the Main Page and the 404 (Not Found) Page.
  4. Click Save.

gsutil

Uses the gsutil tool.

The following command sets the MainPageSuffix property to "index.html" and the NotFoundPage property to "404.html".

gsutil web set -m index.html -e 404.html gs://www.example.com

Setting website config on gs://www.example.com/...

JSON API via Java

Uses the Java client library.

The following code sample sets the MainPageSuffix property to "index.html" and the NotFoundPage property to "404.html".

Website websiteConfig = new Website().setMainPageSuffix("index.html").setNotFoundPage("404.html");
Bucket patchContent = new Bucket().setWebsite(websiteConfig);
Patch bucket = client.buckets().patch("www.example.com", patchContent);
System.out.println("Website configuration: " + bucket.getJsonContent());

The output from the sample code above is:

Website configuration: {website={mainPageSuffix=index.html, notFoundPage=404.html}}

XML API

Uses the XML API.

Buckets are configured using PUT Bucket requests with the query parameter websiteConfig and an XML body describing the two properties MainPageSuffix and NotFoundPage.

PUT http://storage.googleapis.com/www.example.com?websiteConfig HTTP/1.1
Host: storage.googleapis.com
Content-Length: 156
Authorization: Bearer 1/zVNpoQNsOSxZKqOZgckhpQ

<WebsiteConfiguration>
  <MainPageSuffix>index.html</MainPageSuffix>
  <NotFoundPage>404.html</NotFoundPage>
</WebsiteConfiguration>

To get website configuration:

Developers Console

  1. In the Developers Console, select Storage > Storage browser to see a list of buckets.
  2. Click the more actions More actions icon. next to the bucket and select Edit website configuration.
  3. In the Configure website dialog you can view and change the Main Page and the 404 (Not Found) Page.
  4. If you made changes, click Save.

gsutil

The following command gets the website configuration.

gsutil web get gs://www.example.com

{"notFoundPage": "404.html", "mainPageSuffix": "index.html"}

JSON API via Java

To get the website configuration use:

Bucket bucket = client.buckets().get("www.example.com").execute();
System.out.println("Website configuration: " + bucket.getWebsite());

The output from the sample code above is:

Website configuration: {"mainPageSuffix":"index.html","notFoundPage":"404.html"}

XML API

To read a bucket configuration you use the GET Bucket method with the websiteConfig query parameter.

GET http://storage.googleapis.com/www.example.com?websiteConfig HTTP/1.1
Host: storage.googleapis.com
Content-Length: 0
Authorization: Bearer  ya29.1.AADtN_WObQo0sp50vPJRiuscdtHmpSjOCLhk_4E9rUPsI766udLdOpJkbPZQ4gxBHfPjEvDLuUE

The output from the above request will look like the following:

<?xml version='1.0' encoding='UTF-8'?>
<WebsiteConfiguration>
  <MainPageSuffix>index.html</MainPageSuffix>
  <NotFoundPage>404.html</NotFoundPage>
</WebsiteConfiguration>

To remove website configuration:

Developers Console

  1. In the Developers Console, select Storage > Storage browser to see a list of buckets.
  2. Click the more actions More actions icon. next to the bucket and select Edit website configuration.
  3. In the Configure website dialog clear the values in the Main Page and the 404 (Not Found) Page fields.

    Removing both values, removes website configuration for the bucket.

  4. Click Save.

gsutil

To remove website configuration, you can use the set subcommand with no flags:

gsutil web set gs://www.example.com

JSON API via Java

To remove website configuration, set the website configuration with no properties.

Website websiteConfig = new Website();
Bucket patchContent = new Bucket().setWebsite(websiteConfig);
Patch bucket = client.buckets().patch("www.example.com", patchContent);
System.out.println("Website configuration: " + bucket.getJsonContent());

The output from the sample code above is:

Website configuration: {website={}}

XML API

To disable website configuration properties, exclude the corresponding properties. The following example disables both the MainPageSuffix and NotFoundPage properties.

PUT http://storage.googleapis.com/www.example.com?websiteConfig HTTP/1.1
Host: storage.googleapis.com
Content-Length: 69
Authorization: Bearer 1/zVNpoQNsOSxZKqOZgckhpQ

<WebsiteConfiguration>
</WebsiteConfiguration>

Step 5: Test the website

Test that content is served from the bucket by requesting the domain name in a browser, either with a path to an object, or if you set the MainPageSuffix property, with just the domain name.

Example website configuration scenarios

Suppose a bucket www.example.com has been configured as a website with the following settings and files:

  • MainPageSuffix = "index.html"
  • NotFoundPage = "404.html"
  • The bucket contains three publicly shared objects: "index.html", "404.html", and "dir/index.html".

The following table shows the content served for selected URLs:

URL Requested Content Served
http://www.example.com
http://www.example.com/
http://www.example.com/index.html
The object "index.html".
http://www.example.com/hello
http://www.example.com/dir/
The object "404.html". Note that "http://www.example.com/dir/" doesn't return the object "dir/index.html" because webserver directory index behavior applies only at the top level directory of the website.
http://www.example.com/dir/index.html The object "dir/index.html".

If the website is configured instead as:

  • MainPageSuffix = "main.html"
  • NotFoundPage = "404.html"
  • The bucket contains two publicly shared objects: "main.html" and "404.html".

The following table shows the content served for selected URLs:

URL Requested Content Served
http://www.example.com
http://www.example.com/
The object "main.html".
http://www.example.com/index.html The object "404.html".

If an object is shared publicly (e.g., the index.html object), you can also view that object with the URL http://storage.googleapis.com/www.example.com/index.html. For more information about working with publicly accessible data, see Accessing Public Data.

Troubleshooting a bucket configured as a website

Access denied

If you get the following message for a web page served by your website:

<Error>
<Code>AccessDenied</Code>
<Message>Access denied.</Message>
</Error>

Check that the object is shared publicly. For an example of how to do this in Google Developers Console, see Sharing Data Publicly.

If you uploaded an object (e.g., index.html), marked it as shared publicly, and then upload a new version of it, then you must reshare the object publicly because that permission is overwritten with the new upload.

Users are prompted to download content

If you specify a MainPageSuffix as an object that does not have a web content type, then instead of serving the page, site visitors will be prompted to download the content. For example, if you specify the MainPageSuffix property equal to an object named "index" (no extension), then site visitors will be prompted to download the content.

Tips for working with a bucket configured as a website

Adding subdomains

Suppose you want to also serve content from test.example.com, from a bucket different than the bucket serving content for www.example.com. You can do this by adding:

  • A new bucket test.example.com. Because you already verified the domain example.com, you can create buckets to support subdomains, without verification.
  • A new CNAME record for the subdomain.
    NAME                  TYPE     DATA
    test                  CNAME    c.storage.googleapis.com
    

The following example shows what the subdomain bucket looks like in the Google Developers Console.

Bucket website subdomain example.
Example of a bucket configured for a website subdomain.

If you want the test.example.com to serve the same content as is served from www.example.com, add a CNAME record that aliases "test" to "www". A separate bucket is not needed in this scenario.

Setting cache parameters

You can specify metadata on your website assets to control how or if they are cached by configuring cache control headers. You can specify cache control headers only for objects that are accessible to all anonymous users, which the public objects for a static website served from a Google Cloud Storage bucket must be. If an object is accessible to all anonymous users and you do not specify a cache control setting, Google Cloud Storage applies a cache control setting of 3600 seconds. Google Cloud Storage sets the cache control to private for any object that is not publicly accessible. For examples, see the setmeta subcommand of gsutil and the cache control header.

Listing objects

Website configurations are only used to interpret requests where the hostname is a custom domain, for example www.example.com. This preserves existing API behavior for requests to Google Cloud Storage domains, for example storage.googleapis.com/www.example.com. Thus you can continue to list the www.example.com bucket as you would normally list buckets.

gsutil

gsutil ls gs://www.example.com

gs://www.example.com/404.html
gs://www.example.com/index.html

JSON API via Java

List listObjects = client.objects().list("www.example.com");
Objects objects = listObjects.execute();
System.out.println("Bucket listing: ");
for (StorageObject object : objects.getItems()) {
    System.out.println(object.getName());
}

The output from the sample code above will look like the following:

Bucket listing:
404.html
index.html

XML API

GET http://storage.googleapis.com/www.example.com HTTP/1.1
Host: storage.googleapis.com
Content-Length: 0
Authorization: Bearer ya29.1.AADtN_WObQo0sp50vPJRiuscdtHmpSjOCLhk_4E9rUPsI766udLdOpJkbPZQ4gxBHfPjEvDLuUE

Hosting static assets for a dynamic website

You can use a Google Cloud Storage to host static assets for a dynamic website hosted, for example, in Google App Engine or in Google Compute Engine. Some benefits of hosting your static assets, like images or Javascript files, in a bucket include:

  • Google Cloud Storage behaves essentially like a Content Delivery Network (CDN) with no work on your part because publicly readable objects are, by default, cached in the Google Cloud Storage network.
  • Bandwidth charges for accessing content will typically cost less with Google Cloud Storage.
  • The load on your web servers is lessened when serving the static content from Google Cloud Storage.

You can also control caching for your publicly readable static assets (e.g., disable caching or set cache lifetime) by using cache control request headers. For more information, see Setting cache parameters.

When hosting static assets for a dynamic website, you do not need to create a CNAME record and point to a bucket with the same name as you do for a static website. For example, you could have a bucket named www_example_com_assets with appropriate assets configured as shared publicly and then access those assets using the Google Cloud Storage domain. For example, suppose you have the JavaScript file library.js in the bucket www_example_com_assets that is shared publicly, then you can access it as http://storage.googleapis.com/www_example_com_assets/library.js.

Bucket serving static assets.
Example of a bucket serving static assets.

Monitor your storage charges

If you are serving assets, either as a bucket configured as a static website, or serving static assets from a bucket for a dynamic website hosted outside of Google Cloud Storage, you should monitor the charges to your project that contains the bucket. Serving content will incur storage costs for hosting the content (GB/Month), network egress (per GB), and retrieval operations (Class B). See the Google Cloud Storage pricing page for more details.

The simple pricing example on the pricing page can be used as an approximation for the use case of a low-traffic, static website. You can get a detailed breakdown of your project costs on the billing page of Google Developers Console

Using the JavaScript API

You can test client script in your website and explore using Google Cloud Storage from Javascript by trying the Google Cloud Storage JavaScript Example. The example shows you how to perform common bucket operations using the JavaScript API. You can use the example code in a page in your static website. In the example, make sure you set the Redirect URIs and Javascript Origins of the Client ID you use to include your domain.