Jack Atkinson

Science, Archery, Computing

Jack Atkinson's Website

Jack Atkinson

Science, Archery, Computing

Setting up a Subdomain

5 minutes
March 14, 2026

Recently I wanted to add a subdomain to one of my websites. Last time I tried this I made a massive mess of my server and apache setup and gave up before restoring the server from a snapshot. Recently I tried again with more success so decided to document the process for future reference.

There are some large upcoming updates to archerycalculator.co.uk as part of the 2026 classification updates.

Previously I would always check locally and hope for the best before deploying. This invariably led to errors that had to be sorted out with hotfixes and live coding on the server. For a while I knew the ideal solution would be to have a subdomain where I could deploy the development version of the site to check things before deploying the branch to production.

1. Add a subdomain record to your name server

Go to your DNS provider and add an “A” record to point at your subdomain. An A (Address) record maps a domain name to an IP address.

We will add a subdomain staging.archerycalculator.co.uk to point at the IP address of my server. The server will then handle routing to the correct site (see below).

Specifically for my provider, DigitalOcean, this required: Networking -> Domains -> archerycalculator.co.uk -> Add a new record. Add the hostname of staging (i.e. staging.archerycalculator.co.uk) and direct it to the droplet upon which the site will reside.

Set TTL (time to live - how long DNS servers cache the record) as 12 hours - this site is not for public consumption so we can have a slow and low intensity option.

Recall: A is domain name to IPv4, AAAA is domain name to IPv6, and CNAME maps domain name to another domain name.

2. Create new website content on the server

This is one of the places I went wrong last time. I didn’t realise that from the server side the subdomain site is a completely separate website.

This time I added a new site under /var/www/staging_site/.

Initially this contains just index.html with:

1
2
3
4
5
6
7
8
<html>
    <head>
        <title>www.example.com</title>
    </head>
    <body>
        <h1>Success: You Have Set Up a Virtual Host</h1>
    </body>
</html>

3. Set up a new site to be served under apache

Where I really made a mess of everything last time was trying to add the subdomain to the existing config file for archerycalculator.co.uk . Instead, following the separate site ethos above, I set up a brand new config file staging_mysite.conf in /etc/apache2/sites-available to serve the above example page as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<VirtualHost *:80>
    ServerName staging.archerycalculator.co.uk
    DocumentRoot /var/www/staging_mysite/
    <Directory /var/www/staging_mysite/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/staging_error.log
    CustomLog ${APACHE_LOG_DIR}/staging_access.log combined
</VirtualHost>

Remember you can use sudo apache2ctl configtest to check that the syntax of any config files is valid.

Note to self - recall DocumentRoot is where the site will point to and serve files from. Directory sets permissions for a directory. It can be different from DocumentRoot and there could be multiple Directory entries that apply different permissions to different directories.

4. Serve website!

Enable the site under apache (creates a symlink from sites-enabled/) and reload:

1
2
sudo a2ensite staging.archerycalculator.co.uk
systemctl reload apache2

Now navigating to the subdomain address in a browser should show you the simple success message.

5. SSL Certificate

Next we can get a certificate from Let’s Encrypt using certbot :

1
sudo certbot certonly --apache -d staging.archerycalculator.co.uk

Never let anyone try and charge you ££s for a certificate!

Note to self - not using certonly will lead to certbot generating a new apache conf file with a -le-ssl suffix to add certification to the site and then enable it. If you subsequently modify your original config and do not see changes reflected it is because the site is being served from this new file. This caused me to chase my tail for lengthy period when doing this. It’s easier to just get the certificate and then add it manually with:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<VirtualHost *:80>
    # Redirect HTTP to HTTPS
    RewriteEngine On
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
    ServerName staging.archerycalculator.co.uk
</VirtualHost>
<VirtualHost *:443>
    ...
    # SSL Configuration
    SSLCertificateFile /etc/letsencrypt/live/staging.archerycalculator.co.uk/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/staging.archerycalculator.co.uk/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
    ...
</VirtualHost>

6. Prevent indexing

Since this is a staging area for the main site I don’t want search engines to be crawling and indexing this, directing people here instead of the main site.

Add robots.txt under the DocumentRoot as follows:

1
2
User-agent: *
Disallow: /

to prevent it from being indexed, and add

1
Header set X-Robots-Tag "noindex, nofollow"

to the bottom of the apache VirtualHost config as further reinforcement.

7. Install actual website

Now we can place our actual website/web app under the DocumentRoot and update the apache conf file as desired to serve this. Just remember to reload apache to see the changes.

Other useful apache things

A couple of other useful things I came across whilst doing this, not directly related to the setup process, that I’ll preserve here:

The following snippet added to the apacheconf:

1
2
3
4
5
<Directory /var/www/mysite_staging>
    Require all granted
    Options -Indexes
    AllowOverride None
</Directory>

allows apache access to the full website directory, but prevents directory indexing for security and prevents overrides by a .htaccess file.

Rather than setting the Python environment in the wsgi file that is invoked from apache we can set it directly in apache as part of the WSGIDeamonProcess using:

1
2
3
4
5
WSGIDaemonProcess staging.archerycalculator.co.uk \
    python-path=/path/to/venv/lib/python3.x/site-packages \
    processes=1 \
    threads=5 \
    display-name=%{GROUP}

Note we also set the number of processes and also threads here. We can set threads low as this is a staging/test site so are not expecting much action.

We still use:

1
WSGIScriptAlias / /path/to/entrypoint.wsgi

in the apache config to set the entrypoint for the app as the .wsgi file.

Oh, and the staging site is now up and running at staging.archerycalculator.co.uk/ .