Deploy Firebase Hosting Sites on GCP

The gcp:firebase/hostingSite:HostingSite resource, part of the Pulumi Google Cloud provider, provisions Firebase Hosting sites that serve web content at Firebase-managed URLs. This guide focuses on three capabilities: default site provisioning, additional site creation, and web app integration.

Hosting sites belong to Firebase projects and may reference web apps for SDK integration. The examples are intentionally small. Combine them with your own domain configuration and deployment workflows.

Create a site matching your project ID

Firebase projects automatically provision a default hosting site when you enable Firebase Hosting, using your project ID as the site identifier.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.HostingSite("default", {
    project: "my-project-name",
    siteId: "my-project-name",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.HostingSite("default",
    project="my-project-name",
    site_id="my-project-name")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("my-project-name"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.HostingSite("default", new()
    {
        Project = "my-project-name",
        SiteId = "my-project-name",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new HostingSite("default", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("my-project-name")
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: my-project-name

The siteId property must match your project ID for the default site. Firebase constructs the URL as https://{siteId}.web.app, making your primary application accessible at a predictable address. The defaultUrl output provides the full URL after creation.

Create an additional site without a web app

Projects often need multiple hosting sites for staging environments, feature branches, or separate applications.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.HostingSite("default", {
    project: "my-project-name",
    siteId: "site-no-app",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.HostingSite("default",
    project="my-project-name",
    site_id="site-no-app")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("site-no-app"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.HostingSite("default", new()
    {
        Project = "my-project-name",
        SiteId = "site-no-app",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new HostingSite("default", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("site-no-app")
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: site-no-app

The siteId property sets a globally unique identifier that becomes part of the Firebase-provisioned subdomain. Sites without an appId provide hosting infrastructure without Firebase SDK integration, suitable for static content or applications that don’t use Firebase services.

When your hosted application uses Firebase services like Authentication or Firestore, linking the site to a web app enables SDK configuration.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.WebApp("default", {
    project: "my-project-name",
    displayName: "Test web app for Firebase Hosting",
});
const full = new gcp.firebase.HostingSite("full", {
    project: "my-project-name",
    siteId: "site-with-app",
    appId: _default.appId,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.WebApp("default",
    project="my-project-name",
    display_name="Test web app for Firebase Hosting")
full = gcp.firebase.HostingSite("full",
    project="my-project-name",
    site_id="site-with-app",
    app_id=default.app_id)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := firebase.NewWebApp(ctx, "default", &firebase.WebAppArgs{
			Project:     pulumi.String("my-project-name"),
			DisplayName: pulumi.String("Test web app for Firebase Hosting"),
		})
		if err != nil {
			return err
		}
		_, err = firebase.NewHostingSite(ctx, "full", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("site-with-app"),
			AppId:   _default.AppId,
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.WebApp("default", new()
    {
        Project = "my-project-name",
        DisplayName = "Test web app for Firebase Hosting",
    });

    var full = new Gcp.Firebase.HostingSite("full", new()
    {
        Project = "my-project-name",
        SiteId = "site-with-app",
        AppId = @default.AppId,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.WebApp;
import com.pulumi.gcp.firebase.WebAppArgs;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new WebApp("default", WebAppArgs.builder()
            .project("my-project-name")
            .displayName("Test web app for Firebase Hosting")
            .build());

        var full = new HostingSite("full", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("site-with-app")
            .appId(default_.appId())
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:WebApp
    properties:
      project: my-project-name
      displayName: Test web app for Firebase Hosting
  full:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: site-with-app
      appId: ${default.appId}

The appId property connects the hosting site to a Firebase web app, enabling automatic SDK configuration for Firebase services. The web app must exist before creating the site association. This configuration allows your hosted application to access Firebase Authentication, Firestore, and other Firebase services through the SDK.

Beyond these examples

These snippets focus on specific hosting site features: default and additional site creation, and web app integration. They’re intentionally minimal rather than full hosting deployments.

The examples assume pre-existing infrastructure such as a Firebase project with Hosting enabled. They focus on site provisioning rather than content deployment or domain configuration.

To keep things focused, common hosting patterns are omitted, including:

  • Custom domain configuration
  • Site deletion and cleanup (force_destroy)
  • Multi-site routing and rewrites
  • Deploy configuration and version management

These omissions are intentional: the goal is to illustrate how each hosting site feature is wired, not provide drop-in hosting modules. See the Firebase Hosting Site resource reference for all available configuration options.

Let's deploy Firebase Hosting Sites

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Provider & Beta Status
Do I need a special provider to use Firebase Hosting sites?
Yes, this resource is in beta and requires the terraform-provider-google-beta provider.
Site Configuration & Identifiers
What are the requirements for siteId?
The siteId must be globally unique and a valid domain name label. It’s immutable after creation and used to construct Firebase-provisioned subdomains like https://{name}.web.app.
Can I change the siteId or project after creating a site?
No, both siteId and project are immutable and cannot be changed after the site is created.
How do I create a default Firebase Hosting site?
Set the siteId to match your project name. This creates a default site, as shown in the example where siteId: "my-project-name" matches the project.
Web App Integration
How do I link a hosting site to a Firebase Web App?
Set the appId property to reference the Web App’s appId. For example: appId: webApp.appId where webApp is a gcp.firebase.WebApp resource.
Is linking a Web App required for hosting sites?
No, the appId property is optional. You can create a hosting site without linking it to a Web App, as shown in the basic example.
Site Types & URLs
What's the difference between DEFAULT_SITE and USER_SITE?
The type output indicates whether the site is a DEFAULT_SITE (typically matching the project name) or a USER_SITE (custom site). This is determined automatically based on your configuration.
Can I import an existing Firebase Hosting site?
Yes, you can import sites using multiple formats: projects/{{project}}/sites/{{site_id}}, {{project}}/{{site_id}}, sites/{{site_id}}, or just {{site_id}}.

Using a different cloud?

Explore compute guides for other cloud providers: