POST

Hosting a Ghost Blog in GitHub - the easier way

You may want to use an email address you don’t mind being public. See “Security Considerations” below.

  1. Start creating content!

  2. Update the git repository:

    git add .
    git commit -m 'Finished local Ghost setup'

Export website

Now that you have your blog set up locally, we need to generate a static copy that can be published to GitHub. For this we will use the wget command. I gathered the correct options from this blog post by Ilya a few years ago, although it’s not too hard to deduct them from the wget man page.

  1. We will publish the blog from the docs directory of our repository, so that’s where we need to store the static copy:

    wget -r -nH -P docs -E -T 2 -np -k http://localhost:2368/

    This command will crawl the entire site and create a static copy of it under the docs directory. You can open the file docs/index.html in your web browser to verify.

    1. Add the generated pages to the git repository: shell git add docs git commit -m 'Initial commit of static web site'

Push to GitHub

We can finally create our GitHub repo and push the contents to it.

  1. Create the repository. I’m using here the hub command, but of course you can also do it by hand in the GitHub website (in this case you need to add the git remote by hand as well):

    hub create 
    1. Push the local repository to GitHub (this includes both the Ghost source and the generated website under docs): shell git push -u origin master

Publish!

Now all we need to do is enable GitHub Pages on our repository, so that the contents under docs gets published.

  1. Go to your repository’s “Settings” screen:

  2. Scroll down to the “GitHub Pages” section and choose the “master branch /docs folder” option and click the “Save” button:

We are done! After a few minutes (usually takes 2-5 minutes for the contents to be published the first time, afterwards updates are nearly instantaneous), you will find your new website’s content under http://<github-username>.github.io/<github-repo-name>. In our example, the URL is https://zzamboni.github.io/test-ghost-blog/:

The workflow

After the initial setup, you need to follow these steps when you want to update your website:

  1. Start Ghost inside your GitHub repository:

    npm start
    1. Connect to http://localhost:2368/ and update your contents. You can also change the blog settings, themes, etc.

    2. Re-crawl the site to generate the local copy:

      wget -r -nH -P docs -E -T 2 -np -k http://localhost:2368/
  2. Update and push the whole git repository:

    git add .
    git commit -m 'Website update'

    Steps 3 and 4 can be easily automated. I keep the following update_website.sh script in the repository:

    #!/bin/bash
    OUTDIR=docs
    LOCAL_GHOST="http://localhost:2368/"
    wget -r -nH -P $OUTDIR -E -T 2 -np -k $LOCAL_GHOST && \
    git add . && \
    git ci -m 'Update website' &&  \
    git push

Then you can just run this script from within your repository after making any changes:

./update_website.sh

Variations

The method described above is my favorite because it allows me to keep the source data and generated pages in the same repository. However, there are other variations that you might want to use:

You can read more about the different ways to serve GitHub Pages content in the GitHub documentation.

And of course, you can use the same method to host your static content somewhere other than GitHub pages.

Security considerations

One of the most-touted benefits of a static website (also known, I discovered recently, as the JAMstack) is security – without server-side active components, it’s much harder for a website to be compromised.

Sharp-eyed readers may have noticed that with the setup described above, Ghost’s entire database file gets checked into your repository. This file contains not only your published blog posts, but also your user definitions (including hashed versions of the user passwords) and draft posts.

The local Ghost install uses a SQLite database, stored at content/data/ghost-dev.db, which you can query using the sqlite3 command. For example, to see the user definitions:

sqlite3 content/data/ghost-dev.db 'select * from users'

While this seems scandalous, keep in mind that the active Ghost installation is only running locally on your machine, and is not accessible to anyone from the outside, even when it is running (the server is only bound to localhost). Still, you may want to keep in mind:

Conclusion

I followed the steps described above to create a test Ghost install, which you can access at https://zzamboni.github.io/test-ghost-blog/, and its corresponding GitHub repository at https://github.com/zzamboni/test-ghost-blog/. You can also find this article published there.

I hope you’ve found it useful. I’d love to hear your comments!

comments powered by Disqus