When I set up this blog earlier this year I intended this place as a one-way communication system, whereas I would simply add articles or tutorials from time to time. Having had other blogs in the past I knew very well that one of the best ways to keep this interesting and useful was to open it up for comments and reactions from others.
However, I was struggling to find a good service to implement this. Disqus is typically a quick, free easy solution and works well. However, in a post-GDPR 🇪🇺 world, it was difficult to understand:
What data do they collect about users
What do they do with it
Commento.io is an open-source, privacy-focused and feature-rich commenting system that can be embedded as easily as Disqus into your site. It offers a few things:
Easy embedding into existing sites such as this one
The best thing, however, is that you can also self-host the system, which is what I have decided to do. The advantages are that:
You don't pay for anything. Well, you pay for your existing host and your setup and maintenance efforts - as I said above there ain't no magic money tree 😉 If you own a truly popular blog or website, it might mean scaling your existing resources.
You retain all the data. In my case, the comments data will sit alongside the blog in the London datacenter it uses. This means it stays within the EU (at least for the time being... let's not even start that conversation 🤷🏾♀️)
Let's see what it takes to get it done.
Before you begin, it's best to check a few requisites:
An open browser tab at docs.commento.io: I should have said above, the documentation is pretty slick!
A terminal session into your target host for running Commento.
Your site's DNS configuration interface open, as you'll need to add a DNS rule.
I'm also making a few assumptions to keep it simple:
You are installing Commento on the same host where Ghost runs, and that the host runs Ubuntu 18.04.
You'll be using Nginx as the webserver.
You are using Digitalocean - as I'm linking a few of their excellent documentation pages. The instructions are pretty generic and should work anywhere else as long as it's the same Linux distribution.
You don't have a CDN / hardened set up such as the one I described here - if you have this, it just means that the Nginx configuration and SSL set up may involve a few extra steps. As an example, if you serve your subdomain via Cloudflare and you have authenticated origin pulls enabled, then you'll need to relevant configuration lines and certificate added in your Nginx configuration.
Let's get going now!
Once you opened your terminal session, you will need to install Postgresql as this is the database system used by Commento to store the comments data - If you are on Digitalocean then you may as well keep this guide in the background.
Once the installation is complete, start the database and then verify that it's running correctly
sudo systemctl start postgresql
sudo systemctl status postgresql
The second command should tell you something similar to the below
$ sudo systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
Active: active (exited) since ...
Process: [...] ExecStart=/bin/true (code=exited, status=0/SUCCESS)
Main PID: [...] (code=exited, status=0/SUCCESS)
[...] systemd: Starting PostgreSQL RDBMS...
[...] systemd: Started PostgreSQL RDBMS.
Meaning Postgres was installed successfully and it's ready to be configured. Before doing that, we want to tell systemd to enable Postgresql at boot so that it runs automatically if your host is re-started (more info here if you are not familiar with systemctl and systemd)
sudo systemctl enable postgresql
For getting up and running with Commento, you'll need to set up an empty database and a database role. In Postgresql, a database role is very similar to a user, and we will use it to configure the DB connection configuration from Commento (more about Postgresql roles here).
Let's do that now:
sudo -i -u postgres
The postgres user was created automatically during the installation of the DB. The above commands are simply getting us into an interactive PostgreSQL command shell. We will use the below SQL commands in order to
Create a commento role
Add a password to the commento role (note it down)
Create an empty database named commento
List all the databases (you should see the one you just created)
Leave the psql command shell
CREATE ROLE commento WITH LOGIN;
CREATE DATABASE commento;
Once done you can exit the postgres user session
Subdomain & SSL configuration
If your main blog is at www.example.com, you'll want to choose a subdomain such as commento.example.com or similar. You then need to configure a DNS A rule pointing that subdomain to your host's IP address.
Then, depending on your existing domain configuration, you will need to set up SSL accordingly (because who doesn't serve content online without SSL nowadays 👱🏻♀)
Getting a certificate today is a no brainer thanks to Let's Encrypt - so I will give an example based on obtaining a wildcard certificate with certbot for your domain and assuming you use Cloudflare as your DNS provider (note: there are plenty of other DNS plugins if you are on another
The third package in particular (python3-certbot-dns-cloudflare) is used to automate the dns-01 challenge method which will be used to obtain the certificate. In other words, it will allow certbot to use the Cloudflare APIs to set up an appropriate DNS TXT rule. That rule is then used by certbot to verify ownership of the domain and in turn allowing you to obtain a certificate for that domain.
I prefer the DNS method because it avoids all the headaches due to a hardened configuration. For example, using the standard method (which temporarily runs a webserver on port 80) wouldn't work for me because I have a strict TLS policy in place and the verification request will never make it to the temporary webserver.
For the dns-cloudflare plugin specifically, you will need to store your Cloudflare credentials in a file. You must put this in a secure location as anyone able to read that file will be also able to see your global cloudflare API key
Update (August 2020): as the certbot Cloudflare plugin now supports token authentication - it is highly recommended to create a scoped token instead of using your global api key. Simply change the contents above to only include dns_cloudflare_api_token = <TOKEN> . The token will need to have DNS editing permissions on the required Cloudflare Zone.
For example, let's put it in the /etc/letsencrypt folder
You should see something like this in a successful scenario
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-cloudflare, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for test.example.com
Waiting 30 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges
- Congratulations! Your certificate and chain have been saved at:
Your key file has been saved at:
Your cert will expire on 2020-02-28. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
You can safely delete the test certificate now - we just wanted to validate that you set up your dns based authentication with Cloudflare correctly.
The above means that every day at 19:00 the command will be executed and then reload nginx to pick up the new changes (if any). You can tweak the crontab to run at a more convenient time for you, but I recommend that you keep it on a daily frequence. Please note that this command attempts to renews all certificates that are managed by certbot.
You can also test the command in your console to see what it does (I added a --dry-run flag to it).
Now that you have a valid certificate and that it's primed for auto-renewal, it's time to configure nginx so that it's ready to serve requests securely.
Let's set up our nginx webserver so that it's ready to take requests securely, and forward them to Commento. Let's assume the following
Your domain is commento.example.com
You will run Commento on the same host as nginx , on port 1234
You will configure your certificate and private key to the paths indicated by certbot when you created it
The certificate is either a wildcard certificate or a certificate for your specific subdomain.
Then you will want a similar configuration file in /etc/nginx/sites-available/commento.example.com
You can then symlink your above configuration file in /etc/nginx/sites-enabled when you are ready to go. We are not quite ready yet as we still need to install Commento!
Install Commento and enable at boot
We will create a user called commento and we will install commento in that user's home folder.
sudo adduser commento
sudo -i -u commento
Make sure you are in the home directory and download the most recent binary release (1.7.0 right now - please check and update accordingly the below commands)
tar xvf commento-linux-amd64-v1.7.0.tar.gz -C commento-linux-amd64-v1.7.0
ln -s commento-linux-amd64-v1.7.0 commento-latest
The symlink just helps to manage future updates, so that it can be pointed to the new codebase folder when it's released. In fact, it would be probably best to containerize the entire installation but that's a story for another day 👩🏾🏭
What we do want to do now is to create a systemd definition so that we can enable and run commento at boot automatically. For that, you can use the template provided and then add it to service definitions. Do update your ExecStart location if you installed it in a place different than the one I used.
sudo touch /etc/systemd/system/commento.service
Then update your service definition accordingly:
ExecStart: update to your location if different
COMMENTO_ORIGIN : update domain
COMMENTO_PORT : update port and make sure that it corresponds to the port you set up in nginx above (it was 1234 in that example)
COMMENTO_POSTGRES: update with the Postgres Role and Password as per earlier instructions.
The whole system should be now almost ready to serve your self-hosted Commento installation securely over HTTPS. You will need to create an administrative user on the Commento interface. Because this is publicly accessible, you will want to do that fairly quickly before someone else starts mucking with it. Or use some Cloudflare rules to temporarily lock everyone out that page except yourself... I didn't bother!
First thing first, let's double-check our Nginx configuration, symlink it to the sites-enabled folder (if you didn't do that already), then check the config is sane before reloading
sudo nginx -t
sudo nginx -s reload
You should now be able to navigate to your commento subdomain and sign up your administrative user. The official documentation should help you here if not self-explanatory.
Now that you have created your admin user, disable the creation of new owners. Stop the service:
sudo systemctl stop commento
Then modify the service definition above to include
This environment variable will prevent the creation of new admin users
Then restart the service
sudo systemctl start commento
You can verify that this worked by trying to sign up again on the administrative interface. The Sign Up form should be available, but any attempts to submit it should result in an error message.
Add Commento snippet to your blog/site
The very last thing to do is to add the Commento code snippet to your blog/site. This is accomplished by including the following snippet (replace the domain with yours)
For ghost, if you use the standard 'Caspar' theme there is a placeholder that is ideal for this in the post.hbs template. You can use the official Ghost instructions for Disqus (but you will be using your kick-ass, self hosted Commento instead).
There are further configuration options which you should definitely consider before putting this live, but these are for another day (or maybe you want to experiment a little yourself):
Configure SMTP: this is neat especially if you plan to allow users to type in their e-mail addresses when leaving comments. It also helps you in case you forget your administrative user password, as the system comes with a Forgot Password facility. You can refer to the SMTP options available here to understand how to do this. If you are using something like Mailgun - which you may have already configured for your Ghost it should be fairly straightforward
Configure Akismet: make sure to grab an Akismet key and include that in your configuration, so that your comments are checked for spam.
Configure Social Sign In: Commento supports several social sign-in facilities. Again, refer to the configuration options page I linked above.
I hope you enjoyed this - let me know if this worked for you!