Is
Applications Azure

Isso on Ubuntu 24.04 on Azure User Guide

| Product: Isso on Ubuntu 24.04 LTS on Azure

Overview

This image runs Isso 0.14.0, the open source self hosted commenting server by Martin Zimmermann, on Ubuntu 24.04 LTS. Isso gives any page on your website a comment thread that you own: you drop a single script tag into your template, and readers get threaded discussions, replies, markdown, voting and email notifications, while every comment lives in a database on your own VM.

It is deliberately small. The server is a Python WSGI application and the entire data tier is one SQLite file. There is no separate database server, no cache tier, and no third party service holding your readers' conversations or profiling them for advertising.

Isso comment widget showing a threaded discussion with replies, identicons and voting on the appliance's own demo page

Secure by default. Isso's own shipped configuration contains a published default admin password (please_choose_a_strong_password). This image never ships it. On the first boot of every VM, isso-firstboot.service generates values unique to that VM:

  • a 32 character admin password, which is the only credential for the moderation interface
  • a per VM email hash salt, so commenter email hashes cannot be recovered with a rainbow table built against the salt every other Isso install shares

The image is captured with the admin password empty, which authenticates nobody: Isso's login only proceeds if data["password"] and data["password"] == password, so an empty submitted field is rejected before comparison and an empty configured password can never be matched. A fixed placeholder would be worse, because a placeholder published in a public image is itself a known credential.

Isso will refuse to start until first boot has generated real values, on two independent levers: isso.service declares a hard Requires dependency on the rotation, and a preflight check re runs on every start and refuses an empty, default or short password, which also catches a hand edited configuration rather than only a failed first boot.

The database is deliberately absent from the image, and that is a security control rather than housekeeping. Isso signs its admin session cookie with a session-key that it generates with os.urandom and stores inside the SQLite database, once, when the database is first created. An image that shipped a database would give every customer VM the same signing key, and anyone could forge an administrator session against any VM built from it. Because the image carries no database, Isso mints a fresh signing key on your VM's first start.

Architecture. Isso runs under gunicorn bound to 127.0.0.1:8080, behind nginx on port 80. The application has no public listener of its own, so nginx is the only front door.


Step 1 — Launch the VM

Launch from the Azure Marketplace listing, or from the Azure CLI. Isso is small: Standard_B2s is the recommended size and is ample for a busy site.

az group create --name isso-rg --location eastus

az vm create \
  --resource-group isso-rg \
  --name isso-vm \
  --image cloudimg:isso-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

# Open HTTP so readers can reach the comment server. Never open 8080: gunicorn is bound to
# loopback and nginx is the only intended entry point.
az vm open-port --resource-group isso-rg --name isso-vm --port 80 --priority 900

Note the public IP that az vm create prints — it is used as <vm-ip> throughout this guide.


Step 2 — Confirm the services are running

SSH in as azureuser and confirm both units are active. isso-firstboot is a oneshot unit, so active here means it ran to completion and rotated this VM's secrets.

systemctl is-active isso nginx isso-firstboot

Expected output:

active
active
active

Confirm that Isso itself is bound only to loopback, and that nginx is the only public listener:

sudo ss -tlnp | grep -E ':80 |:8080 '

Terminal showing the isso, nginx and isso-firstboot units all active, with gunicorn bound to 127.0.0.1:8080 and nginx listening on port 80

127.0.0.1:8080 for the Python application and 0.0.0.0:80 for nginx is the expected state. If gunicorn were listening on 0.0.0.0:8080, the application would be reachable around nginx.


Step 3 — Retrieve this VM's admin password

The admin password was generated on this VM's first boot and written to a root owned file with mode 0600.

sudo ls -l /root/isso-credentials.txt
sudo cat /root/isso-credentials.txt

The file contains the site URL, the admin URL and ISSO_ADMIN_PASSWORD. There is no username — Isso's admin interface is authenticated by the password alone.

Terminal showing the credentials file is 0600 root:root, with the per VM admin password value redacted

Store the password in your password manager. Nothing else on the VM will show it to you again in plain text, and the value is unique to this VM.


Step 4 — Verify the server is answering

Isso exposes its effective configuration at /config. This is the appliance's health endpoint:

curl -s http://<vm-ip>/config

Now confirm the endpoint the comment widget itself uses. Isso's comment fetch endpoint is the site root with a uri query parameter naming the page whose thread you want, so this is the exact request your readers' browsers make:

curl -s 'http://<vm-ip>/?uri=%2F' | head -c 200

You should get JSON with a replies array, not HTML. Finally, prove that this VM's password actually authenticates. A 302 is a successful sign in; Isso re serves the login form with 200 when a password is wrong:

curl -s -o /dev/null -w "%{http_code}\n" -X POST -F "password=<isso-admin-password>" http://<vm-ip>/login/

Terminal showing /config returning JSON, the widget's own fetch returning comment JSON, and the per VM password returning HTTP 302


Step 5 — Add your website to the whitelist

This is the step that makes Isso work on your own site, and skipping it is the most common reason a freshly deployed widget stays empty.

Isso only accepts comments from sites you explicitly list. This is a deliberate security boundary: it is what stops anyone else embedding your comment server on their pages. On first boot the image whitelists this VM's own addresses so that the built in demo works immediately, but your site is not in that list yet.

Open the configuration:

sudo nano /etc/isso/isso.cfg

Find [general] host and add your site's URL, one per line, indented. Keep the existing entries. List a non SSL URL first if you serve both, as some browsers suppress the referrer on plain HTTP requests:

[general]
host =
    http://<vm-ip>/
    https://blog.example.com/
    http://blog.example.com/

Restart Isso, then confirm it connected to a configured site. Isso HEAD checks each host at start up, so give it a few seconds before reading the log:

