# How to Add a Custom Domain with Automatic SSL
Your app shouldn't live forever at my-app-prod-7x2.example.dev. Pointing a real domain at it and serving HTTPS is a rite of passage — and a place where small misunderstandings cause big confusion. Here's how it actually works.
How DNS connects a domain to your app
When someone visits app.yourdomain.com, their browser asks DNS for the address. Your job is to create a record that points your domain at your platform's ingress. You have two main options.
| Record type | Points to | Use when |
|---|---|---|
A / AAAA | An IP address (v4/v6) | Apex/root domains (yourdomain.com) |
CNAME | Another hostname | Subdomains (app.yourdomain.com) |
The historical wrinkle: the DNS spec doesn't allow a CNAME on the apex (root) domain. Many DNS providers solve this with ALIAS, ANAME, or "CNAME flattening" records. If you're using a subdomain, a plain CNAME is simplest.
Step 1: Add the domain in your platform
Most platforms have you register the domain first so they can issue a certificate for it. After you add app.yourdomain.com, the platform tells you the target to point at — either a hostname (for a CNAME) or an IP (for an A record).
Step 2: Create the DNS record
In your DNS provider (Cloudflare, Route 53, Namecheap, etc.):
# Subdomain via CNAME
Type: CNAME
Name: app
Value: ingress.yourplatform.example.
TTL: 3600# Apex via A record
Type: A
Name: @
Value: 203.0.113.42
TTL: 3600A tip if you're on Cloudflare: during initial certificate issuance, set the record to "DNS only" (grey cloud) rather than "Proxied" (orange cloud), or the ACME challenge may fail. You can re-enable the proxy after the certificate is issued.
Step 3: How automatic SSL works
Automatic HTTPS is powered by the [ACME protocol](https://datatracker.ietf.org/doc/html/rfc8555), most famously via [Let's Encrypt](https://letsencrypt.org/how-it-works/). The flow:
- 1The platform requests a certificate for your domain from a Certificate Authority.
- 2The CA issues a challenge to prove you control the domain — typically an
HTTP-01challenge (serve a token at a well-known URL) orDNS-01(create a TXT record). - 3Once the challenge passes, the CA issues the certificate.
- 4The platform installs it at the ingress and renews it automatically before expiry (Let's Encrypt certs last 90 days).
This is why your DNS record must be correct before the certificate can be issued — the CA verifies control over the exact domain you're requesting.
Step 4: Verify and wait for propagation
DNS changes aren't instant. They propagate according to TTL and caching. Check with command-line tools:
# Confirm the record resolves
dig app.yourdomain.com CNAME +short
# Once SSL is issued, verify the certificate
curl -vI https://app.yourdomain.com 2>&1 | grep -i 'subject\|issuer'If dig returns the wrong target, the record hasn't propagated or was entered incorrectly. Most propagation completes within minutes to a few hours.
Step 5: Force HTTPS and add HSTS
Once HTTPS works, redirect all HTTP traffic to HTTPS and consider an HSTS header so browsers refuse to connect over plain HTTP:
Strict-Transport-Security: max-age=31536000; includeSubDomainsMost platforms handle the HTTP→HTTPS redirect automatically at the ingress. Add HSTS only when you're confident every subdomain serves HTTPS — it's hard to undo because browsers cache it.
Doing it on PandaStack
PandaStack supports custom domains with automatic SSL out of the box. You add your domain in the dashboard, create the DNS record it shows you, and the platform handles certificate issuance and renewal via its ingress layer (Kong, with Cloudflare DNS on the platform side). You don't manage certificate files or renewal cron jobs — when a cert nears expiry it renews automatically.
The whole flow fits the platform's philosophy: connect your repo, it deploys and goes live, then you put your own domain in front of it with HTTPS, no manual certbot runs required.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Certificate won't issue | DNS record wrong, not propagated, or proxied during challenge |
NET::ERR_CERT_COMMON_NAME_INVALID | Cert issued for a different hostname than requested |
Works on www but not apex | Apex needs A/ALIAS, not CNAME |
| Mixed-content warnings | App serving assets over http:// |
References
- [Let's Encrypt — How It Works](https://letsencrypt.org/how-it-works/)
- [RFC 8555: Automatic Certificate Management Environment (ACME)](https://datatracker.ietf.org/doc/html/rfc8555)
- [Cloudflare: CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/)
- [MDN: Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
Deploy an app and put your own domain in front of it with automatic SSL on PandaStack's free tier — start at [dashboard.pandastack.io](https://dashboard.pandastack.io).