Deploying Jekyll on Dreamhost server using GIT

17 Jan 2019

Lets say you make a cool static website using jekyll. It’s pretty straightforward to deploy with Github Pages. But how can you deploy it on your Dreamhost shared hosting server?

Please note I’m using a linux environment. CLI commands may vary depending on your os.

Why

I’ve been using Wordpress on Dreamhost for my personal website for some years and with shared hosting I can have unlimited websites on subdomains and emails without having to worry about managing the server. So while I very much would like to switch to a hosting platform like netlify, or a VPS, I’ve been using Dreamhost for a long time and am comfortable launching small projects on it and hesitant to switch for now. However, I like the simplicity of using Jekyll and deploying through Github Pages, but I want to instead deploy it to my existing Dreamhost server.

Set up SSH

First you have to set up your Dreamhost server and enable ssh. We will set up a passwordless login for it.

  1. First generate a public SSH key on your local machine. If you don’t have one: $ ssh-keygen -t rsa

  2. Copy your ssh id to your Dreamhost. $ ssh-copy-id <user>@<host>

You should be able to ssh with a password now.

Make remote repo on Dreamhost

On your server create a repo where to push the code:

$ ssh <user>@<host>
$ cd ~
$ mkdir <mydomain_com>.git
$ cd <mydomain_com>.git
$ git init --bare

Create a post-receive hook

With our empty repo we want to set up a hook that gets triggered every time changes are pushed to the repo. Essentially when we perform a git push the code will be stored to a temp domain and then the build folder will be copied to your domain.

Ignoring images but keeping them persistent

I’m using images on my website but I don’t want to gum up my GH account with a bunch of images, so I’ve ignored the img directory in my .gitignore file. I want to keep my img directory in my domain’s public folder, but the hook we will make will delete everything. To bypass this in the hook I will temporarily move the images before I delete my public folder and move them back after copying over my static files.

Create a post-receive hook:

$ ssh <user>@<host>
$ cd ~
$ vi <mydomain_com>.git/hooks/post-receive

Then paste in:

#!/bin/bash

# Replace this line with your real domain name
DOMAIN=mydomain.com

echo
echo "~~ Updating $DOMAIN ~~"
echo

# Clearing git env
unset GIT_DIR
unset GIT_WORK_TREE

# temp domain storing the entire jekyll tree (all repo content)
cd ~/$DOMAIN-jekyll
git pull

# temporarily move img directory 
cd ~/$DOMAIN/public
mv <img_directory> ..

# get to the static build directory
cd _site

# delete domain contents
# viewable website in public directory
rm -rf ~/$DOMAIN/public/*

# copy that to our real domain path
cp -R * ~/$DOMAIN/public/

# move image directory back to public
cd ~/$DOMAIN/
mv img public

echo
echo "~~ Done ~~"
echo

Then make the script executable: $ chmod +x <mydomain_com>.git/hooks/post-receive

Create a remote

Next you have to create the remote. In your server clone the repo that we made.

$ cd ~
$ git clone <mydomain_com>.git <mydomain.com>-jekyll

This is where all your code pushed will live. Only the static files will be copied to your real domain for public viewing.

Add remote endpoint on local repo

On your local machine add the remote repo. git remote add live ssh://<user>@<host>/~/<mydomain_com>.git

Now you can push straight to your dreamhost domain: $ git push live master

With this setup I can do version control with Github but easily push to my live website. A caveat about this method is that I have to build locally before pushing new posts whereas Github pages automatically publishes for you with the github-pages gem.

Acknowledgements

Thanks to Bruno Fagundez for his excellent write-up for this topic.