Create a Hugo Blog, along with Isso comment server

Page content

This post includes the workthrough of installation, configuration and integration of Hugo and Isso comment server.

Hugo logo Plus Isso logo

Steps:

  • Install and configure of Hugo
  • Install and configure of Isso comment server in a remote server
  • Integrate Isso with Hugo
  • Publish to an existing GitHub Page

Environment:

Both local computer and remote server work on Debian bullseye.

0. Prerequisites

  • A domain name for GitHub pages:
    • e.g., myblog.com
    • or username.github.io, provided by GitHub Pages.
  • A remote server:
    • You can log in the server via SSH, and work as root, or by sudo
    • Installed the Nginx web server, and (or) enabled https
    • With domain name: comments.mysite.com

1. Install & setup Isso server

1.1 Install Isso in Debian

Although there is a Isso package in Debian repository, it could not work properly. So I installed it accroding to the documentation.

(1) Login to your remove server first.

(2) Install necessary packages

$ sudo apt update
$ sudo apt install python3-setuptools python3-virtualenv python3-dev sqlite3 build-essential

(3) Create a user called ‘isso’:

$ sudo adduser isso

For security consideration, the user isso do NOT able to login the server. Simple append it to the DenyUsers statement of /etc/ssh/sshd_config file:

DenyUsers isso

Then restart sshd service:

$ sudo systemctl restart sshd.service

(4) Switch to user ‘isso’ and install Isso

  • The Isso document emphasized that never install Python packages as ‘root’.
# Switch to user 'isso'
$ sudo su isso
# Go to HOME dir of 'isso'
$ cd

The next operations as the user isso:

# Create necessary dirs
$ mkdir db etc log
# Create virtual environment 'isso'
$ virtualenv ~/venv/isso
# Activate the environment
$ source ~/venv/isso/bin/activate
# Install Isso
(isso) $ pip3 install isso
# Install gevent if necessary
(isso) $ pip3 install gevent

(5) Upgrade

If you’d like to upgrade Isso later, simply run:

(isso) $ pip3 install --upgrade isso

1.2 Configuration

(1) Directiry structure

If completed, the HOME directory of user isso would be like:

$ tree -L 3

.
├── db
│   └── comments.db
├── etc
│   └── comments.cfg
├── log
│   ├── isso-cmd.log
│   └── isso.log
└── venv
    └── isso
        ├── bin
        ├── include
        ├── lib
        └── pyvenv.cfg

Let’s work for it.

(2) Custom Isso configure file

Create an ini-format configure file ~/etc/comments.cfg:

[general]
; Batabase location, check permissions, automatically created if not exists
dbpath = /home/isso/db/comments.db
; Blog website url
host = https://comments.mysite.com/
; Get new comments notification via SMTP
notify = smtp
; Log file
log-file = /home/isso/log/isso.log

[moderation]
; Enable comment moderation
enabled = true
purge-after = 30d

[server]
; Listen custom port 7845
listen = http://localhost:7845

[smtp]
; Please read the information of email server
username = mailuser
password = mailpwd
host = smtp.mailserver.com
port = 465
security = ssl
to = [email protected]
from = "my blog comments"<[email protected]>
timeout = 10

[guard]
; Enable basic spam protection features
; REMEMBER to edit the client configuration accordingly
enabled = true
; limit to 2 new comments per minute
ratelimit = 2
; limit 25 comments directly to the thread
direct-reply = 25
; allow commenters to reply to their own comments when they could 
; still edit the comment
reply-to-self = true
; force commenters to enter a value into the author field
require-author = true
require-email = false

[markup]
options = strikethrough, superscript, autolink
allowed-elements =
allowed-attributes =

[hash]
salt = Eech7co8Ohloopo9Ol6baimi
algorithm = pbkdf2

[rss]
; provide an Atom feed for each comment thread

[admin]
; Provide a web administration interface
enabled = true
password = isso_admin_password

Please refer More parameters to the documentation.

1.3 Test configuration

Simply run Isso program as:

(isso) $ isso -c ~/etc/comments.cfg run

If there were no error message output, the configuration file is ok.

Press Ctrl-C to stop Isso running right now.

1.4 Configure Nginx

Open a new terminal window and login to remove server. Please note, starting now, we will work on two terminal windows, one for Nginx configuration, the other one for Isso configuration.

Edit the Nginx configure file /etc/nginx/site-enabled/mysite.conf and insert isso-related configuration:

server {
        server_name comments.mysite.com;

        root /var/www/isso;
        index index.html;

        location / {
                try_files $uri $uri/ =404;
        }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mysite/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mysite/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # For isso
    location /isso {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Script-Name /isso;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://localhost:7845;
    }
}

