Part 1 Using Github Pages and Hexo to manage personal blogs on Ubuntu


Hexo Tutorial

Github recommends us to use Jekyll to manage static pages, which is based on Ruby and is difficult for us to install and configure. So we use Hexo instead. Hexo is a static blog framework similar to Jekyll ,which is based on Node.js and easier for use to use.

use Github to create repo

  1. create a new repo in github, name by

  2. Setting | Github Pages, choose a theame and deploy.

install nodejs by apt-get

sudo apt-get -y install nodejs
sudo apt-get -y install nodejs-legacy
sudo apt-get -y install npm
node -v 
npm -v 

install nodejs from source

# download and compile
tar xzvf node-v8.9.3.tar.gz
cd node-v8.9.3
make -j8
sudo make install

# link to /usr/bin
sudo ln -s /usr/local/bin/node /usr/bin/node
sudo ln -s /usr/local/bin/npm /usr/bin/npm

# check version
node -v 
npm -v 

test node

cat hello.js
console.log('Hello World');

node hello.js
Hello World

install hexo

# install hexo globally
sudo npm install hexo-cli -g
#sudo npm install hexo --save

# use cnpm from taobao instead of offical npm, which is slow for chinese users.
sudo npm install -g cnpm --registry=

use cnpm instead of npm (optional)

# cnpm install 
sudo cnpm install hexo-cli -g

# check version
hexo -v

create hexo site

cd workspace
mkdir blog
cd blog

hexo init
#npm install
hexo generate
hexo server

now we can visit localhost:4000 and create posts.

deploy to github

vim blog/_config.yml

    type: git
    repo:   [email protected]:kezunlin/
    branch: master    

generate ssh-key and copy to github

# generate ssh-key 
cd ~
cat .ssh/

# copy content to github

# install plungin and deploy to github
npm install hexo-deployer-git --save
hexo deploy

ssh-keygen -t rsa -C “[email protected]

now we can visit

add README and skip render

  1. add to source folder
  2. edit blog/_config.yml to skip render

  3. use hexo generate to copy from source/ to public/

new post and deploy again

hexo new 'first post'
vim source/_posts/

hexo generate
hexo server
hexo deploy

now we can visit and see our first post.


hexo commands

Hexo common commands:

hexo new "postName"       #new post
hexo new page "pageName"  #new page
hexo generate             #generate static files to public/
hexo server               #start server on localhost:4000 
hexo deploy               #push .deploy_git/ to GitHub
hexo clean                #clean files  

Hexo short commands:

hexo n == hexo new
hexo g == hexo generate
hexo s == hexo server
hexo d == hexo deploy    

Hexo composite commands:

hexo server -g
hexo deploy -g


title: Using Github Pages and Hexo to manage personal blogs
date: 2017-12-26 17:28:10
categories: tutorial
    - github pages
    - hexo
    - nodejs
    - npm

see front-matter details


use <!--more--> to control web content

Use next theme

cd blog
git clone themes/next

vim blog/_config.yml

#theme: landscape
theme: next


edit blog\themes\next\_config.yml

avatar: /images/avatar.jpg


install plugin by

npm install <plugin-name> --save

hexo admin

cnpm install --save hexo-admin

now we can visit http://localhost:4000/admin/

git deployer

npm install hexo-deployer-git --save

rss feed

npm install hexo-generator-feed --save

visit http://localhost:4000/atom.xml


npm install hexo-generator-sitemap --save

vim blog/_config.yml

  path: sitemap.xml

now we can visit http://localhost:4000/sitemap.xml

baidu sitemap

npm install hexo-generator-baidu-sitemap --save

vim blog/_config.yml

  path: baidusitemap.xml

now we can visit http://localhost:4000/baidusitemap.xml

cnpm install hexo-abbrlink --save

edit blog\_config.yml

    permalink: post/:abbrlink/
        alg: crc32  # crc16(default) and crc32
        rep: hex    # dec(default) and hex

will fill abbrlink in your

title: Hello World
- tutorial
- hexo
abbrlink: 4a17b156
date: 2017-12-26 17:20:10


npm install hexo-generator-index --save
npm install hexo-generator-archive --save
npm install hexo-generator-category --save
npm install hexo-generator-tag --save

