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.
2 Comments