Creating a Dynamic Public Folder With Apache
What a mouthful for a blog title, right? I wasn’t sure what to call this, but basically, it’s a small post which tells you how to dynamically create public HTML folders, so that you can instantly switch between them when deploying on Linux with Apache. Zero-downtime, if you like…or almost zero.
Let’s expand on that a little with what my old process was. Imagine this: I have just finished my latest can of Pepsi Max and have decided to write a new blog post and publish it. Skipping all the creative, finger tapping and Git related parts, I log on to the server, and run my build script.
It’s quite fast to be fair, but it can take anything up to a minute whilst it removes the public folder and regenerates all the static files. Meanwhile, Doris, my loyal reader from somewhere in Scotland, tries to go to my website and it seems like it’s down. Well, naturally, it is down because there is no public folder and nothing to see. Or worse, it’s in a kind of limbo state, partially created, whilst the build script chugs away. That’s why zero-downtime seems so appealing.
Wouldn’t it be good if we could leave our current site alone whilst we mosey-on-around, taking our time to generate the new version of the site, and once complete, switch them over, like magic? Instantly swapping and achieving that desirable (almost) zero-downtime - lovely. Well, here’s how you can do it.
For this, I am using an Ubuntu system running Apache, with Hexo as my static site generator, but the process can easily be adapted for for other systems and configurations. Also, it’s worth pointing out that I haven’t made any effort to remove the old folders that were deployed (you’ll see what I mean in a minute). That’s deliberate because for now, I quite like the idea of being able to switch back to an old version, at will. When I find I have hundreds of them, I am sure I will feel rather differently!
To begin, let’s chop this post into four pieces - you can use just the bits you need:
- Finding out what your public folder is
- Changing the generated output folder in Hexo
- Generating a new dated folder to store your public HTML files
- Hotlinking your website’s named folder, to your dated folder
Your Public Folder
Let’s see what the currently served folder is for your website in Apache. For me, that was the public folder. In my case, the configuration for this is in the file:
1 | /etc/apache2/sites-enabled/logicalmoon.com.conf |
You may very well have named your configuration file something differently. Poking inside, though, we can see the name of my final public folder and again, yours may be something else:
1 | DocumentRoot /var/www/logicalmoon.com/public/ |
OK, so public it is; remember that because we’ll need it.
Changing the Hexo Output Folder
Back to my website’s folder, I can see that I already have a folder in there named public which also happens to be the default output folder in Hexo.
1 | $ ls -ld public |
Let’s alter that destination folder using Hexo’s configuration file. We’re going to use another name - publichtml instead. The name can be what you prefer, and of course, you’d swap this step with whatever method for altering your destination folder/generator.
Open up the configuration file for editing:
1 | $ nano _config.yml |
and change this line into the name you want:
1 | public_dir: publichtml |
Hang on! Why don’t I just leave things going into public and use an alternative named folder in the Apache configuration? You could, of course, but I quite like using public
so want to keep it, that’s all.
Time to take stock of where we’re up to. Till now, we’ve knackered our website (sorry, Doris) and changed the output folder in Hexo. We’d better move quickly to actually create a new set of static files!
In a flash, we re-generate our output files from static data:
1 | $ hexo clean |
We now have a new folder named publichtml
, ready to use.
Generating a Dated Folder
Next, let’s work out what we will call our new (dated) folder. We’ll use the current date and to handle cases where we might run it more than once a day, we’ll add in the epoch time. That’s just a fancy phrase meaning the number of seconds since the 1st of January, 1970. What’s good about it though is that it will be really hard (though not impossible) for us to create two folders with the same name because, as you know, time keeps ticking. Note: I could also just use the epoch time alone but it’s really handy seeing a human readable date, too. Enough chit-chat - let’s generate it.
1 | $ filename="hexo"`date +"%Y%m%d.%s"` |
We’re making progress, but how are we going to actually use a folder with that name? Well, firstly, let’s rename publichtml
to be that calculated name, to make space for another build later but also keep our historical output separated.
1 | $ mv publichtml $filename |
Hotlinking Our Public Folder
But what about the public
folder we mentioned earlier in our Apache configuration file? The trick here is that it won’t actually be a folder, but instead, a symbolic link to the real folder, and just named public
.
In code, let’s make sure it doesn’t already exist because if it does, we want to remove it.
1 | $ if [ -L public ]; then |
Woosh! Gone. The -L option is testing for the existence of a symbolic link, and in the case, obviously that being public
. If we find it, we echo something to the screen and remove it.
We just need to create the final (new) symbolic link, now.
1 | $ ln -s $filename public |
Here’s what our directory listing looks like once we have run all of these commands:
1 | $ ls -l |
A quick visit to my website confirms all is well. Phew!
Finishing Off
The only thing left to do is to put all of this into one build script and run it each time we deploy. Here’s that script to save you a little effort which you can paste into a file named something like build.sh
:
1 | #! /bin/bash |
If you wanted to improve it more, you could use absolute path names instead of the relative ones, I have (/var/www/...
rather than just public
) and also add something in to remove old folders, if you like.
Right - I have a new blog post to deploy!
Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com