The New Digs: My Server Setup
June 6, 2018
When I learned that Microsoft had acquired GitHub, I first thought about migrating to Bitbucket because they have unlimited free private repos. But then I remembered that I had tried building a public site using their “pages” feature (similar to GH Pages) several years ago, but had been disgusted by the fact that the pages always came wrapped in an iframe. So, I tried migrating to GitLab a couple of days ago. At first, all seemed well, but the process of getting their “pages” feature working was an absolute pain in the ass. Whereas GH Pages could be up and running in two clicks, GL Pages required config files and pipelines, none of which I understood. I’m sure they want to provide a greater degree of customization than GH, but they should still provide a few one-size-fits-all sane defaults for popular static site generators. Plus, their documentation didn’t match my experience; the tutorials and examples were scattered around, and they didn’t all match. I ended up turning to StackOverflow for help. And when I finally got it all going, Jekyll’s blog links were broken and could only be fixed by appending “.html” to each post URL. So, in the end, I decided to push my repos to Bitbucket and to build an Express server on a DigitalOcean droplet to host my sites. This site, for example, is running on that server. I’m writing this post primarily to document how I did it so that I can remember later when I inevitably have to relearn the process. So, here it is!
1. Basic Setup
I created the cheapest possible droplet on DO. It’s running Ubuntu 16.04 and costs $5 per month plus a little for outgoing bandwidth. Then I went to my domain registrar and pointed my domains’ A records to the server’s IP address.
On the server, I started by creating a
Then I logged in with that user and installed LinuxBrew.
Then I used LinuxBrew to install Node and Ruby, and then Jekyll and
I knew I’d need to serve my sites over https, so I installed Certbot, which supplies Let’s Encrypt certificates.
Also, since I wanted to be able to connect to my Bitbucket repos over SSH, I copied the SSH keys from my machine to the server.
2. Let’s Encrypt
To prepare for getting my TLS certificates, I made a folder that would eventually contain all of the interesting server stuff, which I just called
mother-base. I moved into that folder, made a folder called
public, and wrote a little Express app. This app, as you can probably tell, simply serves the
public folder on port 8080. I called this file
However, the Certbot process works over port 80, not 8080. So, I had to reroute port 80 to 8080 using
I ran this app with
Then, I ran Certbot to get my TLS certificates. Since I planned to use multiple domains on this server, it was necessary for me to list all of those domains in this single command so that all of the domains would end up on the same certificate. I also learned the hard way that Certbot only allows 5 failed certification attempts per hour. I made lots of little mistakes along the way and got locked out for an hour. But then I learned that it’s possible to use the
--dry-run flag to test out the process before spending a real attempt.
Then I stopped the
The new certificates were inaccessible to my user, even with
sudo privileges. For example,
sudo /etc/letsencrypt/live failed. So, I had to fix the permissions.
Then, I created a folder called
tlscert in which I created symlinks to the relevant certificate files.
After turning the
mother-base folder into a git repo, I added my websites as submodules, cloned them into the
public folder, and committed them to the
Because this site is built with Jekyll, I moved into the newly-cloned folder and built it.
Here’s the whole Express server.
Once that was set up, the only thing left to do was to configure
iptables to forward port 443 to port 8443.
5. Going Forward
There are still a few things I’d like to fix.
- I need to create a cron job for the Certbot renewal process (since the certificates only last for 90 days).
- I need to create hooks so that my Jekyll sites are automatically rebuilt any time changes are pushed to the repos. Right now, the process is manual.
- I need to make sure that I’ve got as many security hatches battened down as possible. I know nothing about this, so it’ll be a learning process.
- I need to configure time-to-live headers / caching stuff. I know nothing about this either.
- I need to learn more about vhosts, since I’d like to be able to write regular Express apps and pass them to vhosts rather than simply serving static files.
So, yep. That’s it!