Migrating from Ghost to Hugo

This weekend I migrated my blog from Ghost to Hugo. Ghost is great, but I couldn’t justify running a DigitalOcean droplet just for hosting a blog, maintaining it and updating Ghost all the time. Static pages work just fine. So, after looking around at several static site generators I decided to use Hugo.

Here is what I did to migrate:

  1. Created a new hugo site on my local system.
  2. Got a JSON backup of my Ghost content using the export tool.
  3. Got a tar.gz backup of my /var/www/ghost/static/ folder, with all static images etc.
  4. Moved the static content into HUGO/content.
  5. I used this script to convert the json backup file to individual markdown pages. I had to adjust the dateformat so that it fits with what I was using in Ghost.
  6. Pushed it to git on GitLab (private repository)
  7. I tried to find a way to recreate the look & feel of my Ghost blog in Hugo. I ended up using a theme that looks like Ghost’s Casper theme: https://github.com/dencold/hasper. This theme is itself a fork of the (original adaptation)[https://github.com/vjeantet/hugo-theme-casper] but the templates are cleaner. I edited it a bit more; my fork of the hasper fork is here.
  8. I set up hugo to use my custom theme as a git submodule, using git submodule add https://gitlab.com/ikoz/ikoz-hugo-theme-hasper.git themes/ikoz-hugo-theme-hasper. This way I can keep my hugo static content private while the theme is public. If I update the theme, I just need to push it to it’s own repo and within ghost do a git submodule update --remote.
  9. Gitlab also offers Gitlab Pages, which, much like Github Pages allows you to automatically publish your site. I adapted my Gitlab CI yml file to build the site using the latest hugo release (v.017) and support submodules so that the theme works fine. Here is the config:

    image: alpine:3.4
    before_script:
        - apk update && apk add --no-cache bash git openssl
        - git submodule init
        - git submodule update
        - wget https://github.com/spf13/hugo/releases/download/v0.17/hugo_0.17_Linux-64bit.tar.gz
        - echo "6a74626b64434a5ee9fc5ec4fbf22ce6  hugo_0.17_Linux-64bit.tar.gz" | md5sum -c
        - tar xf hugo_0.17_Linux-64bit.tar.gz && cp ./hugo_0.17_linux_amd64/hugo_0.17_linux_amd64 /usr/bin/hugo
        - hugo version
    test:
        script:
            - hugo
        except:
            - master
    pages:
        script:
            - hugo
        artifacts:
            paths:
                - public
        only:
            - master
    
  10. I adjusted my Cloudflare DNS setup so that it points to my Gitlab Pages hostname instead of the DigitalOcean droplet. I also set up strict SSL, origin certs, HSTS and whatnot.

  11. Finally, for each blog post I also adjusted the “slug” as needed and set up aliases so that all internal and external links to my posts still work. Disqus comments also got migrated automatically for each post, which was nice.

Everything seems to work properly. Now, for every blog post I publish I just need to write the markdown file locally and do a commit and git push; everything else gets done automatically and the site is updated in seconds.

mobile security, static & dynamic analysis, automation, payments

London, UK