# Google Cloud load balancer SSL: Google-managed certificates

> Add HTTPS to a Google Cloud Application Load Balancer with Google-managed certificates or Certificate Manager, redirect HTTP, track status.

Source: https://ssl.sh/guides/google-cloud-load-balancer-ssl/
Last updated: 2026-11-10

A Google Cloud global external Application Load Balancer serves HTTPS with a Google-managed certificate: create the certificate for your domains, attach it to an HTTPS proxy and point DNS at the load balancer's IP. Google provisions and renews the certificate automatically.

A second forwarding rule on the same IP redirects HTTP to HTTPS. Commands use the gcloud CLI as of November 2026, with `example.com` and `www.example.com` as the domains.

## Prerequisites

You need a working HTTP load balancer setup.

- The gcloud CLI authenticated to the project, with permissions for Compute Engine load balancing (and Certificate Manager for wildcards).
- A backend service and URL map for your application (here `web-map`), and a reserved global IP address (here `web-ip`), for example `203.0.113.10`.
- Access to DNS for `example.com`.
- CAA records, if present, that allow `pki.goog` and `letsencrypt.org`; check with the [CAA checker](https://ssl.sh/tools/caa-checker/).

## Step 1: Create the Google-managed certificate

A Google-managed certificate covers the domains you list and is provisioned once they resolve to the load balancer:

```bash
gcloud compute ssl-certificates create web-cert \
  --domains=example.com,www.example.com --global
```

## Step 2: Create the HTTPS proxy and forwarding rule

The HTTPS target proxy holds the certificate, and a global forwarding rule sends port 443 on `web-ip` to it:

```bash
gcloud compute target-https-proxies create web-https-proxy \
  --url-map=web-map --ssl-certificates=web-cert --global
gcloud compute forwarding-rules create web-https-rule \
  --load-balancing-scheme=EXTERNAL_MANAGED --global \
  --address=web-ip --target-https-proxy=web-https-proxy --ports=443
```

Optionally attach a TLS policy that requires TLS 1.2 or later:

```bash
gcloud compute ssl-policies create modern-tls --profile=MODERN --min-tls-version=1.2 --global
gcloud compute target-https-proxies update web-https-proxy --ssl-policy=modern-tls --global
```

## Step 3: Point DNS at the load balancer

Create `A` records for `example.com` and `www.example.com` with the address of `web-ip`:

```bash
gcloud compute addresses describe web-ip --global --format='get(address)'
```

Provisioning starts once Google sees both names resolve to that IP.

## Step 4: Redirect HTTP to HTTPS

Create a redirect-only URL map, an HTTP proxy and a port-80 rule on the same IP:

```bash
cat > redirect.yaml <<'EOF'
kind: compute#urlMap
name: web-redirect
defaultUrlRedirect:
  redirectResponseCode: MOVED_PERMANENTLY_DEFAULT
  httpsRedirect: true
EOF
gcloud compute url-maps import web-redirect --source=redirect.yaml --global
gcloud compute target-http-proxies create web-http-proxy --url-map=web-redirect --global
gcloud compute forwarding-rules create web-http-rule \
  --load-balancing-scheme=EXTERNAL_MANAGED --global \
  --address=web-ip --target-http-proxy=web-http-proxy --ports=80
```

For a wildcard such as `*.example.com`, use Certificate Manager instead: create a DNS authorization (`gcloud certificate-manager dns-authorizations create`), add the CNAME it returns, create the certificate with `--dns-authorizations`, put it in a certificate map, and attach the map to the HTTPS proxy with `--certificate-map`.

## Verify

Each domain must reach `ACTIVE` before the load balancer serves the certificate for it. Watch provisioning status per domain:

```bash
gcloud compute ssl-certificates describe web-cert --global \
  --format='get(managed.status, managed.domainStatus)'
```

When it shows `ACTIVE`, check the public endpoint with the [SSL checker](https://ssl.sh/tools/ssl-checker/), or from any terminal:

```bash
curl ssl.sh/example.com
curl -sI http://example.com | grep -iE '^(HTTP|location)'
```

## Automatic renewal

Google renews managed certificates automatically before they expire, as long as the domains keep resolving to the load balancer (load balancer authorization) or the DNS authorization CNAME stays in place (Certificate Manager). Nothing on your side has to run, and shorter public lifetimes (200 days since March 15, 2026, 47 days from March 15, 2029) only mean more frequent renewals by Google. Renewal fails if you move DNS elsewhere, delete the authorization CNAME, or add a CAA record that excludes Google's CAs. Add the domains to [ssl.sh monitoring](https://ssl.sh/monitor/) (in development) as an outside check.

## Troubleshooting

- **FAILED_NOT_VISIBLE**: the domain does not resolve to the load balancer's IP yet; fix the A record and wait.
- **FAILED_CAA_CHECKING or FAILED_CAA_FORBIDDEN**: CAA records exclude Google's CAs; see [CAA record prevents issuance](https://ssl.sh/errors/caa-record-prevents-issuance/).
- **Status stuck in PROVISIONING**: one of the domains is failing; the per-domain status shows which. Remove it or fix its DNS.
- **Browser shows a name mismatch**: the certificate does not include the requested host; see [NET::ERR_CERT_COMMON_NAME_INVALID](https://ssl.sh/errors/net-err-cert-common-name-invalid/).
- **Old clients fail after attaching the MODERN policy**: see [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](https://ssl.sh/errors/err-ssl-version-or-cipher-mismatch/).