tags list page

hexo new page "tags"
# generate source/tags/

edit source/tags/

title: tags
date: 2017-12-27 15:46:09
type: "tags"

now we can visit http://localhost:4000/tags/

categories list page

hexo new page "categories"
# generate source/categories/

edit source/categories/

title: categories
date: 2017-12-27 15:46:03
type: "categories"

now we can visit http://localhost:4000/categories/

install search plugin

cnpm install hexo-generator-search --save

edit themes\next\_config.yml

    enable: true # create a new 'Search' button next to 'Archives'
    # if auto, trigger search by changing input
    # if manual, trigger search by pressing enter key or search button
    trigger: auto
    # show top n results per article, show all results by setting to -1
    top_n_per_article: 1

edit blog\_config.yml

    path: search.xml
    field: post
    format: html
    limit: 10000

Upload images to cnblog

  1. install img-uploader chrome extension by here
  2. upload image and get url.
  3. use url in markdown.
![alt]( "title")

Multiple deploy

  • deploy to
  • deploy to (gitcaffe): username

vim blog/_config.yml

  type: git
      github: [email protected]:/,master
      coding: [email protected]:/.git,master


custom domain and https

  • blog: Github pages
  • SSL:CloudFlare
  • domain: Godaddy (dns nameservers from CloudFlare)

get ips by

dig +noall +answer
  • A: point to 185.199.108/109/110/111.153
  • CNAME: point to


  1. get from
  2. add to github blog’s blog\source\CNAME file
  3. register and add A record with github page IP 185.199.108/109/110/111.153
    cloudflare a records
  4. Go to and add dns nameservers and from here
    godaddy dns
  5. wait for some hours(24 hours) and we get results from CloudFlare
Status: Active

This website is active on Cloudflare.

Universal SSL Status Active Certificate

Active means nameservers take effect.

configure Page Rules | rules for Always use HTTPS

google analytics

  1. get google-site-verification from google search console and add to themes/next/layout/_partials/head.swig
    <meta name="google-site-verification" content="***" />
  2. get google_analytics and edit themes\next\_config.yml
    google_analytics: UA-***

google adsense

  • google-adsense-header.js
  • google-adsense-display.js
  • google-adsense-article.js


<script data-ad-client="ca-pub-5653382914441020" async src=""></script>

baidu zhanzhang

get baidu-site-verification from and add to themes/next/layout/_partials/head.swig

<meta name="baidu-site-verification" content="***" />

360 zhanzhang

get 360-site-verification from and add to themes/next/layout/_partials/head.swig

<meta name="360-site-verification" content="***" />


cnpm install hexo-filter-nofollow --save

edit blog\_config.yml

  enable: true
  field: site
    - ''
    - ''

see hexo-filter-nofollow

code highlight

cnpm install --save hexo-prism-plugin

edit blog\_config.yml

  enable: false

  mode: 'preprocess'    # realtime/preprocess
  theme: 'tomorrow'
  line_number: false    # default false

see prismjs and matery

cnpm i hexo-permalink-pinyin --save

edit blog\_config.yml

  enable: true
  separator: '-' # default: '-'

only for post url with chinese words

recommend posts

install plugin

npm install hexo-recommended-posts --save
hexo recommend

edit blog\_config.yml

  autoDisplay: false # 自动在文章底部显示推荐文章,如果你使用Material-X主题,这里要设置为false。
  server: # 后端推荐服务器地址
  timeoutInMillis: 10000 # 服务时长,超过此时长,则使用离线推荐模式
  excludePattern: []
  titleHtml: Related Recommend Posts #自定义标题
  internalLinks: 4 # 内部文章数量
  externalLinks: 1 # 外部文章数量
  fixedNumber: false
npm install hexo-related-popular-posts --save

see here

pin top post

cnpm install hexo-generator-index-pin-top --save 

and edit _posts/

title: hexo blog
top: 1
 - hexo
 - blog

see here


  1. hexo new page "404"
  2. edit blog\source\404\
  3. hexo generate to generate blog\public\404.html
  4. hexo deploy to deploy blog to github.
  5. now we can access

