Comments for a static website with ISSO

When I created this statically generated blog, I decided to not integrate comments. Mainly because there was no solution which suited my needs: self hosted, small, easy to use, nice look.

For my personal website I used Juvia, but for my needs its too big and it seems that there is no development going on anymore. Here comes the solution: ISSO - "Ich schrei sonst" - A disqus alternative. It's written in Python and very lightweight.

Some features:

  • Disqus import
  • Small SQLite backend (because comments are not big data, says the website)
  • Lightweight backend, most work is done on the client (JS)
  • Up and Downvoting
  • Threaded answers
  • Possibility to edit or delete own comment during 15 minutes
  • E-Mail notifications
  • Comment moderation

The documentation is already very well. Just follow the installation docs.

I wanted to run an ISSO instance per domain under /isso/, mainly to avoid troubles with CORS or some browser security plugins. And as I run all websites with TLS, it is the best choice to run such applications under the same URL.

But I had some troubles getting it to run with mod_wsgi, running on a subfolder (not subdomain), as I'm really not a specialist on running Python applications. Here are some steps to get ISSO up and running with mod_wsgi on Apache:

Apache with mod_wsgi

You need mod_wsgi installed and enabled. On Ubuntu/Debian: apt-get install libapache2-mod-wsgi && a2enmod wsgi && service apache reload

The needed Apache configuration is very simple, just add it to the VHost definition:

WSGIScriptAlias /isso /var/www/
WSGIDaemonProcess isso-yoursite user=www-data group=www-data threads=5

This tells the WSGI process to run under the configured user/group. Make sure that this user has read/write permission on /var/www/ This is very important, because SQLite (which runs under this user) needs permission on this folder to create and remove its lockfile. I had the strange behaviour that the SQLite DB file was not created as this defined user (I don't use www-data!) but instead as the user running the Apache webserver (normally www-data). So if you have troubles with file access, just re-check the permissions on this folder.

If you want to run ISSO per domain, as I do, choose a unique WSGIDaemonProcess name (like isso-yoursite).

Now create the WSGI file /var/www/, the following content is sufficient:

import os

from isso import make_app
from isso.core import Config

application = make_app(Config.load("/var/www/"))

And of course, the config file /var/www/ needs to be created too:

; cat /dev/urandom | strings | grep -o '[[:alnum:]]' | head -n 30 | tr -d '\n'
session-key = <output from above>
dbpath = /var/www/
host =

The database is created on the first time the application is accessed.

Integration into Jekyll

It depends on the Jekyll templates used. As a starting point, here are some snippets I used to integrate it into the minimal-mistakes theme.

Jekyll site config: _config.yml:

  data_isso: /isso/
  script_src: /isso/js/embed.min.js

Template: f.e. _layouts/post.html

{% raw %}
{% if site.isso.script_src %}
  <script data-isso="{{site.isso.data_isso}}" src="{{site.isso.script_src}}"></script>
  <section id="isso-thread"></section>
{% endif %}
{% endraw %}

Bonus: Tweet link for comments

I announce most of my posts on Twitter. So I added a new field to the front-matter tweet_url and enhanced the template _layouts/post.html a bit:

{% raw %}
<p class="byline">JavaScript deactivated? Want to send a comment? Write it here: <a href="{% if page.tweet_url %}{{ page.tweet_url }}{% else %}{{ site.owner.twitter }}{% endif %}">@{{ site.owner.twitter }}</a>
{% endraw %}

As soon as the post is written and the Tweet is made, I copy the URL of the Tweet to the front-matter and commit this changes. This is a nice feature for users who have JavaScript deactivated, but want to comment on the post.

Now I'm looking forward to many helpfull comments.

You've successfully subscribed to Tobias Brunner aka tobru
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.