If you just want to create a wiki online, please see the included README
file instead of this INSTALL file. This file contains details about
installing Luminotes Desktop and Luminotes Server, which you shouldn't
need if you only want to make a wiki.


Luminotes Desktop
=================

Luminotes Desktop allows an individual to take notes on their own
computer without an internet connection.

First, install the prerequisites:

 * Python 2.4 to 2.5
 * CherryPy 2.2
 * pysqlite 2.3 to 2.4
 * simplejson 1.3 to 2.0
 * pytz 2006p to 2008c
 * Python Imaging Library 1.1
 * Python Universal Encoding Detector 1.0

In Debian GNU/Linux or Ubuntu, you can issue the following command to install
these packages:

  apt-get install python python-cherrypy python-pysqlite2 \
          python-simplejson python-tz python-imaging python-chardet


database setup
--------------

Initialize the database with the starting schema and default data. You should
run this command from the base Luminotes directory:

  export PYTHONPATH=.
  python tools/initdb.py -l


running Luminotes Desktop
-------------------------

To start Luminotes, run:

  python luminotes.py -l

This will run the local Luminotes web server and automatically launch a web
browser so you can use Luminotes. You don't need to create an account or
login. Just start creating a wiki.

If Luminotes is already running when you invoke that command, it will just
open a new web browser window to connect to the existing Luminotes
server on the correct port.

In case you're curious, your notes and attached files are stored in the
~/.luminotes directory.

If you'd like to run Luminotes from a USB drive, first install Luminotes
Desktop normally. Once it's installed, instead of running Luminotes, manually
copy the entire Luminotes directory to a USB drive. Then, run
tools/usb_luminotes.sh from the USB drive. Your Luminotes data, including all
of your notes and notebooks, will be stored on the USB drive instead of on the
computer itself. Then, anytime you want to start Luminotes on the USB drive,
run usb_luminotes.sh from it.

If you're only interested in Luminotes Desktop, you can stop reading here. The
rest of this document describes Luminotes Server.


Luminotes Server
================

Luminotes Server allows a team to set up their own Luminotes web server, just
like at luminotes.com.

First, install the prerequisites:

 * Python 2.4 to 2.5
 * CherryPy 2.2
 * PostgreSQL 8.1
 * psycopg 2.0
 * simplejson 1.3
 * pytz 2006p to 2008c
 * Python Imaging Library 1.1
 * Python Universal Encoding Detector 1.0

In Debian GNU/Linux or Ubuntu, you can issue the following command to install
these packages:

  apt-get install python python-cherrypy postgresql-8.1 \
          postgresql-contrib-8.1 python-psycopg2 python-simplejson \
          python-tz python-imaging python-chardet


database setup
--------------

Configure PostgreSQL's pg_hba.conf (usually found under /etc/postgresql/) to
require passwords for local connections:

  local all all md5

Restart postgresql so these changes take effect:

  /etc/init.d/postgresql restart

As the PostgreSQL superuser (usually "postgres"), create a new database user
and set a new password, for instance, "mypassword".

  createuser -S -d -R -P -E luminotes
  createdb -E UTF8 -O luminotes luminotes

Also as the PostgreSQL superuser, setup full-text searching. The path to the
tsearch2.sql file may be different depending on your Linux distribution or
PostgreSQL version, and is usually found within a PostgreSQL "contrib"
package:

  psql luminotes < /usr/share/postgresql/8.1/contrib/tsearch2.sql
  echo "grant all on pg_ts_cfg to luminotes;" | psql luminotes
  echo "grant all on pg_ts_cfgmap to luminotes;" | psql luminotes
  echo "grant all on pg_ts_dict to luminotes;" | psql luminotes
  echo "grant all on pg_ts_parser to luminotes;" | psql luminotes
  echo "update pg_ts_cfg set locale = 'en_US.UTF-8' where ts_name = 'default';" | psql luminotes
  echo "create language plpgsql;" | psql luminotes

Note that you can use a different UTF-8 locale if you prefer. For instance, in
the command above, you can use 'en_GB.UTF-8' instead of 'en_US.UTF-8'.

Initialize the database with the starting schema and default data. You should
run this command from the base Luminotes directory:

  export PYTHONPATH=.
  export PGPASSWORD=mypassword
  python tools/initdb.py


development mode
----------------

Running the Luminotes server in development mode is convenient for testing out
changes, because it uses CherryPy's built-in web server with auto-reload
enabled, so the server will automatically reload any modified source files as
soon as they're modified.

To start the server in development mode, run:

  python luminotes.py -d

Connect to the following URL in a web browser running on the same machine:

  http://localhost:8081/


production mode setup
---------------------

Production mode is intended for a live production web site, so you can skip
this section entirely if you don't care about running such a site. Production
mode doesn't support auto-reload, and logging goes to file (luminotes.log)
instead of the console, but performance should be better than in development
mode.

First you'll need to configure your web server to forward requests for pages
to Luminotes. Example configuration files are included for both Apache and
nginx, but in theory, Luminotes should work with just about any web server.

For Apache, enable mod_rewrite and mod_proxy, and then configure a VirtualHost
as per the example configuration file in examples/apache_luminotes.

For nginx, if you want a working upload progress bar, build and install a
version of nginx with the NginxHttpUploadProgressModule enabled. See:
http://github.com/masterzen/nginx-upload-progress-module/ for more
information. Then, configure nginx as per the example configuration file in
examples/nginx_luminotes.

Also for nginx, you should edit config/Common.py and set the
luminotes.web_server value to "nginx" so that Luminotes makes use of nginx's
X-Accel-Redirect header. For instance:

  "luminotes.web_server": "nginx",