when 404 error occur, github will serve as result.

stats busuanzi

edit /theme/next/layout/_third-party/analytics/busuanzi-counter.swig


<script async src=""></script>


<script async src=""></script>

edit blog\themes\next\_config.yml

    # count values only if the other configs are false
    enable: true
    # custom uv span for the whole site
    site_uv: true
    site_uv_footer: Visitors
    # custom pv span for the whole site
    site_pv: true
    site_pv_footer: Total Visits
    # custom pv span for one page only
    page_pv: true
    page_pv_footer: Reads

gitment for comment (not)

We can use github repo to store blog site’s comments in issues

register OAuth Application

  1. visit
  2. fill in blanks, callback URL:
  3. get client ID and client secret

go to to check your OAuth Apps

gitment config

  1. create a new repo named gitment in Github for storing comments in issues
  2. edit blog\themes\next\_config.yml
    enable: true
    mint: true # RECOMMEND, A mint on Gitment, to support count, language and proxy_gateway
    count: true # Show comments count in post meta area
    lazy: true # Comments lazy loading with a button
    cleanly: false # Hide 'Powered by ...' on footer, and more
    language: zh-Hans # Force language, or auto switch by theme
    github_user: kezunlin # MUST HAVE, Your Github ID
    github_repo: gitment # MUST HAVE, The repo you use to store Gitment comments
    client_id: xxx # MUST HAVE, Github client id for the Gitment
    client_secret: yyy  # EITHER this or proxy_gateway, Github access secret token for the Gitment
    proxy_gateway: # Address of api proxy, See:
    redirect_protocol: # Protocol of redirect_uri with force_redirect_protocol when mint enabled


  • github_user: kezunlin
  • github_repo: gitment

init page comment

  1. hexo deploy to deploy blogs
  2. visit page and click button Initialize Comment
  3. post your first comment.

error fix:

gitalk for comment

see gitalk for hexo next


skip now.

copy code (not)

customize hexo


see here

optimize for speed

multiple deploy

deploy to


cnpm install hexo-neat --save

edit blog\_config.yml

# hexo-neat
neat_enable: true

    enable: true

    enable: true
        - '*.min.css'

    enable: false
    mangle: true
        - '*.min.js'

hexo-all-minifier (not)

npm install hexo-all-minifier --save

edit blog\_config.yml

all_minifier: true

Tips: not enable minifier currently because not stable.

hexo-filter-optimize (not)

cnpm install hexo-filter-optimize

and edit blog\theme\next\_config.yml

  enable: true

Lazy load

Lazy load offscreen images with lazysizes



multi language

sel tools

very good ref here

get alexa rank

access alexa rank for


 Need more Alexa data?  Find our APIs here: 
<ALEXA VER="0.9" URL="" HOME="0" AID="=" IDN="">
<RLS PREFIX="http://" more="0"> </RLS>
<POPULARITY URL="" TEXT="4070983" SOURCE="panel"/>
<REACH RANK="3600610"/>
<RANK DELTA="+1226051"/>
</ALEXA> alexa rank is 4070983.

image resource


hexo Error watch ENOSPC

> hexo server 
(node:7563) [DEP0061] DeprecationWarning: fs.SyncWriteStream is deprecated.
INFO  Start processing
FATAL Something's wrong. Maybe you can find the solution here:
Error: watch /media/kezunlin/Workspace/git/blog/source/_posts ENOSPC


echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

ERROR Local hexo not found in

hexo -v
ERROR Local hexo not found in /home/kezunlin/git/blog


cd blog
rm node_modules
cnpm install --save


google chrome force reload page without cache


F12->Application->Clear Storage->Clear site data

clear site data



  • 2017/12/26: created.
  • 2017/12/27: add Appendix,use next theame,add tags/categories page.
  • 2017/12/28: add Advanced, use gitment,baidushare,local search,etc.
  • 2018/01/02: upload images to cnblogs.
  • 2018/01/03: hexo-neat to compress,cdn,etc.
  • 2018/01/22: add part2.
  • 2018/09/05: add ssl.
  • 2019/11/07: reorganize post contents.

Author: kezunlin
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source kezunlin !