Table of Contents
Overview
Tinycomments is a small self-hosted commenting engine designed to be used with Tinyblog, although it could be used with any website with some adaptation (a little if you’re just using a different Hugo theme, more if you don’t use Hugo at all.) The latest version of Tinycomments is published here.
Like Tinyblog, Tinycomments is built with no externally hosted dependencies and with privacy in mind. It doesn’t use third-party registration or tracking systems of any kind, nor does it require formal user registration. It does use JavaScript local storage to store a poster id, and it asks commenters to enter their email address (although, of course, that email address isn’t displayed publicly.) I feel like that, along with an invisible (to the user) escalating proof of work system, should discourage spambots.
Time will tell, I suppose.
The backend was not written with serverless tools in mind, although if someone was sufficiently motivated, it would be pretty easy to adapt to Lambda or something similar.
The server side is implemented as an HTTP server, which is intended to be reverse-proxied by your main web server. It uses sqlite for data storage, and includes a systemd unit file as well as an rc-style init script to make starting the server easy. Despite the journal being the absolute worst part of systemd, server-side logging is just to stdout and will get sucked into the journal.
Features
- Post and retrieve comments (top-level and nested replies are supported.)
- Upvote/downvote comments
- Basic moderation
- A proof-of-work system for bot/dos mitigation
Design Goals
- Let the database (Sqlite) do the heavy lifting wherever possible.
- Audit and sanitize all input on the way into the database
- Keep the implementation simple
Installation
Build the server binary and copy it to your server.
You’ll need Rust installed for this step; using Rustup is the easiest way to get going if you don’t already have the toolchain installed.
marcusb@dom:~/tmp$ git clone https://github.com/marcus0x62/tinycomments
Cloning into 'tinycomments'...
remote: Enumerating objects: 73, done.
remote: Counting objects: 100% (73/73), done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 73 (delta 22), reused 64 (delta 16), pack-reused 0
Receiving objects: 100% (73/73), 41.29 KiB | 1.01 MiB/s, done.
Resolving deltas: 100% (22/22), done.
marcusb@dom:~/tmp$ cd tinycomments/server
marcusb@dom:server$ cargo build --release
Compiling libc v0.2.152
[ output elided ]...
Compiling tinycomments v0.1.0 (/home/marcusb/tmp/tinycomments/server)
Finished release [optimized] target(s) in 13.56s
marcusb@dom:server$
After you compile the binary:
- copy the resulting file to to /usr/local/bin/tinycomments
- Add the tinycomments user
- Create the tinycomments database
- If running Linux with Systemd, install the systemd service and start the service
- Verify the service is running.
- Configure your webserver to proxy requests to the Tinycomments engine
Add the Tinycomments theme to your hugo site:
- As a module – instructions here
- in your themes directory
If you set the proxy path to something other than /tinycomments/, set the tinycommentsPath parameter in your Hugo site config
Set comments: true in the front matter for any post where you want to enable comments. If you want to disable future comments on a post, you can set commentsLocked: true in the front matter; existing comments will be displayed.
Proof of Work System
Rather than force users to register, which is probably too much friction for comments on a low-volume blog, Tinycomments uses an escalating proof-of-work system that will challenge clients that make requests faster than a threshold (by default, six requests within a 30 second window) with a puzzle to solve. This puzzle is a secret number that has been signed with a randomly-generated HMAC SHA-256 key. The challenge hash and key are provided to the client, but the secret number must be brute-forced. Further requests made within the window will result in the secret being selected from an ever-larger keyspace.
The default threshold is set such that a legitimate client is unlikely to ever receive a challenge.
This system is asymmetric in that the client must expend significant processor (CPU or GPU) resource to solve a puzzle, but the server has to expend only minimal resources to generate or verify a puzzle. HMAC SHA-256 is simple to implement, but the search process is easily parallelizable, and as such, there are better solutions for this problem.
TODO
- Moderation UI
License
Tinycomments is released under the MIT License