sudo systemctl restart isso
sleep 10
sudo journalctl -u isso -o cat -n 20 | grep -iE "connected to|unable to connect"

connected to ... is the healthy state. unable to connect to your website means Isso could not reach any URL in the list from the VM — check DNS and that the site is reachable from this network.

Why one of the listed URLs is this VM's private address. An Azure VM cannot reach its own public IP: Azure's Standard Load Balancer does not route a VM's traffic back to its own frontend address. Isso HEAD checks each configured host at start up and warns if none answer, so the image lists the private address as well, which the VM can always reach. It also lets you serve readers over the VNet without a public IP at all.


Step 6 — Embed the widget in your site

Add these two lines to your page template, wherever you want the thread to appear. This is the whole integration.

<script src="http://<vm-ip>/js/embed.min.js" data-isso="http://<vm-ip>/"></script>
<section id="isso-thread" data-title="My first post"></section>

data-isso tells the widget where the comment server lives. data-title names the thread.

Set data-title. If you omit it, Isso creates the thread by fetching your page to read its <title>, which means your site must be reachable from the VM at that moment. Supplying the title avoids the fetch entirely and is the more robust choice.

Each page gets its own thread automatically, keyed by its URL path. To show a comment count on an index page without loading the whole widget, use the separate counter script and link to the thread anchor:

<script src="http://<vm-ip>/js/count.min.js"></script>
<a href="/my-post/#isso-thread">Comments</a>

This VM serves a live demo of the widget on its own front page at http://<vm-ip>/, with your embed snippet shown alongside it.

The appliance landing page showing the embed snippet and a live Isso thread with a comment being composed


Step 7 — Moderate your comments

Browse to http://<vm-ip>/admin/ and sign in with the password from Step 3.

The Isso admin sign in page, secured by the per VM password

The dashboard lists every comment with its thread, author and timestamp, and gives you Edit and Delete on each one. The filter bar switches between Valid, Pending and Staled, and you can order by date, likes or dislikes, group by thread, or search by URL.

The Isso moderation dashboard signed in, showing five valid comments with their threads, authors, timestamps and edit and delete controls

The dashboard opens on the Pending filter, which is empty until you enable the moderation queue below. Click Valid to see published comments.

Enable the moderation queue

By default a new comment is published immediately. To hold every new comment until you approve it, set enabled = true in the [moderation] section of /etc/isso/isso.cfg and restart Isso. New comments then appear under Pending and stay invisible to readers until you activate them.

This only affects comments posted after the change; existing comments stay published.


Step 8 — Back up your comments

The entire data tier is one SQLite file, so a backup is one command:

sudo sqlite3 /var/lib/isso/comments.db ".backup '/tmp/isso-backup.db'"
ls -lh /tmp/isso-backup.db

Copy that file off the VM with scp and you have everything: every thread, every comment, and the admin session signing key. Restore by stopping Isso, putting the file back at /var/lib/isso/comments.db with isso:isso ownership, and starting Isso again.

Use .backup rather than copying the file directly — it takes a consistent snapshot of a live database.


Step 9 — Serve comments over HTTPS

If your site is HTTPS, browsers will block requests to a plain HTTP comment server as mixed content, so put a certificate in front of Isso. Point a DNS record at the VM, then:

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d comments.example.com

Then add the HTTPS URL to [general] host, update data-isso in your template to the https:// address, and restart Isso. Isso automatically switches its session cookie to SameSite=None; Secure when it is served over HTTPS, which is what allows the widget to work when your site and your comment server are on different domains.


Troubleshooting

The widget shows nothing on my site. Almost always Step 5: your site's URL is not in [general] host. Check your browser's console for a CORS error, add the URL, and restart Isso.

Isso will not start. Run sudo systemctl status isso and sudo journalctl -u isso -n 30. The preflight refuses to start on an empty, default or short admin password, on an empty [general] host, and on upstream's published default salt. The message names which one. Isso itself also exits if [general] host is empty.

"unable to connect to your website" in the log. Isso HEAD checks each configured host at start up. It is a warning, not a failure, and commenting still works — but it means none of the listed URLs answered from the VM. Note that the VM cannot reach its own public IP by design (see Step 5).

A comment fails with "URI is not accessible and no title was provided". The thread did not exist yet and Isso could not fetch the page to read its title. Add data-title to your <section id="isso-thread"> (Step 6).

I lost the admin password. Set a new one in [admin] password in /etc/isso/isso.cfg and restart Isso. Use at least 20 characters; the preflight rejects anything shorter.

Comments are being rejected as spam. [guard] rate limits to 2 new comments per minute per client subnet and 3 top level comments per thread. Raise ratelimit and direct-reply if that is too strict for your traffic.


What is installed

Component Detail
Isso 0.14.0, MIT licence, in a virtualenv at /opt/isso
Application server gunicorn, bound to 127.0.0.1:8080
Web server nginx on port 80, the only public listener
Database SQLite at /var/lib/isso/comments.db
Configuration /etc/isso/isso.cfg, mode 0640 root:isso
Credentials /root/isso-credentials.txt, mode 0600 root:root
Firstboot isso-firstboot.service, rotates the admin password and salt per VM
Preflight /usr/local/sbin/isso-preflight.sh, runs on every start of isso.service

The configuration file holds the admin password in plain text, because Isso compares it as a plain string and has no hashed form. It is readable only by root and the isso service account, and it is not reachable over HTTP.


Support

This image is packaged and maintained by cloudimg. Isso itself is free software under the MIT licence, developed by Martin Zimmermann and the Isso contributors — cloudimg is not affiliated with the Isso project.

For image specific questions, contact cloudimg support through the Azure Marketplace listing. For questions about Isso itself, see the Isso documentation.