Custom Domains on GitLab Pages with Namecheap (and the .dev DNSSEC Gotcha)
I set up custom domains for this blog today. GitLab Pages, Namecheap DNS, a .dev and a .com. The .com was painless. The .dev cost me an hour of staring at SERVFAIL responses before I found the one toggle that fixes everything.
Here’s the whole process so you can skip the debugging. This covers apex/root domains (e.g., sundaydeploys.dev), not subdomains like blog.example.com.
Prerequisites
You need three things before starting:
- A GitLab Pages site that’s already deploying. You should be able to see it at
<username>.gitlab.io. If your CI pipeline isn’t working yet, fix that first. - A domain on Namecheap with access to the Advanced DNS panel.
- Basic familiarity with DNS records. You don’t need deep DNS knowledge, but you should know what an A record is.
Step 1: Clean Up Existing DNS Records
Log in to Namecheap and go to Domain List > your domain > Advanced DNS.
Before adding anything, delete what’s already there. Namecheap often has default records that will conflict with GitLab Pages. Look for:
- URL Redirect Records. These are the biggest offender. They silently create A and AAAA records behind the scenes that point to Namecheap’s redirect servers. If you leave them, your A record for GitLab will be ignored.
- Parking page records or any default A/CNAME records on
@.
Delete them. You want a clean slate.
Step 2: Add the A Record
Add a new record:
| Type | Host | Value | TTL |
|---|---|---|---|
| A Record | @ | 35.185.44.232 | Automatic |
That IP is GitLab’s Pages server. It’s been stable for years. You can double-check it in GitLab’s docs.
Do not add an AAAA (IPv6) record. GitLab’s DNS docs list one (2600:1901:0:7b8a::), but the Let’s Encrypt integration docs explicitly warn against it because it blocks automatic certificate provisioning. If you add it now, you’ll be debugging certificate errors later. Just the A record.
Step 3: Add the Verification TXT Record
In GitLab, go to your project > Deploy > Pages > New Domain. Enter your domain. GitLab will show you a verification code that looks like this:
_gitlab-pages-verification-code.yourdomain.dev TXT gitlab-pages-verification-code=abc123...
Back in Namecheap, add a TXT record:
| Type | Host | Value | TTL |
|---|---|---|---|
| TXT Record | _gitlab-pages-verification-code | gitlab-pages-verification-code=<your-code> | Automatic |
The key Namecheap detail: only put _gitlab-pages-verification-code in the Host field. Don’t append your domain name. Namecheap adds the domain suffix automatically. If you enter the full thing, you’ll end up with _gitlab-pages-verification-code.sundaydeploys.dev.sundaydeploys.dev and wonder why verification fails.
Wait a few minutes, then click Verify in GitLab. If it doesn’t work right away, give it up to 30 minutes. You can check propagation yourself:
dig _gitlab-pages-verification-code.yourdomain.dev TXT
You’re looking for an ANSWER section with your verification code.
Step 4: Enable DNSSEC (.dev Domains Only)
If your domain is a .dev and you’re getting SERVFAIL responses, you likely have a broken DNSSEC chain of trust. Enabling DNSSEC in Namecheap fixes it. If your domain is a .com or another TLD, you probably don’t need this step.
In Namecheap: Domain List > Manage > Advanced DNS > scroll down to the DNSSEC section > toggle it ON. Namecheap handles the DS record and DNSKEY configuration automatically. No keys to enter, no zones to sign manually.
Propagation takes up to 60 minutes. This is the longest wait in the whole process. I explain why this matters in the section below.
Step 5: Wait for Let’s Encrypt
Once GitLab verifies your domain, it automatically starts provisioning a Let’s Encrypt SSL certificate. This takes up to an hour. Mine took about 45 minutes.
During this window you’ll get a certificate error because GitLab is still serving its *.gitlab.io wildcard cert. Your browser sees a cert for gitlab.io on your domain and complains. That’s normal. Don’t start deleting records. Just wait.
You can check the certificate status:
openssl s_client -connect yourdomain.dev:443 -servername yourdomain.dev </dev/null 2>/dev/null | grep 'subject='
When it shows subject=CN=yourdomain.dev instead of subject=CN=*.gitlab.io, you’re done.
Why .dev Domains Break Without DNSSEC
Google owns the .dev TLD and DNSSEC-signs the entire zone. That means validating resolvers check the chain of trust all the way from the .dev registry down to your domain’s nameservers. If there’s a mismatch anywhere in that chain, the resolver doesn’t fall back to an unsigned response. It returns SERVFAIL.
My .dev domain was getting SERVFAIL from every validating resolver I tried, including Google’s 8.8.8.8. The records were there, they were correct, and nothing could see them. Not NXDOMAIN. Not a timeout. SERVFAIL.
My best guess is that Namecheap had published a DS record for my domain at some point (maybe from a previous configuration or migration) that didn’t match the current zone keys. Enabling DNSSEC in Namecheap regenerated the keys and DS record, fixing the mismatch. Once propagation finished, it just worked.
Verify and Troubleshoot
Once Let’s Encrypt finishes provisioning, confirm everything end to end. If something fails, the fix is right below the check.
DNS resolution:
dig yourdomain.dev A +short
# Expected: 35.185.44.232
If you get SERVFAIL on a .dev domain, you likely have a broken DNSSEC chain of trust. Go to Namecheap > Advanced DNS > DNSSEC and toggle it on. Wait up to 60 minutes. If your records look correct but nothing resolves, you probably have a URL Redirect Record hiding in Namecheap. These create phantom DNS records that override yours. Delete them.
Domain verification:
dig _gitlab-pages-verification-code.yourdomain.dev TXT +short
If GitLab verification won’t flip to verified, check that the TXT record Host is exactly _gitlab-pages-verification-code with no domain suffix. If dig shows NXDOMAIN, the record isn’t live yet.
SSL certificate:
curl -I https://yourdomain.dev
If the certificate error persists after an hour, make sure you don’t have an AAAA record. Check for leftover URL Redirect Records. If everything looks clean, try removing the domain in GitLab Pages and re-adding it to trigger a fresh Let’s Encrypt request.
In GitLab, your Pages domain should show green checkmarks for both verification and certificate status.
What I Wish the Docs Said
The fix for my .dev problem was a single toggle buried in the Advanced DNS settings. I couldn’t find any mention of .dev DNSSEC issues in the GitLab or Namecheap documentation. It’s one of those things you only find out about when it breaks.
DNS is like that. When it works, you forget it exists.