Serving Octopress From a Self-hosted Git Repository
There are two good reasons to serve Octopress from a self-hosted git repo.
- It provides you with an off-site backup in case your local copies go up in flames.
- It gives you an environment where you can integrate secondary scripts and libraries that allow you to do things like e-mail posts to Octopress.
- git provides a very efficient, and atomic, means of uploading your files.
Complicating factors:
- Not all ISPs have ssh access or the latest version of ruby, and may not have git or Bundlr installed.
- Because of the above you may not be able to regenerate html files from markdown on the server.
- You need to have a basic familiarity with navigating directories and editing files over ssh.
These instructions are not for people uncomfortable with using the command line in a *nix environment. Of course, if you were uncomfortable with that you probably wouldn’t be using Octopress in the first place.
In order to do this you must have ssh access to your server, and have git installed on it. In order to generate new files on the server you must also have Ruby 1.9.2 (or higher) and Bundlr installed You must also have a basic understanding of how to get around on a Linux command line. This is not uncommon these days, but in order to check just ssh in and type:
which git
which bundle
If they both return a path to the executable you’re all set. If git is installed we
can proceed without problem. If git and bundler are installed and ruby is at 1.9.2 we can generate
the html on the server. For those not already familiar, which xxxx
will print out the path of the executable if it is installed and on your path. If it returns immediately with no output it is either not installed or not on your path.
Next check the ruby version:
ruby --version
Octopress requires a recent version of Ruby to run, so if it says anything lower than 1.9.2 you will not be able to generate files on the server. Talk to your ISP about installing a more recent version of Ruby. You will, however, still be able to use git to transfer files to and from your server, serve from its generated directory, and act as a backup.
There are a couple ways to make this work. You could just host a non-bare repo on the server and set receive.denycurrentbranch to ignore so that you can push to it, but for security reasons, and safer removal of deleted posts it’s better to use a detached work tree.
SSH to your server, and create a new bare git repo somewhere that will not be served to the public.
#on the server
mkdir octopress_blog.git
cd octopress_blog.git
git init --bare
# core.worktree should point to a directory where
# everything will be checked out into, but not
# visible to the public. You must create this
# directory. Git will not create it for you.
git config core.worktree /path/to/staging/directory
Once you’ve done that we need to set up the post-receive hooks. Create a hooks/post-receive
file (in your bare repo) and make it look like this.
#!/bin/sh
# checkout the files after they've been pushed here
GIT_WORK_TREE=/path/to/staging/directory git checkout -f
Next, make it executable
chmod 755 hooks/post-receive
Later we’ll tweak hooks/post-receive
to auto-generate the site (if you’ve got the pre-requesites on your server) but for now we just want to make sure we can push to it successfully.
Back on your local computer:
cd my_octopress_blog
git remote add live me@example.com:/path/to/octopress_blog.git
Now try pushing to it:
git push live master
It doesn’t have to be the master branch but that’s what most people use so we’re working from that assumption. It should push without problem, but pay careful attention to lines starting with “remote:”. If it does have problems, you should be able to figure out what’s wrong from the error message. At the end of the push you should see a message from remote saying “remote: Checking out files:…”
Back on your server take a look in the directory you pointed core.worktree at and see if your blog has been checked out there. From here on out we have to divide the instructions for people who can generate files on the server, and people who can’t.
To generate server-side or not….
Generating HTML server-side
Generating the html files server-side is good because you can set up things like JekyllMail to allow you to post to your Octopress without having to have a local checkout (great for blogging from work). Another benefit is that your “public” directory doesn’t have to be a subdirectory of your Octopress checkout. You can tweak your _config.yml
to generate it anywhere on the server which can make server configuration easier for some. If you do change the destination
attribute in your _config.yml
on the server to a path that differs from your local version you’ll have to be careful to not commit any local changes to it.
Caveat Emptor: On shared servers there is one gotcha that you’ll have to be aware of. Long-running scripts are frequently auto-killed by the server so that one user doesn’t consume an unfair amount of resources. Until such a time as Octopress is capable of regenerating only the new posts there is the possibility that large blogs with hundreds of posts may exceed this limit and the generate script may be killed before completion.
Generating HTML locally
The only notable advantage to generating locally and pushing to a server-side repo is it works on servers where you have git but can’t run Octopress’ generate script for whatever reason.
Serving from a self-hosted git repo without generating HTML files server-side.
This is the simplest way to go, but it requires one change to the standard Octopress workflow, and the ability to point your server at a specific directory to serve your site from. In your workflow you’ll need to commit everything in your public directory each time your run rake generate
, then push to the server. You need to be sure to add & commit any files deleted from your public directory after generation too, or else a deleted post will not get deleted on the server. Typically you can just say git add public
each time and it’ll take care of managing the deleted files too.
Since the HTML files are going to be generated in a subdirectory of your Octopress repo (typically called “public”). You’ll need to point your server to the public directory under the directory that your core.worktree
option is pointed at. Feel free to rerun the command above that set it if you want to change it to a different place now that you know everything works.
Once you’ve pointed your server to the appropriate directory all you will need to do to update your site and create an offsite backup of the original markdown files (and everything else) is to locally run
git push live master
Serving from a self-hosted git repo and generating HTML files server-side.
You’re going to follow the same steps as serving without generating files except you won’t be committing the “public” directory’s contents.
You’ll also need to add the following to the end of your hooks/post-receive
cd /path/to/staging/directory bundle install bundle exec rake generate
Note, if you’re using RVM or a custom gem path you may need to add those to the start of the hooks/post-receive
script so that git will have it in its environment when it runs. For example, on Dreamhost you would have to add something like this to the top (assuming you’d already installed RVM and the current version of Ruby):
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
GEM_PATH=$GEM_PATH:/home/my_username/.gems
PATH=$PATH:/home/my_username/.gems/bin
Make a commit locally, push it to the new repo, and confirm that your changes have been pushed to the staging directory and that rake generate has done its job and placed the new html files in your “public” directory (or wherever your _config.yml
has destination
pointing to).
Once you’ve confirmed that that works you can (optionally) change the /path/to/staging/directory
to point to somewhere that isn’t just for testing in the hooks/post-receive
file and in the core.worktree
setting. All that’s left is pointing your server at whatever directory your _config.yaml
’s destination
is pointed at.
From then on you just run
git push live master
on your local machine to update your blog.