Redirecting Subdomains to URLs
Table Of Contents
This blog is hosted on GitHub Pages. The service offers free static website hosting (TLS included!). The way it works is that GitHub issues a dedicated subdomain for each hosted website; for this one it’s: nathiss.github.io. However, if you try to access it you’ll be redirected to madebyme.today instead.
I’ve set up a custom domain, and GitHub is kind enough to respond with 301 Moved Permanently to requests using the old subdomain.
1$ curl -i https://nathiss.github.io/
2HTTP/2 301
3server: GitHub.com
4content-type: text/html
5location: https://madebyme.today/
6# ...
7content-length: 162
8
9<html>
10<head><title>301 Moved Permanently</title></head>
11<body>
12<center><h1>301 Moved Permanently</h1></center>
13<hr><center>nginx</center>
14</body>
15</html>
Let’s take a closer look and see how it’s done.
Setting up custom domain for GitHub Pages
GitHub Pages supports custom domains with very little config; you, as the owner, only need to set up these DNS records:
Name | Type | Content/Target | TTL |
---|---|---|---|
@ | A | 185.199.108.153 | 600 |
@ | A | 185.199.109.153 | 600 |
@ | A | 185.199.110.153 | 600 |
@ | A | 185.199.111.153 | 600 |
@ | AAAA | 2606:50c0:8000::153 | 600 |
@ | AAAA | 2606:50c0:8001::153 | 600 |
@ | AAAA | 2606:50c0:8002::153 | 600 |
@ | AAAA | 2606:50c0:8003::153 | 600 |
www | CNAME | <username>.github.io. | 600 |
… and create the CNAME
file in the root of your repository with the new domain:
1example.com
The last thing to do is to enable GitHub Pages for your repository. GitHub will validate DNS records and serve the
website under the configured domain. Anyone accessing https://example.com
will see your website.
It’s pretty well explained in About custom domains and GitHub Pages, and Managing a custom domain for your GitHub Pages site.
Note
Optionally, you may want to verify your domain for GitHub Pages; it prevents other users from taking over your domain. It can happen when your GitHub Pages site gets disabled one way or another.
See Verifying your custom domain for GitHub Pages for details.
Using domains as aliases
Recently I came up with an idea to configure subdomains, that will redirect to a few tools I’d like to make accessible
online. For example calendar.madebyme.today
could be a redirect to my GCalendar.
However, DNS can’t be used like that. It’s a name resolution system – it knowns nothing about HTTP. If I’d host my own web server, then I could configure it to do redirects with the proper 301 status code.
Snippet below shows an example config with
Nginx’s server_name
.
However, that’s not the case and, as far as I know, GitHub does not provide any way of setting up HTTP redirects for GitHub Pages.
Redir 301
Redir 301 is a service that uses DNS records to redirect subdomains to URLs. It requires two DNS records in order to work:
Name | Type | Content/Target | TTL |
---|---|---|---|
subdomain | CNAME | redir301.link. | 600 |
301.subdomain | TXT | <destination URL> | 600 |
Let’s test it, shall we?
I’d very much prefer not to mess with my current DNS records, so let’s use mess with dns for this experiment.
Tip
By following the guide we’ve got:
Let’s wait for the DNS records to propagate… 🕓
…and when we request the subdomain:
1$ curl -i http://calendar.aster176.messwithdns.com
2HTTP/1.1 301 Moved Permanently
3Date: Thu, 04 Jan 2024 09:47:53 GMT
4Server: Apache
5Location: https://example.com/
6Cache-Control: no-cache, no-store, must-revalidate
7Pragma: no-cache
8Expires: 0
9Transfer-Encoding: chunked
10Content-Type: application/cgi
…it returns 301 with the Location header :thumbs_up:
It’s worth to point out that it does not support HTTPS, only HTTP. It’s a Redir 301 limitation; the free tier of the service does not offer TLS certificates.
Additionally, as stated by the owner, a “fair use” policy applies to Redir 301. There’s a non-zero cost to run the service, so if you decide on using the system, please consider donating the maintainer. See
for details.Redirecting with GitHub Pages
The HTTP Location header isn’t the only way of redirecting to a URL. Another method is to use JavaScript, and the simplest way to achieve this is:
This approach is not recommended, because users might have disabled JavaScript in their browsers.
Yet another way is to inform the browser to perform the redirection for us; that can be done via the meta refresh tag:
1<meta http-equiv="refresh" content="0; url=https://example.com/" />
To use this, we need to set up a website under calendar.aster176.messwithdns.com
, that will have the correct meta
refresh tag. However, due to the fact that the domain madebyme.today
is already associated with my GitHub account, I
had some issues with making the calendar.aster176.messwithdns.com
subdomain work. As a workaround I’ll switch to
example.madebyme.today
from now on.
Let’s set up required DNS records first, to give them time to propagate. Since I already have my domain configured to be used by GitHub Pages, I only really need to add one more record:
Name | Type | Content/Target | TTL |
---|---|---|---|
example | CNAME | nathiss.github.io. | 1h |
With that out of the way, we can create a new repo.
We need two files:
index.html
with the meta tag:1<!DOCTYPE html> 2<html> 3 <head> 4 <meta charset="utf-8" /> 5 <meta http-equiv="refresh" content="0; url=https://example.com/" /> 6 <link href="https://example.com" rel="canonical" /> 7 <title>Redirecting to https://example.com</title> 8 </head> 9 <body> 10 <a href="https://example.com/">Redirect</a> 11 </body> 12</html>
CNAME
to point to GitHub which subdomain it should use:1example.madebyme.today
See the full setup here: redirect-example.
Alright, let’s see if our new DNS record has propagated:
1$ dig example.madebyme.today CNAME +noall +answer
2
3; <<>> DiG 9.10.6 <<>> example.madebyme.today CNAME +noall +answer
4;; global options: +cmd
5example.madebyme.today. 3233 IN CNAME nathiss.github.io.
It has indeed.
The last thing to do, is to enable GitHub Pages for the new repo. Go to Settings > Pages
.
Select a branch and a folder your site will be served from. GitHub automatically picks up custom domain name configured
in the CNAME
file. Wait a moment for it to perform some DNS checks and to provision a new TLS certificate for your
subdomain, then enable HTTPS enforcement for your site.
All parts should be in place, let’s check if it works:
1$ curl -i https://example.madebyme.today/
2HTTP/2 200
3server: GitHub.com
4content-type: text/html; charset=utf-8
5# ...
6content-length: 356
7
8<!DOCTYPE html>
9<html>
10 <head>
11 <meta charset="utf-8" />
12 <meta http-equiv="refresh" content="0; url=https://example.com/" />
13 <link href="https://example.com" rel="canonical" />
14 <title>Redirecting to https://example.com</title>
15 </head>
16 <body>
17 <a href="https://example.com/">Redirect</a>
18 </body>
19</html>
🎉
If a browser respects the meta refresh tag, then it works. When it doesn’t, the user has an option to manually click on the “Redirect” link.
Conclusion
Redirects via GitHub Pages is not an ideal solution. Having to use meta’s http-equiv="refresh"
, instead of the proper
301 Moved Permanently makes me sad. Having said that, personally, I’d prefer to use GitHub Pages, as the backing
service, rather than Redir 301.
The only benefit of Redir 301 over GitHub Pages is the 301 status code with the Location header. However, it’s reasonable to assume that vast majority of modern browsers supports (and does not block) the meta refresh tag.
I think GitHub Pages can prove to be a more reliable service in the long run, plus it provisions free TLS certificates out-of-the-box.
I’d love to hear about other approaches of doing domain-to-URL redirects without a self-hosted web server. Let me know in the comments what works for you.
Interested in my work?
Consider subscribing to the RSS Feed or joining my mailing list: madebyme-notifications on Google Groups .
Disclaimer: Only group owner (i.e. me) can view e-mail addresses of group members. I will not share your e-mail with any third-parties — it will be used exclusively to notify you about new blog posts.