📑 Daftar Isi
- Why GitHub Pages Custom Domain Setup Fails
- GitHub Pages Custom Domain Setup: Step by Step
- Step 1: Check Your Repository Layout
- Step 2: Add the CNAME File
- Step 3: Enable the Custom Domain in Settings
- Step 4: Point Your DNS
- Step 5: Wait for Propagation and Verify
- Step 6: Enforce HTTPS
- Troubleshooting GitHub Pages Custom Domain Issues
- Pro Tips From the Field
- FAQ: GitHub Pages Custom Domain
- Q: Why doesn't my custom domain activate right after I save it?
- Q: Should I use www or non-www?
- Q: Why is my TLS certificate stuck on "not active"?
- Q: Is there a difference between user sites and project sites for custom domains?
- Wrap-Up
How to Set Up a Custom Domain on GitHub Pages: Complete Step-by-Step Guide
Skip the fluff — here’s the deal. A few months back, a client of mine burned two full days fighting GitHub Pages because he’d typed his domain into Settings but never created the CNAME file. Two days, gone, over a single missing file. I’ll make sure that doesn’t happen to you. This is the straightforward github pages custom domain setup walkthrough — no extra steps, no fluff, just what actually works.
Think of your repo as a physical shop. GitHub hands you a free storefront at username.github.io the moment you enable Pages. A custom domain is your own sign and your own mailing address. To make it real you need two things: the sign hung on the storefront (that’s the CNAME file), and your address registered in the city directory so the postman knows where to deliver (that’s DNS). Missing either one and mail just… doesn’t arrive. Nothing about this is optional.
Why GitHub Pages Custom Domain Setup Fails
The failure always comes down to one of three places, and the annoying part is the error messages rarely tell you which one. First, the CNAME file — either it doesn’t exist, it’s in the wrong branch, or it doesn’t match what you typed in Settings. Second, the DNS records — wrong type, wrong target, or pointed at an outdated IP from an old tutorial. Third, timing — DNS propagation and TLS certificate provisioning both take time, and impatient people keep touching things that were already fine. Nail all three and you’re done; skip one and you’ll be chasing symptoms all day.
The symptoms you’ll see are pretty consistent. “Domain is already assigned to another site” means GitHub thinks that domain belongs to a different repository of yours. “DNS has not resolved yet” means your records haven’t propagated, or they’re just wrong. And the classic HTTPS error, “Certificate not active,” only means Let’s Encrypt hasn’t finished issuing your cert yet — usually because DNS still wasn’t resolving when GitHub first tried. You can chase all three at once, or you can follow the order below and avoid most of them entirely.
Here’s the thing I tell everyone: treat this as a pipeline. CNAME first, then DNS, then wait, then HTTPS. If you jump the line — say, you enable Enforce HTTPS before DNS resolves — you’ll just create extra work and longer wait times. Trust me, I’ve seen people toggle that checkbox for an hour straight expecting it to fix the DNS. It won’t. Order matters, and that’s the entire trick to this. Get the sequence right once, and every future domain change becomes a ten-minute job.
GitHub Pages Custom Domain Setup: Step by Step
I’ll assume you already have a working GitHub Pages site (a user site at username.github.io or a project site on the gh-pages branch) and a domain where you can edit DNS records. If either of those is missing, sort it out first — you can’t wire up what doesn’t exist yet.
Step 1: Check Your Repository Layout
User sites need the repo named exactly <username>.github.io. Project sites can publish from the gh-pages branch or a /docs folder. Whatever you use, the rule below applies to the branch that actually gets published. Write this down somewhere — it’s the branch you’ll keep coming back to in the next few steps.
Step 2: Add the CNAME File
Create a file named CNAME — all caps, no extension — in the root of your repository, in the branch that Pages publishes from. The entire file is one line: your domain, no https://, no trailing slash.
example.com
Want www instead? Then write www.example.com. Whatever you put here must match, character for character, what you’ll type in Settings later. Commit and push, then double-check the file is actually visible in the repo on GitHub’s website. Skipping files is a classic move — I’ve done it myself more than once.
/docs folder or the gh-pages branch, the CNAME must live there — not just in your source branch.Step 3: Enable the Custom Domain in Settings
Open the repo, go to Settings > Pages. Under Custom domain, type the same domain you put in the CNAME file and hit Save. If everything lines up, you’ll get a success message with a green check. If you get an error instead, go back to Step 2 — it’s almost always the CNAME file, and occasionally DNS that hasn’t caught up. Leave the Enforce HTTPS checkbox alone for now. We’ll come back for it in Step 6.
Step 4: Point Your DNS
Here’s where most of the confusion lives, so let’s keep it simple. You have two possible setups, and they use different records. Figure out which one applies to you, then add exactly those records.
Using the apex domain (example.com)? Then you need four A records pointing at GitHub’s IPs. These IPs are official and fixed — ignore tutorials that list different ones:
| Record | Name | Value | TTL |
|---|---|---|---|
| A | @ | 185.199.108.153 | 3600 |
| A | @ | 185.199.109.153 | 3600 |
| A | @ | 185.199.110.153 | 3600 |
| A | @ | 185.199.111.153 | 3600 |
| AAAA | @ | 2606:50c0:8000::153 | 3600 |
| AAAA | @ | 2606:50c0:8001::153 | 3600 |
| AAAA | @ | 2606:50c0:8002::153 | 3600 |
| AAAA | @ | 2606:50c0:8003::153 | 3600 |
Using www.example.com? Then one CNAME record is all you need, pointing at your user site:
| Record | Name | Value | TTL |
|---|---|---|---|
| CNAME | www | username.github.io | 3600 |
Want both example.com and www.example.com to work? Combine them: four A records (plus the AAAA block if you want IPv6 support) for the apex, plus one CNAME for www. That’s the setup I’d recommend for 95% of people — it’s clean, and both URLs land on the same site.

