tekuti

Tekuti means “I’m telling you” in Oshiwambo. It is weblog software written in Scheme, using Git as its persistent store.

Why

Tekuti hacks the web as it is meant to be hacked.

Tekuti uses tags, not categories. Put however many labels you like on your posts, the more the merrier: with each tag you add meaning to your tag cloud, related posts, and related tags.

Tekuti uses Git as its backing store. The data model scales, and you get hot backups and rollback for free.

All operations on the data store are revertable. Try it: make a post, add some comments, revert some comments, revert the reversions...

Tekuti is secure. There is one entry point, and the entirety of the program is written in the functional style. It does not perform any destructive modifications to data. It is very easy to audit its code.

Tekuti respects the meaning of the web’s GET and POST operators. Clicking on a link will not modify the data store.

There is a strict separation in types between XML and strings. You won’t see malformed XHTML come out of Tekuti, much less an XSS vulnerability.

Output transformation and templating is easy and built-in to the language via the powerful pre-post-order operator.

And, most importantly, it’s written in Scheme, so it’s fun to hack!

How

Installing prerequisites

  1. Build and install Guile 2.2 or newer.

  2. Install git. Any modern git will work.

Get and build tekuti

git clone https://github.com/wingo/tekuti
cd tekuti; autoreconf -vif; ./configure && make

Run it!

./env src/tekuti

Now navigate to http://localhost:8080/ in your browser. Does it work? Sweet!

To add posts, visit the admin interface at e.g. http://localhost/blog/admin. The default user is admin and the password is admin.

Serving tekuti behind nginx

Add this to your server { ... } block:

location = / { proxy_pass http://127.0.0.1:8080/; }
location /admin { proxy_pass http://127.0.0.1:8080/admin; }
location /archives { proxy_pass http://127.0.0.1:8080/archives; }
location /feed { proxy_pass http://127.0.0.1:8080/feed; }
location /search { proxy_pass http://127.0.0.1:8080/search; }
location /tags { proxy_pass http://127.0.0.1:8080/tags; }
location /debug { proxy_pass http://127.0.0.1:8080/debug; }

Then restart your nginx and you should be good to go.

Hacking tekuti

Run Tekuti with the --listen option. Then telnet to port 37146 on localhost, and voila, a REPL!

For me, the best way to hack in the repl is to enter “inside” other modules. For example, to change the admin password, I would:

 ;; enter in the already-defined (tekuti config) module
 (define-module (tekuti config))
 ;; replace the *admin-pass* definition
 (define *admin-pass* "foo")

Of course the best way is to do all this from within Emacs. Just install Geiser, then M-x geiser-connect to the running REPL. Open tekuti/config.scm in Emacs, change the admin password, and press C-x C-e after the closing parenthesis. Then go to your admin page and see if the password changed. Nifty, eh?

Deploying

For deployment-specific variables like the CSS files and the paths and such, you can run tekuti with the -c argument and pass it a config file, which will be evaluated inside the (tekuti config) module. For example, one of mine looks like this:

;; -*- scheme -*-
(use-modules (ice-9 textual-ports))
(set! *navbar-links*
      '(("about" . "/about/")
        ("archives" . "/archives/")
        ("projects" . "/projects/")
        ("talks" . "/talks/")))
(set! *inline-css*
      (call-with-input-file "/home/wingo/www/site.css" get-string-all))

I suggest taking the CSS file from my blog and customizing it for your usage. Please make it look different. If you come up with something that I should include as a default, I’d be interested in seeing it.

I deploy tekuti in a screen session. Run screen, then run tekuti. Then press C-a d to detach from the session. Then when you come back to your server you run screen -r to jump back into that tekuti session.

Feedback

Send me an email at wingo at pobox.com.