For either web server, you should change the paths in your configuration file
to point to wherever Luminotes happens to be installed. The example
configuration causes your web server to serve static files itself, while
passing through requests for dynamic pages to the Luminotes web server running
locally.

Additionally, you should let Luminotes know about the public hostname of
your web site. Simply edit config/Common.py and change the value of
luminotes.http_url based on the domain you're using. For instance:

  "luminotes.http_url": "http://yourhostname.com",

SSL support
-----------

If you want to use SSL, procure and install an SSL cert for use with your web
server. Duplicate the standard non-SSL web server configuration for a separate
SSL-enabled VirtualHost or server section, but change the IP address from
127.0.0.1 to 127.0.0.2 for SSL. This hack allows the Luminotes server to
distinguish between SSL and non-SSL requests by looking at the proxy IP.
Without this, Luminotes would have no way of knowing whether a particular
request was encrypted when received by your web server. (There are ways to do
this in a less hacky manner, which might be supported in the future.)

To configure the Luminotes server for SSL support, edit config/Common.py
and change the value of luminotes.https_url based on the domain you're
using. For instance:

  "luminotes.https_url": "https://yourhostname.com",


starting production mode
------------------------

Then to actually start the production mode server, run:

  python luminotes.py

You should be able to connect to the site at whatever domain you've configured
Apache or nginx to serve.

Optionally, you can copy examples/luminotes_debian_initscript to
/etc/init.d/luminotes and use the following command to start the Luminotes
server instead:

  /etc/init.d/luminotes start


sending email
-------------

If you would like Luminotes to be able to send password reset emails, then
you'll need a mail server running on the same machine that is capabable of
receiving local SMTP connections and sending email. Either way, please set
the luminotes.support_email address in config/Common.py to the email address
you'd like in the From field of all outgoing emails. This email address also
shows up in various error messages and other places for a support contact
address.


user rate plans
---------------

By default, all Luminotes users start at rate plan 0. This corresponds to the
Luminotes "free" account level described at http://luminotes.com/pricing

If you'd like to change the details of any of the rate plans, edit
config/Common.py and change the first listed plan under luminotes.rate_plans.
For instance, if you'd like users at rate plan 0 to be allowed to invite other
users to edit their notebooks, change the "notebook_collaboration" value to
"True". If you like, you can also increase the amount of storage they're
allowed.


memcached
---------

For improved performance, it is recommended that you install and use memcached
for production servers.

First, install the prerequisites:

 * python-dev 2.4 or 2.5
 * libmemcache-dev 1.4
 * memcached 1.4
 * cmemcache 0.95

In Debian GNU/Linux or Ubuntu, you can issue the following command to install
these packages:

  apt-get install python-dev libmemcache-dev memcached

The cmemcache package is not currently included with Debian or Ubuntu, so
you'll have to build and install it manually. Download and untar the package
from:

  http://gijsbert.org/cmemcache/

From the untarred cmemcache directory, issue the following command as root:

  python setup.py install

This should build and install the cmemcache module. Once installed, Luminotes
will use the module automatically. When Luminotes starts up, you should see a
"using memcached" message.


Python unit tests
-----------------

If you're interested in running unit tests, install:

 * nose 0.9.0

In Debian GNU/Linux or Ubuntu, you can issue the following command to install
this packages:

  apt-get install python-nose

Then you can run unit tests by running:

  nosetests


search performance
------------------

If you have many notes in your database and/or many users, you may find that
wiki searching is too slow. If that's the case, you can try modifying the way
that notes are indexed for searching in the database.

These changes are completely optional and fairly technical, and you can safely
ignore them for the majority of Luminotes Server installations.

First, download an English ispell dictionary from this site:

  http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/

Untar the tarball and put the two english.* files into a convenient location
such as /usr/local/lib/ispell

Then, at a psql prompt for the luminotes database, run the following SQL
command to tell PostgreSQL's tsearch2 module about the new dictionary files:

  insert into pg_ts_dict (
    select
      'en_ispell',
      dict_init,
      'DictFile="/usr/local/lib/ispell/english.dict",'
      'AffFile="/usr/local/lib/ispell/english.aff",'
      'StopFile="/usr/share/postgresql/8.1/contrib/english.stop"',
      dict_lexize
    from pg_ts_dict
    where dict_name = 'ispell_template'
  );

You may have to change the paths if you put the english.* files in a different
location, or if your PostgreSQL installation has the english.stop file in a
different location.

Next, run the following commands at the psql prompt to make PostgreSQL use the
new dictionary for searches by default:

  update
    pg_ts_cfgmap set dict_name = null where ts_name = 'default' and
    dict_name = '{simple}';

  update
    pg_ts_cfgmap set dict_name = '{en_ispell,en_stem}'
  where
    dict_name = '{en_stem}' and ts_name = 'default';

The second command should update about three rows.

To test whether the new dictionary is working, run the following command:

  select lexize('en_ispell', 'program');

You should see a result like the following: 

    lexize
  -----------
   {program}
  (1 row)

If you don't see "{program}" in the result, PostgreSQL may not be finding your
english.* dictionary files, so check the paths and try again.

Lastly, regenerate the database indices used for searching. This may take a
while:

  drop trigger search_update on note_current;
  drop index note_current_search_index;
  update
    note_current set search = to_tsvector('default',
    coalesce(title,'') ||' '|| coalesce(contents,'') );
  vacuum full analyze;
  create index note_current_search_index on note_current USING gist (search);
  vacuum full analyze;
  create trigger search_update
    before insert or update on note_current
    for each row
    execute procedure tsearch2('search', 'drop_html_tags', 'title',
    'contents');

For a much more thorough treatment of using custom dictionaries with tsearch2,
read the "Tsearch V2 Introduction" on the aforementioned web page.