server {
    if ($host = comments.mysite.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        listen [::]:80;

        server_name comments.mysite.com;
    return 404; # managed by Certbot
}

Note: The HTTPS has been configured by Let’s Encrypt.

Test the modification first:

$ sudo nginx -t

If no error message printed, restart Nginx server:

$ sudo systemctl restart nginx

1.5 Web interface of Isso comments database

In the terminal working on isso, re-run the Isso server:

(isso) $ isso -c ~/etc/comments.cfg run &

Then the comments database would be available at: https://comments.mysite.com/isso/admin

Input your isso_admin_password in isso configure file comments.cfg.

1.6 Running Isso as a service

As the above operation, you have to remember to run isso everytime your server start/restart. Here is an approach to setup Isso as a systemd service.

Still in the Isso working terminal, create a bash script, /home/isso/bin/isso-start.sh:

#!/bin/bash
set -e

# Lanuch venv `isso`
source /home/isso/venv/isso/bin/activate

ISSO_CFG=/home/isso/etc/comments.cfg

# launch isso server
isso -c $ISSO_CFG 

Next add excute permission:

(isso) $ chmod u+x ~/bin/start-isso.sh

Switch to the normal terminal window, create systemd service file isso.service:

$ sudo vim /lib/systemd/system/isso.service
[Unit]
Description=Isso Comment Server

[Service]
Type=simple
User=isso
workingDirectory=/home/isso
ExecStart=/home/isso/bin/start-isso.sh
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Now we need to enable the service:

$ sudo systemctl daemon-reload
$ sudo systemctl enable isso

OK, we could start Isso service by:

$ sudo systemctl start isso

And check its status by:

$ systemctl status isso

2. Hugo

The next steps work on your own computer.

2.1 Install Hugo

Hugo is already in Debian repository.

Suppose you are running Debian GNU/Linux in your own computer, run

$ sudo apt update
$ sudo apt install hugo

For other OS, please visit Hugo document.

2.2 Create a site

$ hugo new site myblog

It creats a new Hugo site in the folder myblog, and the dir structure is:

myblog/
├── archetypes
│   └── default.md
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes
Directory & File Description
archetypes Store .mdtemplate files, it has higher priority than archetypes/ folders under the theme/.
config.toml The main configuration file.
content Stores all the content of the website. Each top-level folder in Hugo is considered a content section. e.g., blog/, articles/, and tutorials/. Hugo uses sections to assign default content types.
data Store configuration files that can be used by Hugo when generating your website. Support YAML, JSON and TOMI format.
layouts Stores templates in the form of .html files that specify how views of your content will be rendered into a static website.
static Stores all the static content: images, CSS, JavaScript, etc. The files in this directory will be directly copied to /public later.

2.3 Customize Hugo theme

Hugo does not provide a default theme. So user have to choose a theme from themes.gohugo.io first. I’m using the theme mainroad.

$ cd myblog/themes
$ git clone https://github.com/vimux/mainroad

The myblog/ directory would be like:

myblog/
├── archetypes
│   └── default.md
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes
    └── mainroad
        ├── archetypes
        ├── assets
        ├── CONTRIBUTING.md
        ├── exampleSite
        ├── i18n
        ├── images
        ├── layouts
        ├── LICENSE.md
        ├── package.json
        ├── package-lock.json
        ├── README.md
        ├── static
        └── theme.toml

2.4 Customize the theme

Edit the configuration file config.toml under the myblog/ folder:

baseURL = "https://myblog.com/" # The blog url. Don't forget the tailing '/'
title = "My Blog"
languageCode = "en-us"
theme = "mainroad" # Using Hugo theme 'mainroad'
googleAnalytics = "UA-000000000-0" # Google Analytics tacking id

[Author]
  name = "John Doe"
  bio = 'John Doe's biography'
  avatar = "img/avatar.png" # Path 'myblog/static/img/'

[Params]
  subtitle = "" # Deprecated in favor of .Site.Params.logo.subtitle
  description = "John Doe's Blog" # Site description. Used in meta description
  copyright = "John Doe" # Footer copyright holder, otherwise will use site title
  opengraph = true # Enable OpenGraph if true
  schema = true # Enable Schema
  twitter_cards = true # Enable Twitter Cards if true
  readmore = true # Show "Read more" button in list if true
  authorbox = false # Do not show authorbox at bottom of pages if true
  toc = true # Enable Table of Contents
  pager = true # Show pager navigation (prev/next links) at the bottom of pages if true
  post_meta = ["author", "date", "categories", "translations"] # Order of post meta information
  mainSections = ["posts", "blogs", "news"] # Specify section pages to show on home page and the "Recent articles" widget
  DateForm = "2020-01-01"
  googleFontsLink = "https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700" # Load Google Fonts

[Params.style.vars]
  hightlightColor = "#2B547E"

  # Override font-family sets. Secondary font-family set responsible for pre, code, kbd, and samp tags font
  # Take care of different quotes OR escaping symbols in these params if necessary
  fontFamilyPrimary = "'Open Sans', Helvetica, Arial, sans-serif"
  fontFamilySecondary = "SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace"

[Params.logo]
  image = "img/logo.png" # Logo image. Path relative to "static"
  title = "John Doe's Blog" # Logo title, otherwise will use site title
  subtitle = "A bit more details" # Logo subtitle

[Params.sidebar]
  home = "right" # Configure layout for home page
  list = "right"  # Configure layout for list pages
  single = "right" # Configure layout for single pages
  # Enable widgets in given order
  widgets = ["search", "recent", "categories", "taglist", "social"]

[Params.widgets]
  recent_num = 5 # Set the number of articles in the "Recent articles" widget
  categories_counter = false # Enable counter for each category in "Categories" widget
  tags_counter = false # Enable counter for each tag in "Tags" widget

[Params.widgets.social]
  # Enable parts of social widget
  # facebook = "username"
  # twitter = "username"
  # instagram = "username"
  # linkedin = "username"
  # telegram = "username"
  github = "username"
  # gitlab = "username"
  # bitbucket = "username"
  email = "[email protected]"

[Params.isso]
  # Parameters for Isso comment server
  # Besure to mofity related parameters according to the "[guard]" section
  # in the Isso configure file "comment.cfg"
  enabled = true
  data = "https://comments.mysite.com/isso/"
  id = "thread-id"
  css = true
  lang = "en"
  replyToSelf = true
  requireAuthor = true
  requireEmail = false
  avatar = true
  avatar-bg = "#f0f0f0"
  jsLocation = "https://comments.mysite.com/isso/js/embed.min.js"

2.5 Create your first post

Under the myblog directory, run:

$ hugo new posts/my-first-post.md

Edit and add some contents in this file. Then run:

$ hugo server -D

Visit the site at http://localhost:1313/.

3. Integrate Hugo/mainroad with Isso comment server

Hugo uses Go’s html/template and text/template libraries as the basis for the templating.

Considering the complicated template syntax, it’s a bit complicated to integrate Isso with Hugo theme.

For the theme mainroad, just edit the file comments.html in the themes/mainroad/layouts/partials/:

$ vim myblog/themes/mainroad/layouts/partials/comments.html

Insert Isso templates before the last row {{ END }}. The modified comments.html file would be like:

{{ if and .Site.DisqusShortname (index .Params "comments" | default "true") (not .Site.IsServer) }}
<section class="comments">
	{{ template "_internal/disqus.html" . }}
</section>
{{/* Add support for ISSO comment system */}}
{{ else if .Site.Params.isso.enabled }}
  <article class="post">
    <script
        data-isso="{{ .Site.Params.isso.data }}"
        data-isso-id="{{ .Site.Params.isso.id}}"
        data-isso-css="{{ .Site.Params.isso.css }}"
        data-isso-lang="{{ .Site.Params.isso.lang }}"
        data-isso-reply-to-self="{{ .Site.Params.isso.replyToSelf }}"
        data-isso-require-author="{{ .Site.Params.isso.requireAuthor }}"
        data-isso-require-email="{{ .Site.Params.isso.requireEmail }}"
        data-isso-avatar="{{ .Site.Params.isso.avatar }}"
        data-isso-avatar-bg="{{ .Site.Params.isso.avatarBg }}"
        src="{{ .Site.Params.isso.jsLocation }}">
    </script>
    <noscript>Please enable JavaScript to view the comments powered by <a href="https://posativ.org/isso/">Isso</a>.</noscript>
    <div>
      <section id="isso-thread"></section>
    </div>
</article>
{{ end }}

All parameters listed here could be found in the [Params.isso] section in the main config.toml file.

You can add more parameters in it according to Isso documentation.

If the Hugo server is still running, you could find the page refreshed automatically in web browser and the comment area appears. Otherwise, re-run:

$ hugo server -D

4. Publish to GitHub Page

4.1 Let the Hugo know to publish the post

Remove or comment the row draft: true in the heading area of your post page.

4.2 Build static pages

Run the command:

$ hugo -D

It creates a new directory public/. Create a file CNAME, of which content is:

mysite.com

4.3 Publish to GitHub Pages repository

Since I already created a GitHub Page, I just replace the contents in the existing repository:

$ cd myblog/public
# Init an empty Git repo
$ git init
$ git add .
$ git commit
$ git remote add origin https://github.com/your_repo/your_repo.github.io.git
$ git push -f origin master

The whole workflow completed. We could visit https://mysite.com now.

For publishing new posts later, simply run:

$ git add .
$ git commit
$ git push

5. Misc Tips

5.1 Change the start level of table of contents (TOC)

At the begining of the post, there is a TOC to show the heading levels. The default start level of it is 2. So the level 1 will never be displayed. To modify it, simple add the next block into your config.toml file:

[markup]
  [markup.tableOfContents]
    endLevel = 3
    ordered = false
    startLevel = 1

Save the file and re-publish your blog.


A. References:

  1. Hugo Documentation
  2. Isso Documentation
  3. Hugo Theme: Mainroad
  4. Adding Isso Comments to Hugo
  5. Build a Personal Website With Github Pages and Hugo
  6. Add comments to a static blog with Isso
  7. Debian / Ubuntu 搭建 Isso 评论系统教程
  8. Static site migration - we have working comments with isso!
  9. How to add Isso comments to your site
  10. Installing, configuring, and integrating isso (commenting web app) into Confluence
  11. Isso: simple self-hosted commenting system
  12. Hugo: Configure Markup