Edit: Thursday November 15 2018
Note that I do not use this any more. The steps talked about here may still work with minimal changes and may be worth reading for the Go program, though keep in mind how old this is.
Friday February 12 2016
What this article is and is not
This article is a quick setup tutorial based on how I have chosen to run Jekyll and Nginx while using Git as my version control. This article will not explain in-depth Jekyll, Nginx, or Git.
Nginx and Jekyll on your remote server
Make sure that you have Nginx installed, I choose to run FreeBSD and as such Nginx comes with a pretty basic and centralized configuration. I tend to lean it out and add an include for a separate vhosts folder like so:
user nobody;
# user www;
worker_processes 2; # Number of cores
events {
# worker_connections 1024; # Standard configuration
worker_connections 10000; # Likely overkill
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
# include inc/*;
include vhosts/*.conf;
}
This is of course only an example configuration. Do what is right for your system, especially when it comes to the main configuration file.
The virtual host file that I’m using with Jekyll is as follows:
# Example letsencrypt command:
# letsencrypt certonly --webroot-path /tmp/lets -d www.example.com -d example.com
server {
listen 80;
# You may or may not have IPv6, so disable this if necessary
listen [::]:80;
server_name
example.com
www.example.com
myotherexample.com
www.myotherexample.com
;
# For the Letsencrypt certificates
# root /tmp/lets;
# Otherwise:
location / { return 301 https://www.example.com$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /usr/local/etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/www.example.com/privkey.pem;
server_name
example.com
;
location / { return 301 https://www.example.com$request_uri; }
}
server {
# Note, to use HTTP/2 you will need an up to date mainline version
# of Nginx. On FreeBSD this is called "nginx-devel"
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /usr/local/etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/www.example.com/privkey.pem;
server_name
www.example.com
;
index index.html index.htm;
root /var/www/example.com;
autoindex on;
# Handle Jekyll being separate but on the same level as everything else
location / {
try_files $uri $uri/ @jekyll;
rewrite ^(.*)/$ $1/index.html last; # Allow for /index.html to be the index
}
# Any file that does not exist in our root will get tossed to the
# Jekyll _site directory.
location @jekyll { root /var/www/example.com/jekyll/_site; }
# Do not allow anyone access to the /jekyll directory directly
location /jekyll { deny all; }
# If I were to put a picture in here I'd like to call it without
# the file extension, just a personal preference.
location /pictures {
autoindex on;
try_files $uri $uri.png $uri.jpg $uri.gif $uri/ /;
}
# If I'm going to add some files for the world to see there is no
# reason to have autoindex off
location /files {
autoindex on;
}
# This is going to be used by our webhooks to auto update our website
location /git-autoupdate {
include inc/proxy.conf;
# Make sure this matches your ~/.gohook.yaml
proxy_pass http://127.0.0.1:10000/;
}
}
You’ll note that I’m using Let’s Encrypt here, even providing an example command although it’s not required to run a domain with a SSL certificate I highly recommend that you do not skip the SSL certificate. It not only protects the privacy of others but it also protects your content from modification or censorship by malicious parties
Now for the Jekyll setup,
I will assume that you have a local Jekyll site and already have its contents in a git repository. The commands below will clone your remote repository into the jekyll folder
$ export REPO_URL="https://github.com/username/example.com"
$ cd /var/www/example.com # The root of your website, this should match your Nginx config
$ git clone "$REPO_URL" jekyll # clone into the Jekyll folder
$ jekyll build # Initial Build of the website
$ cat > .git/hooks/post-merge <<EOF
#!/bin/sh
# This script will make sure your site is rebuilt on every git update
jekyll build
EOF
$ chmod +x .git/hooks/post-merge # Make sure that it's executable
Automatically have your Jekyll site updated
when you run a git push
To accomplish this I’m going to leverage webhooks
provided by server side software such as Github, Gogs, and Gitlab. First things
first let’s make sure that we have our application setup to receive the web hook
I’ve written a small application in Go to make this easy. You can also find the source code and some extra documentation on my git server. You may need to install go, some distributions provide go as a package, you can also follow the instructions on their website.
Setup commands:
$ go get git.riedstra.us/mitch/gohook
$ cd $GOPATH/src/git.riedstra.us/mitch/gohook
$ go install
$ cp gohook.yaml ~/.gohook.yaml
$ $EDITOR ~/.gohook.yaml
~/.gohook.yaml
# Address and port the Go "net/http" server will listen on
# Make sure this matches the Nginx configuration above
listen: 0.0.0.0:10000
# Map of URLs to look for in the hook, with options
repos:
https://gogs.example.com/bob/site:
dir: /var/www/example.com/jekyll
branch: master
location: origin
To make sure this runs on boot can differ for practically every system in existence. I just have it setup to run from the crontab.
$ REPO_OWNER="www" crontab -e -u $REPO_OWNER
Contents of the crontab:
# Note, you will need to set PATH and HOME, e.g.
PATH="/usr/home/www/bin/go"
HOME="/usr/home/www"
# Automatically update repositories
@reboot gohook >/dev/null 2>&1 &
Run gohook without rebooting:
$ gohook >/dev/null 2>&1 &
Go ahead and test your setup
At this point everything should be set up to allow you to push from your local machine to your git server ( or service, such as Github ) and have your website update within a few seconds.