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: However, if you try to access it you’ll be redirected to 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
 2HTTP/2 301
 4content-type: text/html
 6# ...
 7content-length: 162
10<head><title>301 Moved Permanently</title></head>
12<center><h1>301 Moved Permanently</h1></center>

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:


… and create the CNAME file in the root of your repository with the new domain:

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 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.


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 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;
3  return 301;

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:

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.


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
 2HTTP/1.1 301 Moved Permanently
 3Date: Thu, 04 Jan 2024 09:47:53 GMT
 4Server: Apache
 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:

1<body onload="window.location = ''">
2    <!-- ... -->

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=" />

To use this, we need to set up a website under, that will have the correct meta refresh tag. However, due to the fact that the domain is already associated with my GitHub account, I had some issues with making the subdomain work. As a workaround I’ll switch to 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:


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>
     3    <head>
     4        <meta charset="utf-8" />
     5        <meta http-equiv="refresh" content="0; url=" />
     6        <link href="" rel="canonical" />
     7        <title>Redirecting to</title>
     8    </head>
     9    <body>
    10        <a href="">Redirect</a>
    11    </body>
  • CNAME to point to GitHub which subdomain it should use:

See the full setup here: redirect-example.

Alright, let’s see if our new DNS record has propagated:

1$ dig CNAME +noall +answer
3; <<>> DiG 9.10.6 <<>> CNAME +noall +answer
4;; global options: +cmd 3233 IN CNAME

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
 2HTTP/2 200
 4content-type: text/html; charset=utf-8
 5# ...
 6content-length: 356
 8<!DOCTYPE html>
10    <head>
11        <meta charset="utf-8" />
12        <meta http-equiv="refresh" content="0; url=" />
13        <link href="" rel="canonical" />
14        <title>Redirecting to</title>
15    </head>
16    <body>
17        <a href="">Redirect</a>
18    </body>


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.