Cloudflare DNSEdit
Context
In May 2022 I switched to using Cloudflare Registrar for my domain registrations (from Namecheap) because they offer domain renewals at fair prices. Basically, they run the registry "at cost" as a kind of loss-leader for their other offerings. I don’t know how long they will keep this up, but their registrar went public in 2018, so it’s 4 years so far at the time of writing. Back in the day, Namecheap used to offer reasonably fair renewal prices too — that’s why I ran into their warm embrace, fleeing from an abusive relationship with GoDaddy, pausing in an intermediate rebound relationship with Joker along the way — but unfortunately, it wasn’t to last…
Anyway, Cloudflare also hosts the DNS for free, allowing me to save a few pennies by switching that away too (from Amazon Route 53). All of this follows on from another cost-saving measure I undertook in 2021, which was moving some static pages from Amazon EC2 (paid) to GitHub Pages (free). Speaking of free, I stopped paying for SSL certificates once Let’s Encrypt took off; any time I need an SSL certificate for a site I run, I use that, and for sites I don’t run (eg. GitHub Pages, Cloudflare URL forwarding etc) the corresponding providers deal with the SSL for free. Overall, having a simple, static presence online has gotten a lot cheaper since the early days.
Static hosting on GitHub Pages with redirects
Case study #1: greg.hurrell.net
GitHub set-up
- Source code: github.com/wincent/cv.
- Build script.
gh-pages branch.
- wincent.github.io/cv: GitHub pages site for this repo (redirects to
greg.hurrell.net).
CNAME configuration, telling GitHub that there’s a CNAME for greg.hurrell.net pointing at the GitHub pages site for this repo.
Cloudflare set-up
- DNS for
hurrell.net:
CNAME greg → wincent.github.io
CNAME @ (root) → github.hurrell.net (proxied); used for a redirect — see "Page Rules" below.
CNAME www → github.hurrell.net (proxied); used for a redirect — see "Page Rules" below.
- Page Rules for
hurrell.net:
hurrell.net/* via Forwarding URL (301 — Permanent Redirect) → https://greg.hurrell.net/$1
www.hurrell.net/* via Forwarding URL (301 — Permanent Redirect) → https://greg.hurrell.net/$1
- DNS for
greghurrell.net (and a couple of other similar domains that I have):
CNAME @ (root) → github.greghurrell.net (proxied); used for a redirect — see "Page Rules" below.
CNAME www → github.greghurrell.net (proxied); used for a redirect — see "Page Rules" below.
- Page Rules for
greghurrell.net:
greghurrell.net/* via Forwarding URL (301 — Permanent Redirect) → https://greg.hurrell.net/$1
www.greghurrell.net/* via Forwarding URL (301 — Permanent Redirect) → https://greg.hurrell.net/$1
gh-pages branch.
- wincent.github.io/cv: GitHub pages site for this repo (redirects to
greg.hurrell.net). CNAMEconfiguration, telling GitHub that there’s aCNAMEforgreg.hurrell.netpointing at the GitHub pages site for this repo.
- DNS for
hurrell.net:CNAMEgreg→wincent.github.ioCNAME@(root) →github.hurrell.net(proxied); used for a redirect — see "Page Rules" below.CNAMEwww→github.hurrell.net(proxied); used for a redirect — see "Page Rules" below.
- Page Rules for
hurrell.net:hurrell.net/*via Forwarding URL (301 — Permanent Redirect) →https://greg.hurrell.net/$1www.hurrell.net/*via Forwarding URL (301 — Permanent Redirect) →https://greg.hurrell.net/$1
- DNS for
greghurrell.net(and a couple of other similar domains that I have):CNAME@(root) →github.greghurrell.net(proxied); used for a redirect — see "Page Rules" below.CNAMEwww→github.greghurrell.net(proxied); used for a redirect — see "Page Rules" below.
- Page Rules for
greghurrell.net:greghurrell.net/*via Forwarding URL (301 — Permanent Redirect) →https://greg.hurrell.net/$1www.greghurrell.net/*via Forwarding URL (301 — Permanent Redirect) →https://greg.hurrell.net/$1
The net effect of the above on requests is:
- greg.hurrell.net (HTTPS) → handled by GitHub Pages site.
- greg.hurrell.net (HTTP) → redirects to HTTPS URL.
- hurrell.net (HTTPS) → redirected to greg.hurrell.net (HTTPS).
- hurrell.net (HTTP) → redirected to greg.hurrell.net (HTTPS).
- www.hurrell.net (HTTPS) → redirected to greg.hurrell.net (HTTPS).
- www.hurrell.net (HTTP) → redirected to greg.hurrell.net (HTTPS).
- greghurrell.net (HTTPS) → redirected to greg.hurrell.net (HTTPS).
- greghurrell.net (HTTP) → redirected to greg.hurrell.net (HTTPS).
- www.greghurrell.net (HTTPS) → redirected to greg.hurrell.net (HTTPS).
- www.greghurrell.net (HTTP) → redirected to greg.hurrell.net (HTTPS).
- Non-root requests get redirected too; eg. www.hurrell.net/cv-full.en.html → greg.hurrell.net/cv-full.en.html.
Note that all the redirects are a single "hop", which you can see with a command like curl -L -i http://www.hurrell.net/cv-full.en.html; it shows an immediate 301 redirect to the HTTPS URL on the GitHub Pages site.
Credit for the Page Rules configuration goes to this Stack Overflow answer and comment. Conveniently Cloudflare gives you three Page Rules for free with every site.
Case study #2: hex.wincent.dev
GitHub set-up
- Source code: github.com/wincent/hextrapolate.
- Build script.
gh-pagesbranch.- wincent.github.io/hextrapolate: GitHub pages site for this repo (redirects to
hex.wincent.dev). CNAMEconfiguration, telling GitHub that there’s aCNAMEforhex.wincent.devpointing at the GitHub pages site for this repo.
- wincent.github.io/hextrapolate: GitHub pages site for this repo (redirects to
Cloudflare set-up
- DNS for
wincent.dev:
CNAME hex → wincent.github.io
- A zillion other
A and CNAME records for various things hosted elsewhere, like:
A record for git.wincent.dev pointing at an EC2 Elastic IP.
A record for wincent.dev root pointing at another Elastic IP.
CAA record wincent.dev saying that letsencrypt.org is allowed to issue certificates; this works because GitHub Pages uses Let’s Encrypt to create the certificate for hex.wincent.dev and I also use Let’s Encrypt to generate the other certificates for wincent.dev, git.wincent.dev (etc) domains on EC2. If GitHub Pages ever switches to a different Certificate Authority, I’ll have to add another CAA record.
- Page Rules for
wincent.dev: none.
Case study #3: s3.example.com[1]
wincent.dev:
CNAMEhex→wincent.github.io- A zillion other
AandCNAMErecords for various things hosted elsewhere, like:Arecord forgit.wincent.devpointing at an EC2 Elastic IP.Arecord forwincent.devroot pointing at another Elastic IP.CAArecordwincent.devsaying thatletsencrypt.orgis allowed to issue certificates; this works because GitHub Pages uses Let’s Encrypt to create the certificate forhex.wincent.devand I also use Let’s Encrypt to generate the other certificates forwincent.dev,git.wincent.dev(etc) domains on EC2. If GitHub Pages ever switches to a different Certificate Authority, I’ll have to add anotherCAArecord.
wincent.dev: none.As the name suggests, this hostname is associated with an AWS S3 bucket, which I use for hosting binary archives. I originally used s3.example.com as the bucket name, but later switched to wincent, because Amazon uses a wildcard certificate that does not match buckets with dots in their names (ie. it covers wincent.s3.amazonaws.com but not s3.example.com.s3.amazonaws.com).
As suggested in this ServerFault Pro-Tip, we can see the certificate info as follows (edited for brevity, but note the Subject Alternative Name info, which says DNS:*.s3.amazonaws.com, DNS:s3.amazonaws.com):
$ echo | openssl s_client -showcerts \
-servername s3.example.com.s3.amazonaws.com \
-connect s3.example.com.s3.amazonaws.com:443 2> /dev/null | \
openssl x509 -inform pem -noout -text
Certificate:
Data:
...
X509v3 extensions:
...
X509v3 Subject Alternative Name:
DNS:*.s3.amazonaws.com, DNS:s3.amazonaws.com
Cloudflare set-up
- DNS for
wincent.dev:
CNAME s3 → wincent.s3.amazonaws.com (proxied)
This wasn’t the actual hostname I was using, just an example of the form s3.$something.com. ↩︎
wincent.dev:
CNAMEs3→wincent.s3.amazonaws.com(proxied)
This wasn’t the actual hostname I was using, just an example of the form
s3.$something.com. ↩︎