Redirecting Subdomains to URLs

6 min Kamil Rusin

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:

NameTypeContent/TargetTTL
@A185.199.108.153600
@A185.199.109.153600
@A185.199.110.153600
@A185.199.111.153600
@AAAA2606:50c0:8000::153600
@AAAA2606:50c0:8001::153600
@AAAA2606:50c0:8002::153600
@AAAA2606:50c0:8003::153600
wwwCNAME<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.

1server {
2  server_name calendar.madebyme.today;
3  return 301 https://example.com/;
4}

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:

NameTypeContent/TargetTTL
subdomainCNAMEredir301.link.600
301.subdomainTXT<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

If you’re planning on changing your DNS records and are unsure about the changes, then I’d suggest to do so first via mess with dns, a tool by Julia Evans and Marie Claire LeBlanc Flanagan. It’s a service for performing experiments with DNS. Anyone can set up their DNS records and test with them for free.

By following the guide we’ve got:

mess with dns configuration for Redir 301

Click on the image for the full size.

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 https://redir301.link/ 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:

1<body onload="window.location = 'https://example.com/'">
2    <!-- ... -->
3</body>

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:

NameTypeContent/TargetTTL
exampleCNAMEnathiss.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.

GitHub Pages configuration for redirect-example repository

Click on the image for the full size.

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.

GitHub Pages configuration with custom domain and enforced HTTPS

Click on the image for the full size.

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.