# Firebase Hosting custom domain SSL: setup and status fixes

> Connect a custom domain to Firebase Hosting: TXT and A records, CAA for letsencrypt.org and pki.goog, and fixes for Needs setup and Pending.

Source: https://ssl.sh/guides/firebase-hosting-custom-domain-ssl/
Last updated: 2026-11-10

Firebase Hosting provisions and renews an SSL certificate for every custom domain you connect, with nothing to configure beyond DNS. You prove ownership with a TXT record and point A records at Hosting. Firebase then deploys the certificate across its CDN within 24 hours, usually within a few hours.

Firebase uses Let's Encrypt and Google Trust Services, so a restrictive CAA policy must allow both. Steps follow the Firebase Hosting documentation as of November 2026, with `example.com` as the domain. They cover Firebase Hosting; Firebase App Hosting has its own custom domain flow.

## At a glance

| Question | Firebase Hosting |
|---|---|
| CA for automatic certificates | Hosting's CAs: Let's Encrypt and Google Trust Services |
| Ownership | `TXT` record on the apex, kept permanently |
| Apex and `www` | `A` (and `AAAA` where shown) records with the IPs from the wizard |
| CAA must allow | `letsencrypt.org` and `pki.goog` |
| Wildcard domains | Not described; connect each hostname (Firebase recommends at most 20 subdomains per apex) |
| Upload your own certificate | Not described in the docs |
| Renewal | Automatic ("reprovisions SSL certs, as needed") |
| Time to HTTPS | Up to 24 hours after the A records point to Hosting |

## Step 1: Start the Connect Domain wizard

On the project's **Hosting** page click **Add custom domain** (or **View** on the site first if you have several sites). Enter `example.com`. Optionally tick the box that redirects requests to a second domain so that `example.com` and `www.example.com` serve the same content; add the second name as its own custom domain. Each custom domain can be connected to only one Hosting site.

## Step 2: Verify ownership with a TXT record

If the wizard asks you to verify the apex, add the TXT record it shows at the apex (host `@` or blank). Verifying the apex proves ownership of all its subdomains. In Advanced Setup the record has the form `hosting-site=[site_id]`.

Keep this TXT record forever. Firebase uses it to prove ownership and to authorize assigning and renewing certificates. Allow up to 24 hours for propagation, then click **Verify**. An error at this point means the record has not propagated or the value is wrong.

## Step 3: Point the domain at Hosting

Choose **Quick Setup** for a domain that does not serve traffic yet, or **Advanced Setup** for a live domain that must move without downtime.

**Quick Setup.** Add the records the wizard shows for each hostname. The docs' example uses:

```dns
example.com.      3600  IN  A  199.36.158.100
www.example.com.  3600  IN  A  199.36.158.100
```

Use the values your wizard shows, not this example. Then remove every `A` or `CNAME` record that points to another provider, and remove `AAAA` records as well; the Quick Setup instructions say that if any of these remain, Firebase cannot provision the certificate.

**Advanced Setup.** Firebase prepares the certificate before traffic moves:

1. Add the ownership TXT record and, if Hosting finds CAA records that would block it, the pair of CAA records the wizard proposes.
2. Complete an ACME challenge: either a TXT record at the `_acme-challenge` name, or a file uploaded to your current site at the URL shown.
3. Once the certificate exists, replace the old records with Hosting's A/AAAA records. Your old host keeps serving until the status reaches **Connected**.

If the CA cannot validate the challenge, Hosting generates a new set of challenges for you.

## Step 4: Check CAA records

No CAA records means no restriction. If you have CAA records, allow both CAs:

```dns
example.com.  3600  IN  CAA  0 issue "letsencrypt.org"
example.com.  3600  IN  CAA  0 issue "pki.goog"
```

Look at the live policy with the [CAA checker](https://ssl.sh/tools/caa-checker/) or `dig CAA example.com +short`.

## Verify

Once the status is **Connected**, the domain presents a Let's Encrypt or Google Trust Services certificate. Check from outside with the [SSL checker](https://ssl.sh/tools/ssl-checker/):

```bash
curl ssl.sh/example.com
```

Or inspect the certificate directly:

```bash
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -ext subjectAltName -dates
```

Firebase lists your domain as one of the Subject Alternative Names in the FirebaseApp SSL certificate, so the SAN list may contain names other than yours. During provisioning you may briefly see a certificate without your domain; that resolves once your certificate is available.

## Renewal

Firebase states that Hosting automatically reprovisions SSL certificates for custom domains as needed. Two things keep that working: the ownership TXT record must stay in DNS, and the A records must keep pointing at Hosting. A CAA change that drops `letsencrypt.org` or `pki.goog` can also stop a later certificate. Public certificate lifetimes fall to 100 days from March 15, 2027 and 47 days from March 15, 2029, so renewals become more frequent; watch the domain with [ssl.sh monitoring](https://ssl.sh/monitor/) (in development).

## Troubleshooting by status

The domain status in the console tells you which step failed. Firebase documents these statuses for custom domains:

- **Needs setup**: usually the A records have not propagated to Firebase Hosting. After 24 hours, check that the records point to Hosting. In rarer cases (mostly Advanced Setup) the SSL certificate challenges failed and the token, a DNS TXT record or uploaded file, is now invalid; click **View** on the domain and provide the new token.
- **Pending**: the domain is set up correctly but Hosting has not provisioned a certificate. Firebase names three causes:
  - CAA records are too restrictive: allow `letsencrypt.org` and `pki.goog` (see [CAA record prevents issuance](https://ssl.sh/errors/caa-record-prevents-issuance/)).
  - The challenge code is invalid because an Advanced Setup migration failed: click **View** and provide the new token.
  - Too many subdomains: Firebase recommends no more than 20 subdomains on one apex custom domain because of certificate minting limits.
- **Minting Certificate**: the certificate is being produced. Wait.
- **Connected**: DNS records are correct and the certificate exists; the site is served on your domain.

If the browser shows a name mismatch ([NET::ERR_CERT_COMMON_NAME_INVALID](https://ssl.sh/errors/net-err-cert-common-name-invalid/)) while the status is not yet **Connected**, provisioning has not finished. Use the Google Admin Toolbox Dig service, or `dig`, to confirm that the records have updated.
