The Most Complicated Way to Build a Site

The Most Complicated Way to Build a Site

It feels like I’ve been changing how my website works for as long as it’s been alive. It started as a WordPress site, then ran Octopress for a while, but three years ago I changed it over to Jekyll, running the Skinny Bones theme. I’m pretty happy with that choice.

Unlike a traditional CMS, Jekyll builds my site offline. There is no back-end and the site is just pure HTML from the user’s perspective. Because there is no back-end, Jekyll isn’t susceptible to viruses or hackers, like a traditional CMS. I don’t need to constantly update the site just to keep it safe and working.

Which doesn’t mean that I don’t. Learning to use Jekyll has been part of the fun, but it sure takes some learning. Originally, I built my site offline and used FTP to move it to my university’s server. I did this for a while before realizing there was a much easier option: GitHub Pages. GitHub Pages supports Jekyll by default, so I didn’t have to do any extra work: I pushed a new version to GitHub and it built a new version of the site. It was great. I bought a domain, pointed it at GitHub and I had free hosting.

This worked for a while, but then an update to Chrome changed how it handled security and suddenly everyone visiting my site got a scary warning. It was hosted on GitHub, but the address wasn’t a GitHub address so Chrome warned everyone of my clever misdirection. Getting security warnings isn’t an optimal way to start a visit to a site, so I had to do something.

I tried some other alternatives and ran into some problems, but eventually I figured out a way to make everything work. The setup works, but is incredibly complex for a simple personal website. It does have it’s perks: there is no CMS, changes are saved by git so I can’t lose anything important even if I mess up, I can work with the site offline – or use an online editor, if I want to.

Here’s the setup I ended up with:

I have local copies of the site on all computers I usually work with, but the site is actually stored on GitHub. This means that when I want to make changes – like post a new blog post – I usually work with an offline copy and push the changes I made to GitHub. Not always, though. There is a front-end for editing Jekyll-based websites on GitHub that I’ve used on several occasions: Prose. Using Prose is a bit like writing on a WordPress site, but just on GitHub.

After I’ve written a post or changed something, the changes need to actually happen on the live website. This happens in two stages.

First, CircleCI checks out the latest version of the site from GitHub automatically. It runs the same build commands I would use offline in a virtual machine and builds a new version of the site. The result is run through a light checkup to see that nothing went wrong – that there are no broken links, for example. If something goes wrong, CircleCI stops and I get a warning in my email.

If everything went well, CircleCI uses a simple rsync command and copies the resulting website to my hosting provider. What ends up there is a simple list of HTML files, checked for errors and less than 10 MB total in size. The journey from command line to GitHub to CircleCI to my hosting provider is quite a round-trip, but at least it works the way I wanted it to. The same setup could be used for a much more complicated site and it would benefit from the same speed, light weight and error-checking as this site.

Setup guide

Here’s a short guide of what you need to do in order to get the same setup working. I’m assuming you know how to install things on the command-line and use git, so I won’t explain the details here.

1. Get Jekyll

Technically, you don’t need a local install of Jekyll. You can build the site on a remote machine that already has Jekyll, but it’s probably easier if you first test that everything works locally. Installing Jekyll could be a bit easier, but basically you need Ruby, RubyGems and some build tools.

2. Build your site

Get yourself a local copy of Skinny Bones, or some other Jekyll template. If you want to build the site yourself, Jekyll can also create a simple skeleton for you to build upon, but working with a template makes things a bit easier.

Skinny Bones has an excellent “Getting Started” guide for the steps you need to take in order to get a working site. The short version is that you need to edit _config.yml. You probably also want to add some pages and write some posts to _posts. There are a few different ways to do it and the Getting Started guide tells you more about it.

At this point you probably want to test your site locally to see that everything looks right. Run bundle exec jekyll serve and you get a nice live preview of what the site will look like.

3. Push to GitHub

Create a repository and push your site to GitHub. You can use GitHub Pages to have GitHub build your page and present it either as a user page or a project page. Now you have a working webpage, if you don’t care what the URL is.

4. Get hosting

Next, you need a host for your site. You need to get DNS services and a virtual machine for hosting the contents of your site. It’s not necessary, but probably easier, if you get both from the same provider. The provider should at least allow connecting through a command-line SSH connection. It doesn’t need to be very fast or have a lot of space, since you are only going to transfer HTML files there.

Next steps will depend on your provider, but the basic steps needed are:

  1. Change the name servers to your hosting providers name servers.
  2. Change the DNS records to the hosting providers IP address.
  3. Check that you can log in and see something in the URL you got.
  4. Create SSH keys and copy the public key to the virtual machine.

5. Setup continuous integration

You could also use some other continuous integration service, but CircleCI provides one free virtual machine for building your projects and is pretty easy to use. You can log in with your GitHub account and connect CircleCI to your website repository. CircleCI searches for a circle.yml file from the root of your repository and reads it for build instructions. They provide guidelines for writing a config file, but you can get by with a very simple one. Here’s an example:

machine:
  environment:
      NOKOGIRI_USE_SYSTEM_LIBRARIES: true # speeds up installation of html-proofer

      dependencies:
        post:
	    - bundle exec jekyll build

	    test:
	      post:
	          - bundle exec htmlproofer ./_site --allow-hash-href --disable-external --empty-alt-ignore

		  deployment:
		    prod:
		        branch: master
			    commands:
			          - rsync -rv ./_site/ USER@MACHINE:/home/USER/WEBSITE-FOLDER

This config builds your site, runs a simple check to see that the HTML is valid and then uses rsync to move your site over to the hosting providers machine.

This won’t work as is: you need to change the USER to whatever your username is, MACHINE to whatever the address of the virtual machine is and WEBSITE-FOLDER to whatever the default folder for the server is (probably something like public_html). You also need to add your private SSH key to CircleCI so that it has access to the virtual machine without providing a password.

If everything is correct, CircleCI will now build and deploy your site whenever you push new changes to GitHub. If something goes wrong, the site won’t be deployed and you will get a warning message telling you what went wrong.

Leave me a comment if you have suggestions on how to make this setup better or if you encounter any problems.