cmc/cleberg.net
My personal web garden & blog.
clone: git clone https://gitbay.org/cmc/cleberg.net.git
main: content/blog/2020-08-22-redirect-github-pages.org · raw
1#+date: [2020-08-22 Sat 00:00:00]
2#+title: GitHub Pages Redirect Subdomain to TLD
3#+description: A quick recap of a Stack Overflow answer that I want to exist in perpetuity.
4#+slug: redirect-github-pages
5#+filetags: :web:
6
7* Short answer
8
9** Step 1
10
11Add a new file called =CNAME= (canonical name) to your GitHub Pages repository
12containing only one line: your top-level domain name. E.g.: =example.com=
13
14** Step 2
15
16[Optional] but highly recommended
17
182.1: Remove all other top-level records (prefixed with @) of type A from your
19DNS configuration.
20
212.2: Remove a CNAME record for the second-level domain =www=, if it is present.
22
23** Step 3
24
25Add these 5 entries to the very top of your domain name system (DNS)
26configuration:
27
28#+begin_src txt
29@ A 185.199.108.153
30@ A 185.199.109.153
31@ A 185.199.110.153
32@ A 185.199.111.153
33www CNAME your_github_username.github.io.
34#+end_src
35
36Replace =your_github_username= with your actual GitHub username.
37
38** Step 4
39
40Wait for your DNS changes to propagate. DNS changes aren't effective
41immediately. They can take up to a full day to propagate.
42
43* Long answer
44
45This issue has two sides. One is the DNS configuration itself. Another one is
46the way GitHub Pages will forward hypertext transfer protocol (HTTP) requests.
47
48We need to know a few things to understand what GitHub is trying to say in their
49documentation.
50
51** DNS Entry Types
52
53There are two types of DNS records which interest us: CNAME and A.
54
55=A= is also known as =Apex= or sometimes as =root entry=. It forwards requests
56to a specified fixed IP address. =CNAME= entry forwards requests to a specified
57URL (actual valid plain text URL, not an internet protocol (IP) address).
58
59** DNS Load balancing
60
61GitHub has one central URL address which accepts all DNS requests for GitHub
62Pages: =http://username.github.io=. That URL is resolved to different IP
63addresses based on your geographical location. Website hosted on GitHub Pages is
64a simple collection of =HTML=, =CSS= and =JS= files. GitHub distributes these
65files to different servers across the globe. So that when your browser sends a
66request from Europe, it receives data from a server in Europe. The same is valid
67for the requests from Asia and the USA.
68
69** What GitHub is trying to say
70
71Since =A= records in DNS must contain IP addresses, and they must be either
72=185.199.108.153= or =185.199.109.153= or =185.199.110.153= or
73=185.199.111.153=, there is no way to forward requests to a server located
74somewhere in Europe or Asia. Your website hosted at GitHub Pages will be
75downloaded from a central GitHub Pages server. There is a minor risk that if
76GitHub Pages DNS servers (=x.x.x.153=) are down for some reason, all custom
77domains which use fixed GitHub Pages IP addresses will not be accessible (their
78DNS requests will not be resolvable).
79
80That is why GitHub strongly suggests to either use a second-level domain for
81your GitHub Pages (e.g. =blog.example.com=) or use a DNS service provider that
82supports a record type =ALIAS= that acts as =A= record but forwards request to a
83URL address (e.g. =username.github.io=) instead of a fixed IP address.
84
85** How GitHub Pages treats HTTP requests
86
87After a DNS request for =your_github_username.github.io= is resolved into an IP
88address, e.g. =185.199.108.153= your browser sends an HTTP request to that
89server with an HTTP header =Host=. Below are =curl= examples that load the same
90website (these examples might not work if you are behind a proxy server):
91
92#+begin_src sh
93curl --header "Host: your_github_username.github.io" http://185.199.108.153/
94curl --header "Host: www.example.com" http://185.199.108.153/
95curl --header "Host: example.com" http://185.199.108.153/
96#+end_src
97
98This way GitHub Pages servers know which user website to serve.
99
100#+begin_quote
101GitHub Pages server will automatically redirect HTTP requests to the top-level
102domain if your =CNAME= file contains =example.com= but =www.example.com= is
103requested.
104
105The same is valid if your =CNAME= file contains =www.example.com= but the header
106=Host= in the =HTTP= request contains =example.com=.
107#+end_quote
108
109** Why can't I add a =CNAME= record entry that accepts a top-level request (=@=) to my DNS configuration?
110
111Quote from the GitHub Pages documentation:
112
113#+begin_quote
114Warning: Do not create a CNAME record for your custom apex domain! Doing so may
115cause issues with other services, such as email, on that domain.
116#+end_quote
117
118** References:
119
1201. [[https://docs.github.com/en/github/working-with-github-pages/configuring-a-custom-domain-for-your-github-pages-site][Setting up a custom domain with GitHub Pages]]
1212. [[https://docs.github.com/en/github/working-with-github-pages/troubleshooting-custom-domains-and-github-pages][My custom domain isn't working]]
1223. [[https://serverfault.com/questions/589370/cannot-access-my-github-pages-website-by-ip-address][Cannot access my GitHub Pages website by IP Address]]
1234. [[https://stackoverflow.com/questions/23375422/how-do-i-set-up-github-pages-to-redirect-dns-requests-from-a-subdomain-e-g-www][How do I set up GitHub Pages to redirect DNS requests from a subdomain (e.g.
124 www) to the top-level domain (TLD, Apex record)?]]