08 β Custom Domain & SSL
β Previous: 07 β First Deploy
π° Domain registration costs money β paid to your registrar, not GCP. A
.cldomain costs approximately $10β20/year depending on the registrar (NIC.cl charges ~$12/year). The domain is yours regardless of which hosting you use.β Everything else in this chapter is free. GCP domain mapping, SSL certificate provisioning, and auto-renewal are all free. Cloudflare's DNS and DDoS protection are free on the free plan.
What Cloud Run provides by default
After deploying, Cloud Run gives you a URL like:
This URL already has HTTPS with a Google-managed SSL certificate. For production you want to use your own domain (mycoolproject.cl) instead.
How SSL works here
SSL ownership depends on how you configure your DNS. There are two options:
| Setup | Who manages SSL | Trade-off |
|---|---|---|
| Cloudflare DNS only (grey cloud) | GCP / Cloud Run | Google provisions and auto-renews your certificate for free. No middleman. This is what this guide uses. |
| Cloudflare proxied (orange cloud) | Cloudflare | Cloudflare terminates SSL and re-encrypts traffic to GCP. Adds Cloudflare's WAF and DDoS protection. More complex to set up correctly β you need to set Cloudflare SSL mode to "Full (strict)" or you'll get redirect loops. |
This guide uses DNS only β Cloud Run handles everything. GCP talks directly to your domain's DNS, provisions a free certificate via Google Trust Services, and terminates all SSL at the Cloud Run edge. No Certbot, no nginx, no certificate management needed.
Map your domain to Cloud Run
# Maps your custom domain to the Cloud Run service and begins SSL certificate provisioning.
# After running this, GCP will tell you which DNS record to add at your registrar.
# Result: GCP prints the required CNAME or A record β add it to your DNS provider.
gcloud run domain-mappings create \
--service=mycoolproject \
--domain=mycoolproject.cl \
--region=southamerica-east1
This returns a DNS record to add β something like:
Or an A record pointing to Google's IP. The exact record depends on whether it's a root domain or subdomain.
Check status (SSL provisioning takes a few minutes to up to an hour):
# Checks the status of the domain mapping and SSL certificate provisioning.
# Wait until certificateMode shows AUTOMATIC and mappingStatus shows ACTIVE.
# SSL provisioning takes a few minutes to up to an hour after DNS propagates.
gcloud run domain-mappings describe \
--domain=mycoolproject.cl \
--region=southamerica-east1
Wait until certificateMode shows AUTOMATIC and mappingStatus shows ACTIVE.
DNS setup (at your registrar or Cloudflare)
If using Cloudflare (recommended β free DDoS protection, bot filtering):
- Add your domain to Cloudflare (free plan)
- Point your registrar's nameservers to Cloudflare's
- In Cloudflare DNS, add the record GCP gave you
- Set proxy to DNS only (grey cloud) βοΈ
Why grey cloud? When you set the record to "DNS only", Cloudflare acts as a pure DNS resolver β it just tells browsers where your server is. GCP then handles the SSL certificate directly with your domain. If you enable the orange cloud (proxied), Cloudflare intercepts all traffic and tries to terminate SSL itself, which breaks GCP's certificate provisioning and causes
SSL_ERROR_RX_RECORD_TOO_LONGerrors in the browser.You still get Cloudflare's DDoS protection and bot filtering on the free plan with DNS-only mode β it just works at the network layer rather than the application layer.
If using your registrar directly (NIC.cl, Namecheap, etc.):
- Log in to your registrar's DNS management panel
- Add the CNAME or A record GCP provided
www redirect
To also handle www.mycoolproject.cl:
# Maps the www subdomain to the same service, so www.mycoolproject.cl also works.
gcloud run domain-mappings create \
--service=mycoolproject \
--domain=www.mycoolproject.cl \
--region=southamerica-east1
Or add a CNAME www β mycoolproject.cl in your DNS and let Cloudflare/registrar handle the redirect.
Update ALLOWED_HOSTS
Once the domain is live, update the Cloud Run service to include both the custom domain and the original .run.app URL:
# Updates the ALLOWED_HOSTS env var on the running service without a full redeploy.
# Django rejects requests with an unrecognised Host header β this prevents that 400 error.
# Cloud Run creates a new revision automatically when env vars change.
gcloud run services update mycoolproject \
--region=southamerica-east1 \
--update-env-vars=ALLOWED_HOSTS="mycoolproject.cl,www.mycoolproject.cl"
ALLOWED_HOSTS is Django's security setting that rejects requests with an unrecognised Host header β prevents HTTP Host header attacks.
π Navigation
- 01 β GCP Project Setup
- 02 β Artifact Registry
- 03 β Cloud SQL (PostgreSQL Database)
- 04 β Secret Manager
- 05 β Cloud Storage (Media & Static Files)
- 06 β Dockerfile
- 07 β First Deploy
- 08 β Custom Domain & SSL (Current chapter)
- 09 β Workload Identity Federation (Keyless GitHub Actions Auth)
- 10 β GitHub Actions CI/CD Pipeline
- 11 β Quick Reference
- 12 β Bonus: Custom Email (@domain.cl)