Wildcard Sub-Domains

How to configure a Digital Ocean droplet for multiple domains and wildcard subdomains

April 21, 2016

When I began moving my various personal domains to a new droplet on Digital Ocean, I had a few requirements that I wanted for my set up:

  • I wanted to be able to host multiple domains (we have a few different family domains).
  • I wanted to be able to add custom (wildcard) sub-domains for my personal domain, preferably without having to mess with Apache config files and restart the server each time.
  • I wanted any non-existent sub-domains to redirect to my primary domain.

It took a bit of research, but here’s how I did it.

Setting up virtual hosts

First, I created a new droplet on Digital Ocean from the LAMP 14.04 One-Click image. This sets up a new droplet with Linux, Apache, MySQL, and PHP. (I’d used these for most of the sites I was moving over.) Then I used this great guide for setting up virtual hosts on Digital Ocean. The basic process is as follows:

  • Create individual domain.com/public_html folders for each domain under /var/www.
  • Set the owner/group for each domain to your account.
  • Put placeholder pages inside the public_html folder under each domain. (Optional but helpful for verifying that stuff is working before you move real files over.)
  • Create Apache config files for each domain
  • Enable the new virtual domains for each site using the config files you just created.
  • Restart the Apache server
  • Pointed my local /etc/hosts file at the new droplet to test.

Boom! Now I can host multiple domains on a single droplet. Next I needed to get wildcard sub-domains up and running for a specific domain.

Adding in wildcard sub-domains

First of all, I set up a CNAME record in my domain’s DNS settings with a name of * and a value of @. That will automatically redirect any sub-domain for the domain to the same address as the primary domain. (If you want to add explicit sub-domains pointing elsewhere, you’ll need another CNAME record with the name and IP address for the other server.) Once I had the wildcard set up in my DNS settings, I had to set up Apache to recognize it. It took a bit of searching to find the right details for adding wildcard sub-domains, but I finally stumbled across this answer on Stack Overflow that I adapted to solve my problem. The key bit was this:

<VirtualHost *:80>
        VirtualDocumentRoot /var/www/domain.com/subdomains/%1/public_html
        ServerAlias *.domain.com

It’s placed after my primary domain VirtualHost directive, and acts as the wildcard for whatever sub-domain catches your fancy. Defining a VirtualDocumentRoot allows you to dynamically determine the location of your sites’ documents on the server based on portions of the domain name the client used to get to your host. For instance, the %1 above refers to the first part of the domain name (aka the sub-domain). In other words, if a visitor goes to test.domain.com in their browser, this directive tells Apache to look for files for that domain at /var/www/domain.com/subdomains/test/public_html. After that, I created the subdomains folder inside my primary domain folder, then added folders for any sub-domain I wanted underneath (with a public_html inside) — for instance, a gifs sub-domain and various other project-related sub-domains, etc.

If you have trouble falling asleep, enjoy reading more technical documentation, or want to play around with other ways of using dynamic domains, there’s a lot more detail about this in the mod_vhost_alias Apache Module documentation.

So that’s it, right? Not quite. If you look at that bulleted list at the top one more time, you’ll see three points listed and so far we’ve only addressed two of them. Let’s look at how I handled the last one.

Redirecting MIA sub-domains

I could leave the solution at that. But I hate the possibility that someone could try to go to theamazing.stegrainer.com and be presented with an error page. (That’s not amazing at all!)

So the last tricky little bit is how to deal with sub-domains that don’t have a directory on the server. This is where my Google-fu utterly failed me. Every permutation of searching I attempted ultimately ended up at a solution that didn’t work properly (or worse, broke what was already working). I nearly gave up, though I knew it had to be possible.

Then I had a small epiphany: even if the domain wasn’t found, the server was still returning a 404 page. I could harness that to redirect from the 404 page to the primary domain! I added a new line to my wildcard directive:

ErrorDocument 404 http://domain.com/

This defines a new error location for any missing pages on the wildcard sub-domains. Now, whether you go to The Amazing Ste Grainer or The Silly Ste Grainer, you’ll get redirected to my primary domain. At least until I decide to use those ...

Here’s the final Apache config…

<VirtualHost *:80>
        ServerAdmin webmaster@domain.com
        ServerName domain.com
        ServerAlias www.domain.com
        DocumentRoot /var/www/domain.com/public_html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
<VirtualHost *:80>
        VirtualDocumentRoot /var/www/domain.com/subdomains/%1/public_html
        ServerAlias *.domain.com
        ErrorDocument 404 http://domain.com/