Blair's Book Blog

I goofed / use git to build and upload a Jekyll site

While moving my blog to NearlyFreeSpeech.net, I figured it would be handy if I could automate building and uploading. Euan Torano has a promising looking guide for Deploying Hugo on NearlyFreeSpeech.NET with Git, and Jesse Squires has Building a site with Jekyll on NearlyFreeSpeech.

While following these guides, I ran into issues with the site.git directory containing the actual git content under site.git/site; I’m not by any means a git expert (I’m learning as I go along with this site, picking it up in the last couple of months), so I have no idea why my setup is off.

The next thing I wanted to solve was avoiding placing the actual remote git repo on NearlyFreeSpeech.net, instead using my diminutive print server at home, so that I could avoid duplicating the content on the server.

Finally, I wanted my Git hooks to build and then upload the blog content my web directory on NearlyFreeSpeech.net. While doing that I discovered that missing a / uploaded my content into a subdirectory on the server.

So, here’s a slight remix of what I got working. In the following, my workstation is running Debian 11, my print server is running Ubuntu 22.04, and my web host is running FreeBSD 12.4-RELEASE.

Before you begin

Ensure that install Ruby and other prerequisites for Jekyll.

If you haven’t, place existing Jekyll content under Git version control.

Create a bare Git repository

Create a bare Git repository. Later you’ll use this as your remote to push blog changes from your workstation.

Run the following commands to create a bare Git repository. I ran the commands on my print server, the other tutorials suggest doing this on the NearlyFreeSpeech server.

# If you're using this on NearlyFreeSpeech.net, uncomment the following line
# cd $HOME
# If you're using this on NearlyFreeSpeech.net, comment the following line
cd $HOME/private
mkdir site.git
cd site.git
git init --bare

Create a checkout directory

This contains a checkout of the repository that Jekyll works on. What I gather happens is that a Git hook that you’ll create uses this directory to checkout the Jekyll content on the remote and then use that copy to build your site.

Run the following commands to create a checkout directory. Again, I ran the commands on my print server.

# If you're using this on NearlyFreeSpeech.net, uncomment the following line
# cd $HOME
# If you're using this on NearlyFreeSpeech.net, comment the following line
cd $HOME/private
mkdir site_checkout
cd site_checkout
# If you're using this on NearlyFreeSpeech.net, uncomment the following line
#git clone $HOME/site.git
# If you're using this on NearlyFreeSpeech.net, comment the following line
git clone /home/private/site.git/

Create a post-receive Git hook

The following script runs each time you run git push to the remote repo. In the site.git directory (the bare git repo), there is a hooks/ directory with sample scripts that you can look at for ideas of other things you can do with hooks.

In this case, create a new file in /home/private/site.git/hooks/post-recieve and add the following content:

#!/bin/bash

set -ex

# I set $HOME explicitly on my print server
export GEM_HOME=$HOME/.gems
export PATH="$HOME/.gems/bin:$PATH"

# If you're using this on NearlyFreeSpeech.net, uncomment the following line
# SITE_CHECKOUT=$HOME/site_checkout/site
# If you're using this on NearlyFreeSpeech.net, comment the following line
SITE_CHECKOUT=$HOME/private/site_checkout/site
GIT_DIR=$SITE_CHECKOUT/.git
BUILD_WWW=$HOME/www
# The following is the WWW directory on your actual web server
PUBLIC_WWW=/home/public/

cd $SITE_CHECKOUT

git --git-dir=$GIT_DIR status
git --git-dir=$GIT_DIR pull -f
git --git-dir=$GIT_DIR status

# Uncomment the following line to update your Ruby gems every time that you run
# git push
#bundle install
bundle exec jekyll build --destination $BUILD_WWW

# The following fix any permissions on directories and files before upload
find $BUILD_WWW -type d -exec chmod 755 {} \;
find $BUILD_WWW -type f -exec chmod 644 {} \;

# For the following rsync commands, change the following:
# username: your username
# web_server_ssh_address: the ssh address to connect to your web server

# Use the following rsync command to test that rsync uploads the files that
# you expect and to the locations that you expect:
rsync -v -rz --checksum --delete --dry-run $BUILD_WWW/ username@web_server_ssh_address:$PUBLIC_WWW
# After verifying that the test command works as expected, comment it out and
# uncomment the following line:
#rsync -v -rz --checksum --delete $BUILD_WWW/ username@web_server_ssh_address:$PUBLIC_WWW

exit

Run the following command to set the execute bit on the script:

chmod ug+x /home/private/site.git/hooks/post-receive

Create a remote repo on your workstation

Run the following command:

git remote add local_remote trunk ssh://username@local_server/home/private/site.git

Change the following:

Edit, commit, build and upload

Create a blog entry with your desired editor. Then, run the following commands to commit your changes:

git add file_name
git commit

Replace file_name with file name(s) that you edited. When you run git commit, an editor is displayed; enter a commit message and save.

Then, push your changes to your remote:

git push local_remote

Pushing your content causes the post-receive script to run, which builds the site and uploads necessary changes to the web server (saving you space and network transit fees).