How to Install and Create a Blog with Hexo on Ubuntu 20.04
Hexo is a static blogging framework built on Node.js. Hexo allows you to write posts in Markdown format. These blog posts are processed and converted into static HTML files using pre-defined themes.
It is different from the usual blogging software like WordPress as it generates static files. WordPress loads the blog dynamically by running PHP code every time you reload the site which makes it susceptible to vulnerabilities.
In this tutorial, you will learn how to Install Hexo and use it to create a blog on Ubuntu 20.04 based server.
Prerequisites
-
Ubuntu 20.04 based server with a non-root user with sudo privileges.
-
Git should be installed. If you don't have git installed, you can do it via following commands.
$ sudo apt install git $ git config --global user.name "Your Name" $ git config --global user.email "[email protected]"
-
An account on Github.
Configure Firewall
Ubuntu 20.04 comes with Uncomplicated Firewall(UFW) by default. In case it is not, install it first.
$ sudo apt install ufw
Enable SSH port.
$ sudo ufw allow "OpenSSH"
Enable the firewall.
$ sudo ufw enable
Enable the port 4000 which is used by the Hexo server.
$ sudo ufw allow 4000
Also, open the HTTP and HTTPS ports which we will need later.
$ sudo ufw allow http
$ sudo ufw allow https
Check the firewall status.
$ sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
4000 ALLOW Anywhere
443/tcp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
4000 (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
Install Node.js
Since Hexo is based on Node.js, you need to install it first.
Run the following command to add Node.js Repository.
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
Install Node.js.
$ sudo apt-get install nodejs
Confirm if it is installed properly.
$ node --version
v14.15.0
Install Hexo
Run the following command to install the Hexo package.
$ sudo npm install hexo-cli -g
The -g
parameter installs the hexo-cli
package globally which will allow you to install Hexo blog in any directory of your choice.
Create the directory to install Hexo in.
$ sudo mkdir -p /var/www/hexo
Set the required permissions and ownership.
$ sudo chown -R $USER:$USER /var/www/hexo
$ sudo chmod -R 755 /var/www/hexo
Next, you need to initialise and set up the necessary files for the Hexo blog. To do that, switch to the directory you just created.
$ cd /var/www/hexo
Initialise the Hexo blog.
$ hexo init
INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
INFO Install dependencies
added 185 packages from 430 contributors and audited 191 packages in 6.47s
14 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
INFO Start blogging with Hexo!
Install Hexo.
$ npm install
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
added 5 packages from 1 contributor and audited 191 packages in 1.567s
14 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
You can now check the directory structure.
$ ls
_config.yml node_modules package-lock.json package.json scaffolds source themes
The _config.yml
file holds the configuration for your Hexo blog. Most of the blog settings can be changed from here.
The node_modules
directory holds all the packages Hexo needs and the ones that it depends on.
The package.json
file contains a list of all the packages and their version numbers that Hexo needs.
The package-lock.json
file is automatically generated by npm
every time you perform an installation or a change to the Hexo package. It contains information about packages and the versions that were installed or changed.
The scaffolds
directory contains the templates on which your blog posts and pages will be based.
The source
directory contains the actual site content in HTML/CSS format which is then published on to the web. Any folder or file prefixed with _
(underscores) is ignored by Hexo except the _posts
folder. For now, the directory is empty because we haven't written or published anything.
The themes
directory contains your Blog themes.
Configure Hexo
Open the _config.yml
file for editing.
$ nano _config.yml
Check the section of the file titled Site
# Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site
title: Hexo
subtitle: ''
description: ''
keywords:
author: John Doe
language: en
timezone: ''
The options are pretty self-explanatory. Change the name of your site, set a subtitle if you like. Add a description of your site and some keywords to describe it. Change the author name and the time-zone for your site.
Next, check the URL
section of the file.
# URL
## If your site is put in a subdirectory, set url as 'http://example.com/child' and root as '/child/'
url: http://example.com
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
trailing_html: true # Set to false to remove trailing '.html' from permalinks
Change the URL of your site to your domain name. Make sure you use HTTPS in your URL since we will install SSL later.
If you don't want your site URL to show index.htm
l at the end of each page, you can change both the options trailing_index
and trailing_html
to false
.
There are a few more settings you should turn on.
Change the value of the default_layout
variable from post
to draft
. This will create new posts as drafts so you will need to publish them before they appear on the blog.
Change the value of the post_asset_folder
variable to true
. This will allow you to have individual image folders for each post instead of a single image folder for all posts.
Save the file by pressing Ctrl+X and entering Y when prompted.
Installing a Theme
Hexo ships with a default theme named Landscape. You can switch to a different theme by installing another Hexo theme available from its Themes page.
All the Hexo themes are available via Github so you need to clone the theme's Github repository.
For our tutorial, we are installing the Next theme. Switch to the Hexo directory and Clone the theme's Github repository into the themes
directory.
$ cd /var/www/hexo
$ git clone https://github.com/theme-next/hexo-theme-next themes/next
Change the /var/www/hexo/_config.yml
file to change the theme from Landscape to Next.
$ nano _config.yml
Make the change to the theme variable to switch the theme.
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: next
You can change the theme settings by modifying the /var/www/hexo/themes/next/_config.yml
file.
Create and Publish a Post
Time to create our first post.
$ hexo new first-post
INFO Validating config
INFO Created: /var/www/hexo/source/_drafts/first-post.md
Open the new post for editing.
$ nano ./source/_drafts/first-post.md
Every post needs to have its front-matter
set up. Front-matter is a short block of JSON or YAML that configures essential details like the title of the post, published date, categories, tags, etc. Replace the default data with the correct options.
title: Howtoforge's First Post
tags:
- test
categories:
- Hexo
comments: true
date: 2020-11-14 00:00:00
---
## Markdown goes here.
**This is our first post!**
If you want to insert an image in your post, add the following code in your post.
{% asset_img "example.jpg" "This is an example image" %}
After that, copy the file example.jpg
to the \source\_posts\first-post
directory which is where all images for your first post will be retrieved from.
Save the file by pressing Ctrl+X and entering Y when prompted once you are finished writing the post.
Next, publish the post.
$ hexo publish first-post
INFO Validating config
INFO Published: /var/www/hexo/source/_posts/first-post.md
This post will be visible once we host the blog.
Installing a Plugin
Hexo has few hundred plugins that you can install. You can install one or more plugins depending upon your usage.
All the Hexo plugins are Node.js packages and hosted on Github where you can find their installation and configuration details.
For our tutorial, we will install the hexo-filter-nofollow
plugin.
Make sure you are in the hexo directory first and then install the plugin.
$ cd /var/www/hexo
$ npm i hexo-filter-nofollow --save
Open the Hexo configuration file for editing.
$ sudo nano _config.yml
Paste the following code at the end of the file.
nofollow:
enable: true
field: site
exclude:
- 'exclude1.com'
- 'exclude2.com'
The enable
option enables the Plugin. The field
option defines the scope of the plugin where site
adds nofollow attribute to the external links on the entire site and post
adds nofollow attribute only to the links in the posts. The exclude
option whitelists domains on which nofollow attribute won't be added.
Test Server
Hexo ships with a basic web server. Now that our post is published, it is time to start the Hexo test server.
$ hexo server
You can now launch the URL http://yourserverIP:4000
in your browser and you will see the following page.
Exit the server by pressing Ctrl + C at the terminal.
Generate Hexo Static files
The Test server of Hexo can serve the blog dynamically as well as through the static files. The above command served the blog dynamically.
There are several ways to serve Hexo blog publicly. For our tutorial, we will serve Hexo's static files using Nginx server.
Run the following command to generate the static files.
$ hexo generate
The above command generates static files which are stored in the /var/www/hexo/public
folder. We will use Nginx server to serve files from this folder.
Install and Configure Nginx
Install Nginx server.
$ sudo apt install nginx
Create and open the Hexo configuration file for Nginx.
$ sudo nano /etc/nginx/sites-available/hexo.conf
Paste the following code in it.
server {
server_name hexo.example.com;
root /var/www/hexo/public;
index index.html index.htm;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/hexo.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hexo.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES25> ssl_prefer_server_ciphers off;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location / {
try_files $uri $uri/ =404;
}
}
server {
if ($host = hexo.example.com) {
return 301 https://$host$request_uri;
}
server_name hexo.example.com;
listen 80;
listen [::]:80;
return 404;
}
Save the file by pressing Ctrl+X and entering Y when prompted.
Activate the configuration.
$ sudo ln -s /etc/nginx/sites-available/hexo.conf /etc/nginx/sites-enabled/
Open the /etc/nginx/nginx.conf
file for editing.
$ sudo nano /etc/nginx/nginx.conf
Paste the following line before the line include /etc/nginx/conf.d/*.conf
server_names_hash_bucket_size 64;
Change the value of the variable types_hash_max_size
from 2048 to 4096.
types_hash_max_size 4096;
Press Ctrl + X to close the editor and press Y when prompted to save the file.
Test to make sure there are no syntax errors in your configuration.
$ sudo nginx -t
If there aren't any issues, restart the Nginx server.
$ sudo systemctl restart nginx
Install SSL
It is time to install SSL using Let's Encrypt service for our hexo blog.
For that, install Certbot.
$ sudo apt install certbot
Stop Nginx because it will interfere with the Certbot process.
$ sudo systemctl stop nginx
Generate the certificate. We also need to create a DHParams certificate.
$ sudo certbot certonly --standalone -d hexo.yourdomain.com --preferred-challenges http --agree-tos -n -m [email protected] --keep-until-expiring
$ sudo systemctl start nginx
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
We also need to set up a cron job for renewing the SSL automatically. To open the crontab editor, run the following command.
$ sudo crontab -e
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]: 1
The above command opens Crontab editor. If you are running it for the first time, you will be asked to choose the editor for editing Cron jobs. Choose 1 for the Nano editor.
Paste the following line at the bottom.
25 2 * * * /usr/bin/certbot renew --quiet --pre-hook “systemctl stop nginx” --post-hook “systemctl start nginx”
The above cron job will run certbot at 2:25 am every day. You can change it to anything you want.
Save the file by pressing Ctrl + X and entering Y when prompted.
Update Hexo
Switch to the Hexo folder.
$ cd /var/www/hexo
If you are switching to a major Hexo version, you need to update the package.json
file. Open it for editing. You can skip directly to the update command for updating to minor versions.
$ nano package.json
Change the following line under the dependencies
section.
"hexo": "^5.0.0",
Change the value 5.0.0
to the next version whenever it releases in the future. For example, if Hexo 6.0 is out, then change it to following.
"hexo": "^6.0.0",
Save the file by pressing Ctrl + X and entering Y when prompted.
Run the following command to update hexo.
$ npm update
Deploying Hexo
Hexo can not only be hosted directly on your server but can also be deployed directly on Git, Netlify, Vercel, Heroku, OpenShift and various other methods.
Most of the deployment plugins require you to install a plugin. For our tutorial, we will setup Hexo's deployment to Netlify. If you want to deploy to Netlify, then you don't need to follow the steps related to Nginx and SSL as Netlify comes with free SSL.
A Netlify's site is usually deployed from a Git repository. But for our purpose, we will directly publish the static site to Netlify using its CLI tool.
Install Netlify CLI.
$ sudo npm install netlify-cli -g
You can verify to see if the CLI tool was installed.
$ netlify --version
netlify-cli/2.68.5 linux-x64 node-v14.15.0
Login to Netlify.
$ netlify login
Logging into your Netlify account...
Opening https://app.netlify.com/authorize?response_type=ticket&ticket=dfb575d97d07213c9cf73848c8d19e90
You are now logged into your Netlify account!
Run netlify status for account details
To see all available commands run: netlify help
Copy the login from the terminal in your browser and login to your Netlify account to authentifcate.
You can check if you are logged in by using the following command.
$ netlify status
???????????????????????
Current Netlify User ?
???????????????????????
Name: Your Name
Email: [email protected]
Teams:
Your Team's team: Collaborator
Switch to Hexo's public directory.
$ cd /var/www/hexo/public
Deploy the site to Netlify.
$ netlify deploy
This folder isn't linked to a site yet
? What would you like to do? + Create & configure a new site
? Team: Navjot Singh's team
Choose a unique site name (e.g. isnt-yourname-awesome.netlify.app) or leave it blank for a random name. You can update the site name later.
? Site name (optional): Howtoforge
Site Created
Admin URL: https://app.netlify.com/sites/Howtoforge
URL: https://Howtoforge.netlify.app
Site ID: 986c931c-3f06-40a1-a89b-59621f337c18
Please provide a publish directory (e.g. "public" or "dist" or "."):
/var/www/hexo/public
? Publish directory /var/www/hexo/public
Deploy path: /var/www/hexo/public
Deploying to draft URL...
? Finished hashing 37 files
? CDN requesting 9 files
? Finished uploading 9 assets
? Deploy is live!
Logs: https://app.netlify.com/sites/howtoforge/deploys/5fb0c9b806e72eb9c5f073c8
Website Draft URL: https://5fb0c9b806e72eb9c5f073c8--howtoforge.netlify.app
If everything looks good on your draft URL, deploy it to your main site URL with the --prod flag.
Choose by arrow keys to create a new site and enter a name for your site. Enter .
as the directory to deploy from which refers to the current directory.
You will be given a draft URL. Copy the URL and load it into a browser. If everything looks fine, then run the following command to do a production deployment.
$ netlify deploy --prod
Your site should now be live. You can add a custom domain in Netlify settings to point it into a real site.
Every time you publish a new post and generate fresh files, run the following command from Hexo's main directory to deploy the changes to Netlify.
$ netlify deploy --dir ./public --prod
Conclusion
This concludes our tutorial to install and create a blog using the Hexo Blog framework on Ubuntu 20.04 based server. If you have any questions, post them in the comments below.