Cloudflare Domain Redirect Rules from Root (@) to www Subdomain


It took me a bit of fiddling around to get 301 redirects working from the root (@) of a domain to the www subdomain.

For example, if I user requested https://gaurav.io/path/to/somewhere?foo=bar, I’d want them to get a 301 Moved Permanently redirect to https://www.gaurav.io/path/to/somewhere?foo=bar.

CloudFlare offers powerful Redirect Rules that can get this done, but googling around community posts proved less than helpful on how exactly to get this done, especially on their free plan. So, might as well document it here since this blog (for now, at least) is powered using CloudFlare Pages with a custom domain (and that too for free, I might add 😬).

First off, you’d only want to associate one domain with the CloudFlare Pages deployment – the domain itself. It’s a mistake to treat domain.com and www.domain.com as two separate domain names. They might be two separate host names, but they’re the same domain name.

When you register domain.com through a registrar (like GoDaddy, NameCheap, Google Domains, etc), you’re only paying for it once – you don’t need to pay and add your details again for pointing www.domain.com somewhere if you’ve already registered and paid for domain.com. So, this is a nice mental model to understand that domain names are domain.com (or more generally, the $your-unique-name.$tld scheme). Therefore, you just associate the domain.com custom domain with your CloudFlare Pages deployment, the official documentation for which is quite straightforward.

CloudFlare Pages with a Custom Domain

To extend this mental model, when a user makes a request to a domain name, they generally do so to [subdomain]domain.com (or more generally to ($subdomain.)?$your-unique-name.$tld schema). When the subdomain is missing, it is assumed to be the root/apex/naked/@ subdomain. By convention, the public website for a domain has historically been served on the www subdomain (so www.domain.com would serve the website for domain.com), but there’s no hard rule around this.

I’m not sure if there’s any consensus around best practices, but I personally like all content on a domain name to be served via a subdomain – so, I still serve the default public website via the www subdomain as has been the widely accepted historical convention. I know a lot of websites serve the default public website on the root subdomain, but I feel there’s something not quite right with it (while I can make some technical arguments around why it’s not a good idea, they’re strawman arguments at best, there’s nothing inherently wrong with it but to me it feels a little off).

In either case, whether you’re serving the default public website via the root subdomain or the www subdomain (or something completely different like a blog subdomain), what you really should be doing is setting up redirects so that the other possibilities redirect to the subdomain where you’re serving the content.

So, whenever someone (even an indexing bot) is assuming where you might be serving content, they at least get pointed to the right destination. Normally, in the self hosted scenario, you can point subdomains (including the @ subdomain) to your server using A records and then your web server/proxy like Nginx can handle the redirect.

In our case, CloudFalre offers powerful Redirect Rules for managed domains that can perform the same redirect for us. In our case, we need a single rule that has the incoming condition as:

(http.request.full_uri wildcard "https://domain.com/*")

and has a Dynamic forwarding expression of:

concat("https://www.domain.com", http.request.uri)

with a status code of 301 and Preserve query string checkbox ticked.

CloudFlare Domain Redirect Rule

Once this rule is enabled, you should have the redirects working fine. This also works with their generous free plan (I tried initially with regex_replace function which didn’t work because it needed a paid plan).