Setup a self-hosted commenting system on your blog

Privacy Mar 7, 2021

After adding the privacy and data notice on this blog, it felt like it's time to reduce the 2-11 trackers that were being blocked by Brave browser and bring it down to zero. Also, since Disqus tracks visitor data on the free tier (still, they have a Do Not Sell My Data policy which can be toggled on and off, it still didn't feel okay to even allow Disqus tracking data on this blog by default), so, I decided to switch to a self-hosted commenting system that would respect the privacy of the users accessing this blog.

Women look at security cameras
Photo by Matthew Henry / Unsplash

Let's get into the tutorial.

We will be replacing Disqus with Remark42 commenting system which can be self-hosted and ensures the privacy of incoming users. We will only allow GitHub login for the folks who decide to use their GitHub profile to interact in the comments section. Since, this is a tech blog, I hope everyone has a GitHub account. Also, you will be able to comment as an Anonymous user as well. (We can have moderators enabled on this system, so spam and abusive comments can be very well handled!)

For this tutorial, I'll be using one of my servers from Oracle Cloud free tier running Ubuntu 20.4 LTS:

How to get 2x Oracle Cloud servers free forever
This is a follow up to my How to get a Google server free forever post. In the comments selim13 let...

Step 1: Download latest release from GitHub and extract it:

wget -O remark42.linux-amd64.tar.gz

tar xzf remark42.linux-amd64.tar.gz remark42.linux-amd64

mv remark42.linux-amd64 /usr/local/bin

Step 2: Create remark42 user and base directory:

useradd -r remark42

mkdir -m 770 /var/www/remark42

chown :remark42 /var/www/remark42

Step 3: Create the configuration file

vim /var/www/remark42/remark42.conf

Step 4: Create a systemd service for remark42:

Description=remark42 comment engine

ExecStart=/usr/local/bin/remark42.linux-amd64 server


Activate the service:

systemctl enable --now remark42

Step 5: Setup GitHub OAuth in order to allow users to authenticate the commenting system using their GitHub account:

  1. Go to GitHub -> Click on Profile Icon -> Click on Settings -> Developers -> OAuth Apps
  2. Click on New OAuth App
  3. Set base URL to same value as  in environment file
  4. Set callback URL by appending auth/github/callback to the base RemarkURL:
  5. Note down client id and client secret and add them to environment configuration file
vim /var/www/remark42/remark42.conf

Step 6: Test the setup by going to the demo URL:

Append /web/ to the base URL which would look something like:

Remark42 Demo Page

Step 7: Setup yourself as the moderator and admin:

Login into your commenting system with GitHub to get the login ID which would start with github_

vim /var/www/remark42/remark42.conf
GitHub Login ID

Step 8: Embed the commenting system on your Ghost blog:

Add the below <div> and <script> to the post.hbs file at /var/www/ghost/content/themes/<theme_name>/ where you want the comments to appear.

<div id="remark42"></div>
  var remark_config = {
    host: "REMARK_URL",
    site_id: 'YOUR_SITE_ID',
    components: ['embed'],
    max_shown_comments: 10, 
    theme: 'light', 
    locale: 'en', 
    show_email_subscription: false 
  (function(c) {
    for(var i = 0; i < c.length; i++){
      var d = document, s = d.createElement('script');
      s.src = + '/web/' +c[i] +'.js';
      s.defer = true;
      (d.head || d.body).appendChild(s);
  })(remark_config.components || ['embed']);

And there it is. The commenting system should be up and running by now with GitHub and Anonymous login options.

Remark42 in Production where I just typed random characters for testing without giving it even a second of thought

Step 9: Setup reverse proxy with Nginx:

sudo vim /etc/nginx/sites-available/default
server {
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

    location / {
         proxy_redirect          off;
         proxy_set_header        X-Real-IP $remote_addr;
         proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header        Host $http_host;
         proxy_pass    ;
sudo nginx -s reload


Configure the Ghost theme to detect Dark or Light mode from the user's browser and configure the comment system to match it while loading completes. The below script will detect browser if it has a dark mode enabled by default and match it. In case the browser is set to light mode by default, the above embedding configuration has light mode already enabled by default.

window.onload = function() { 
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {


Configure the Ghost theme to change theme according to the Dark/Light theme toggle. Now, in most cases, the toggle to change theme is based on an <input> tag being used as a checkbox:

Add onchange event listener to the toggle:

<input type="checkbox" name="toggle-dark" onchange="toggleComments()">
var toggleComments = function() {

if (document.getElementById("toggle-dark").checked == true) {
} else {


P.S. - I am happy to say that now with this change applied, the trackers on this blog as shown on Brave browser are down to zero. If you click the BMC widget, it does initiate some trackers (4-5 in total), but they are handled by Brave quite well. So, yeah, it's okay to say Brave is one of my favouite companies along with Cloudflare.

[Update - 13th March 2023]

As of today, I have retired this commenting system on the blog due to resource constraints.