August 12, 2016

Self-hosted alternative to GitHub's blogging

Initially I wanted to write some raw stuff about Jekyll and how cool is it. Finally I decided to present how to achieve alternative way of GitHub’s blogging. I think it might be interesting to learn about few new tools or technologies. You do not have to start hosting your blog on your own, but it’s useful to know about Gogs, rbenv or nginx.

The following post shows simple way of blogging combined from Gogs, Jekyll and nginx. Gogs provides us web interface for repository, Jekyll builds blog and nginx servs generated files. The whole trick is to trigger building after commit with blog updates using git hooks.

I described only major points of configuration. I do not want to duplicate documentation and make this post too long. I bet this kind of stuff is mostly fun to people who like tinkering and already have good basics.

Demo: repository
Demo: blog

blogs repository

Let’s get started

Gogs is self-hosted Git service. It requires much less resources than GitLab, but it has everything what is needed in most cases. It is not as mature as GitLab, but I recommend to give it a try.

You can install Gogs using sources, from packages or just run binary. If you are using one Debian, Ubuntu or CentOS you can install package from packager.io for ArchLinux there are AUR packages.

If you go for sources or binary, remember to symlink gogs.service which template is in gogs/scripts/systemd/.

Starting Gogs

systemctl enable gogs.service
systemctl start gogs.service

either (when you do not care about gogs.service)

./gogs web

Gogs should listen by default on port 3000.

I assume you got some machine with ip. You can visit gogs with your_ip:3000.

I prefer using subdomains and to achieve that I configure nginx as reverse-proxy.

Example

upstream gog  {
      server localhost:3000;
}
server {

        listen 80;
        listen [::]:80;
        server_name repo.edu.fx7.me;

        location / {
         proxy_pass  http://gog;
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
         proxy_redirect off;
         proxy_buffering off;
         proxy_set_header        Host            $host;
         proxy_set_header        X-Real-IP       $remote_addr;
         proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       }
}

I assume you can handle nginx by yourself

There are few things to configure before you start using Gogs.

  • App settings - things like app port, ssh port, user and path for repositories
  • Database - you can chose between MySQL, PostgreSQL, SQLite3

You can find more information reading documentation.

Ruby with rbenv

Jekyll is written in Ruby thus we need to install some Ruby package. I highly recommend using tools like rbenv or rvm. I prefer rbenv.

You can install ruby system wide. It is usually faster. However if you decided to manage ruby versions somehow, remember to let gogs user to run Jekyll.

Installation of rbenv is quite easy, readme has everything what is needed. In overall installation is just cloning repository and editting $PATH variable.

ruby-build it’s useful plugin for rbenv. It lets us compile and install different versions of Ruby using rbenv install command.

finally we can install ruby rbenv install 2.3.0
select ruby version rbenv local 2.3.0

Jekyll

First of all we need to install Jekyll and it can be done using RubyGems
gem install jekyll

The next step is to download some theme. I chose one on JekyllThemes For purpose of this post I chose the newest one Jekyll-Mono.

To check if Jekyll works fine, clone theme repository, change directory to theme repository and run jekyll serve.

Jekyll is able to serve himself using WEBrick.

git clone git@github.com:AkshayAgarwal007/Jekyll-Mono.git
cd Jekyll-Mono
jekyll serve

jekyll serve should fail. This is because most of themes needs some additional plugins. In this case Jekyll-Mono needs jekyll-feed and jekyll-sitemap lets install these plugins using RubyGems.

gem install jekyll-feed jekyll-sitemap

You can find many interesting plugins here

Try once again

jekyll serve

Everything should be fine now and your blog should be visible at http://127.0.0.1:4000/

ok, server is ready.

Gogs and git hook

Jekyll and Gogs are installed and prepared to work. We are ready to setup repository on our server and create post-receive hook for automatically jekyll -build.

Before creating new repository on Gogs. Prepare your blog source e.g clone some theme.

Let’s create new repository on Gogs. To local repository add new remote to new repository on Gogs. blogs repository

Gogs will hint you what to do in Push an existing repository from the command line section.

git remote add origin ssh://git@repo.edu.fx7.me:14322/fx7me/demo-repo.git

And finally it’s time for event-based git hooks. There are few different types of hooks, we will build Jekyll using post-receive hook. If you need something more there is documentation

Gogs let us manage git hooks via web fronted in repository settings. blogs repository

We can use script from documentation. Script is not complicated, there are few paths and Jekyll build command.

Make sure your path to Jekyll is correct. If you decided to use rbenv you would need to point to shims e.g $HOME/.rbenv/shims/jekyll.

GIT_REPO=$HOME/gogs-repositories/fx7me/my-blog-post.git
TMP_GIT_CLONE=$HOME/tmp/jekyll
PUBLIC_WWW=$HOME/public_html/jekyll

JEKYLL=$HOME/.rbenv/shims/jekyll

git clone $GIT_REPO $TMP_GIT_CLONE
$JEKYLL build -s $TMP_GIT_CLONE -d $PUBLIC_WWW

rm -Rf $TMP_GIT_CLONE
exit

Save git hook, and try to push to gogs repo. Jekyll should build blog and put files in $HOME/public_html/jekyll. To make blog visible create vhost with the same root.

example

server {  
        listen 80;  
        listen [::]:80;  
  
        server_name demo.fx7.me;  
  
        #    $HOME/public_html/jekyll`
        root /home/USERNAME/public_html/jekyll;  
        index index.html;  
  
        location / {  
  
                try_files $uri $uri/ =404;  
        }  
}

My goal was not to lead you step by step how to build identically setup, but present you few interesting tools. You can automatize your work using git hooks, keep your stuff on Gogs and manage your Ruby versions using rbenv.