www already has a CNAME pointing at an old host, delete or update it first — one record name can’t have two targets. And if your registrar has a “domain forwarding” feature active on top of this, turn it off; it will fight with GitHub’s own redirects.Step 5: Wait for Propagation and Verify
DNS doesn’t update instantly, and that’s fine — plan for it. To check whether your records are correct, use dig or nslookup:
dig example.com +short
For the apex, you want to see the four 185.199.x.x IPs above. Anything else means a wrong record or stale cache. For www:
dig www.example.com +short
That one should print username.github.io. If both match, your DNS is done and GitHub will start provisioning a TLS certificate. One note on TTL: 3600 seconds means changes take up to an hour to spread everywhere. If you’re about to make a lot of changes, drop the TTL to 300 first — future you will appreciate being able to test quickly instead of waiting an hour per attempt.
Step 6: Enforce HTTPS
Head back to Settings > Pages. Once your domain shows as active and DNS resolves correctly, GitHub begins issuing a free Let’s Encrypt certificate automatically. Give it anywhere from a few minutes to a few hours, then tick Enforce HTTPS. If you tick it before the certificate exists, you’ll just sit in error land waiting. Sequence: DNS resolves, domain active, cert issued, then enforce.
Once enforced, verify with curl:
curl -I https://example.com
You want HTTP/2 200 or a 301 redirect to the HTTPS version. If you get a certificate error, provisioning is still running — check again in a few hours. If it’s still failing after 24 hours, something in DNS or the CNAME is off. Back to steps 2-4 you go.
Troubleshooting GitHub Pages Custom Domain Issues
Here’s the troubleshooting table I keep in my head (and now, in print) for when things go sideways. Save it, it’ll save you a headache.
| Symptom | Likely Cause | Fix |
|---|---|---|
| “Domain is already assigned to another site” | The domain is set as custom domain on another repo | Check all your repos, remove the old custom domain |
| “DNS has not resolved yet” | Records not added or not propagated | Verify with dig, wait up to 24 hours |
| “Certificate not active” | TLS provisioning still in progress | Confirm DNS resolves, wait a few hours |
| Site works but redirects to username.github.io | CNAME file missing or in the wrong branch | Put CNAME in the root of the published branch |
| 404 despite correct DNS | Pages source or branch misconfigured | Check Settings > Pages source |
The single most common failure I see in the field is a mismatched CNAME — someone types example.com into Settings but the CNAME file says www.example.com, or the file lives on the wrong branch entirely. Both must match, and the file must be in the published branch. Also worth checking: if you manage multiple environments, make sure the CNAME that got pushed actually came from the right one.
Pro Tips From the Field
A few small things that quietly save people hours:
- Pick one canonical hostname. Choose www or non-www, make it the primary, and let GitHub’s automatic redirect handle the other. Two active hostnames pointing at the same site without a defined canonical splits your SEO signals and confuses users.
- Verify DNS from multiple vantage points. Your ISP’s resolver results alone prove nothing. Use an external lookup tool so you’re not debugging a stale local cache.
- Only trust GitHub’s official IPs. The four 185.199.x.x addresses above are current and stable. Old tutorials floating around still list IPs from years ago — skip them.
- Lower the TTL before big changes. A 300-second TTL means changes propagate in minutes, so you can iterate fast during setup, then raise it back once everything is stable.
If DNS propagation itself has ever confused you — why it’s slow, how it actually works — I wrote a deep dive you’ll want: DNS Propagation Troubleshooting Guide. For more on A and CNAME records specifically, check How to Set Up a DNS A Record. And if you’re thinking about outgrowing GitHub Pages and moving to your own box, read How to Migrate a Website to a VPS before you make the jump.
FAQ: GitHub Pages Custom Domain
Q: Why doesn’t my custom domain activate right after I save it?
Because three separate things have to happen in order: the CNAME file has to be correct, DNS has to resolve to GitHub’s IPs, and GitHub has to issue a TLS certificate. Each step takes time. Give it a full 24 hours before you start changing records — most “problems” are just impatience.
Q: Should I use www or non-www?
Technically it doesn’t matter — what matters is consistency. Pick one as your primary and let GitHub redirect the other. Non-www is arguably cleaner for branding, www is fine too. The genuinely bad option is running both without a defined canonical, because it splits your traffic and your SEO signals.
Q: Why is my TLS certificate stuck on “not active”?
GitHub uses Let’s Encrypt, and provisioning can take a few hours. First confirm DNS resolves to the right IPs and the CNAME file is correct. If it’s still stuck after 24 hours, re-check DNS from an external tool — a wrong or stale record is the usual culprit.
Q: Is there a difference between user sites and project sites for custom domains?
Yes. On a user site (username.github.io), the custom domain applies to everything in that repo. On a project site, the domain applies only to that project, and each project repo needs its own CNAME file. The DNS records and HTTPS setup work identically in both cases.
Wrap-Up
Honestly? GitHub pages custom domain setup comes down to three things: a correct CNAME file, the right DNS records (four A records for the apex or one CNAME for www), and the patience to let propagation and certificate provisioning finish. Get those three right and the domain just works. If you want to go deeper on how DNS works and why it frustrates everyone, the DNS propagation guide I linked above has you covered.
Save this page — custom domains are rarely a one-and-done thing. New domain, migration to a VPS, manual SSL setup… you’ll be back to this exact sequence every time. Bookmark it, follow the order, and you’re done. Go wire up that domain.