Skip to content

Setting up TiddlyWeb (TiddlyWiki)

I’ve been a fan of TiddlyWiki for a long time now. It’s an HTML file that contains self-editing powers. You download this file, load it in your web browser, and it presents a note-taking application where the notes are stored within that same HTML file (very portable).

I really like this functionality, but I’d like to have it stored somewhere central (a web server for example), so that I don’t have to worry about syncing this file. From looking around, it seemed like TiddlyWeb was a good (albeit possibly over-kill) solution. It works as a server-side TiddlyWiki implementation, but it’s more general: it presents an API that can manage general blobs of information (tiddlers). I got this set up.

I pretty much followed Ben Gillies’ instructions. Here’s a short run-down of what I did:

Boot-strap virtualenv

This is a cool facility in python where you can set up a customized python installation. To do so, you download this virtualenv.py script from http://pypi.python.org/pypi/virtualenv, and then create a directory for your new custom (local) python installation in ~/virtualenv/tiddlyweb:

python2.6 virtualenv.py ~/virtualenv/tiddlyweb
cd ~/virtualenv/tiddlyweb/
source bin/activate

Install

Basically, you want pip, which you can get through easy_install. From pip, you re-install virtualenv (to be safe) and tiddlyweb:

easy_install -U pip
pip install -U virtualenv
pip install -U tiddlywebwiki

Create an instance

An instance is basically the storage for TiddlyWeb:


twinstance main_inst

At this point, I deviated from Ben Gillies’ instructions. The exception is that I’m running on WebFaction, so did not use the CGI method. Instead, I used the twanager server. I’m avoiding calling this the CherryPy method, because WebFaction has a different definition of what a CherryPy application is: notably, it expects to see a site.py in the application directory.

The way this works is that twanager server listens on a local port for requests. WebFaction is set up to forward requests from a public URL to this local server. The first issue is that the config file contains a host/port specification. This needs to be what you’d see publicly, for example, my.awesomewiki.com:80. So, you’d set the following in tiddlywebconfig.py:

[cce_python]

# A basic configuration.
# Run “pydoc tiddlyweb.config” for details on configuration items.

config = {
‘system_plugins’: [‘tiddlywebwiki’],
‘secret’: ‘5431798403asdf123r84sd6f781234ra4s6df46231087’,
‘twanager_plugins’: [‘tiddlywebwiki’],
‘server_host’: {
‘scheme’: ‘http’, # or https
‘host’: ‘my.awesomewiki.com’, # or an IP number
‘port’: ’80’, # or some other port. You must put port even if 80 or 443. This needs to be a string.
}
}

[/cce_python]

That’s what you want, except how do you now tell the server to listen to a local port, and not an externally available port? Well, you do it on the command line:

twanager server 127.0.0.1 8080

This tells the twanager server to listen to only local connections (loopback interface) and on port 8080. WebFaction (i.e. nginx) is responsible for forwarding external connections to this local port.

I set up a cron script to run the actual server:

[cce_bash]

cat ~/virtualenv/tiddlyweb/bin/start

#!/bin/sh

INST_DIR=”/home/wagh/virtualenv/tiddlyweb/main_inst”
LOCKFILE=”${INST_DIR}/server.lock”
source /home/wagh/virtualenv/tiddlyweb/bin/activate

cd $INST_DIR

if [ -f $LOCKFILE ]; then
exit
fi

touch $LOCKFILE
twanager server 127.0.0.1 8080
rm -f $LOCKFILE
exit

[/cce_bash]

I’m surprised that Linux has no equivalent of the extremely useful BSD command lockf. Seriously, every script needs to implement the functionality of a lock file?

I hate to admit it, but at this point, I had no idea how to see the TiddlyWiki presented by TiddlyWeb. I found the answer at http://tiddlyweb.peermore.com/wiki/#[[TiddlyWeb%20for%20the%20Impatient]]. This was in Ben Gillies’ instructions, too, but you basically enter http://my.awesomewiki.com/recipes/default/tiddlers.wiki.

Anyway, my next major problem was figuring out how to lock it down so that random stumblers could neither view nor edit it. To do so, I had to delve into the policy configuration of my bags and recipes. Basically, a bag has permissions defined in the policy. Same with recipes. To lock things down, you need to set the read (for example) policy to R:USER. The R: prefix designates this as a role in the system. You can assign a role to a user by (for example):

twanager adduser Poojan s3cretp@ssw0rd USER

for new users, or:

twanager addrole Poojan USER

for existing users.

The documentation says that I can set the policy to ”read”: [“ANY”], which allows any authenticated user to read the specified bag/recipe. However, the issue with this is that anyone can use OpenID and log in to become an authenticated user. So, you’ve effectively allowed anyone with a Yahoo/Gmail/LiveJournal account to list and see the contents of your tiddlers.

To edit the policies, I just edited the files within the store directory directly:

cat main_inst/store/bags/system/policy
{“read”: [“R:USER”], “create”: [“R:ADMIN”], “manage”: [“R:ADMIN”], “accept”: [“R:ADMIN”], “write”: [“R:ADMIN”], “owner”: “administrator”, “delete”: [“R:ADMIN”]}

cat bags/common/policy
{“read”: [“R:USER”], “create”: [“R:USER”], “manage”: [“R:ADMIN”], “accept”: [“R:USER”], “write”: [“R:USER”], “owner”: “administrator”, “delete”: [“R:USER”]}

I’m not sure if this was a bad thing to do, but it was easier than running twanager and typing in the entire policy mantra for each policy I wanted.

I’m looking forward to having my notes storage at my fingertips everywhere I go.

Be the first to like.

2 Comments


  1. Fatal error: Uncaught Error: Call to undefined function ereg() in /home/wagh/webapps/techblog/wp-content/themes/plaintxtblog/functions.php:183 Stack trace: #0 /home/wagh/webapps/techblog/wp-content/themes/plaintxtblog/comments.php(33): plaintxtblog_commenter_link() #1 /home/wagh/webapps/techblog/wp-includes/comment-template.php(1510): require('/home/wagh/weba...') #2 /home/wagh/webapps/techblog/wp-content/themes/plaintxtblog/single.php(43): comments_template() #3 /home/wagh/webapps/techblog/wp-includes/template-loader.php(78): include('/home/wagh/weba...') #4 /home/wagh/webapps/techblog/wp-blog-header.php(19): require_once('/home/wagh/weba...') #5 /home/wagh/webapps/techblog/index.php(17): require('/home/wagh/weba...') #6 {main} thrown in /home/wagh/webapps/techblog/wp-content/themes/plaintxtblog/functions.php on line 183