The startsite script

The script is used during Setting up a Lino production server to setup a new Lino production site on a server.

The script is meant as template for a script to be adapted to your system.


$ wget
$ nano

Edit the config section of the file to adapt it to your system-wide server preferences.

$ sudo chmod a+x $ sudo mv /usr/local/bin

The remaining sections of this page just describe what the script does. You don't need to read them unless something goes wrong.

Create a project directory

First create the main prod_sites folder:

$ sudo mkdir -p /usr/local/src/lino/prod_sites/
$ cd /usr/local/src/lino/prod_sites/

Create the project folder for your first site, in this example we shall use prj1:

$ mkdir prj1
$ cd prj1

Set up a Python environment

Create a new Python environment in your project directory:

$ sudo apt install virtualenv
$ virtualenv --python=python2 env

Activate this environment by typing:

$ . env/bin/activate

Afterwards update the new environment's pip and setuptools to the latest version:

$ pip install -U pip
$ pip install -U setuptools

Get the sources

Create a directory repositories to hold your working copies of version-controlled software projects and then clone these projects.

$ go prj1 $ mkdir repositories $ cd repositories $ git clone $ git clone $ git clone

Replace MYAPP by the name of the Lino application you want to install.

The lino repository contains general Lino core code. The xl repository contains the Lino extension library used by most Lino applications.

Now you are ready to "install" Lino, i.e. to tell your Python environment where the source file are, so that you can import them from within any Python program:

$ pip install -e lino
$ pip install -e xl
$ pip install -e MYAPP

More Debian packages

Some Debian packages and why you might need them:

$ sudo apt install apache2 libapache2-mod-wsgi

This will automatically install Apache (packages apache2 apache2-doc apache2-mpm-prefork libexpat1...)

If MySQL is your database backend:

$ sudo apt install mysql-server
$ sudo apt install libmysqlclient-dev
$ sudo apt install python-dev
$ sudo apt install libffi-dev libssl-dev

Install the mysql client into your project's virtualenv:

$ pip install mysqlclient

If you prefer PostgreSQL:

$ sudo apt install postgresql

Install the PostgreSQL client into your project's virtualenv:

$ pip install psycopg2

For more info on how to setup a user and database see MySQL cheat sheet and Use a PostgreSQL database.

Configuring site-wide default settings

Lino applications (unlike Django projects) have a hook for specifying site-wide default values for their Django settings.

As root, in your /usr/local/src/lino the directory create a empty file:

$ sudo touch /usr/local/src/lino/

In that directory, create our file that contains the site-wide configuration:

$ sudo nano /usr/local/src/lino/

Paste the following content into that file:

# -*- coding: UTF-8 -*-
# replace '' by your domain name
# change the value of SECRET_KEY

import site
import os, sys
from os.path import split, dirname, join, realpath, exists

def manage(filename, *args, **kw):
    # Called from files
    setup(dirname(filename), *args, **kw)
    from import execute_from_command_line

def wsgi(globals_dict, *args, **kw):
    # Called from files
    homedir = dirname(globals_dict['__file__'])
    sp = realpath(join(homedir, 'env/lib/python2.7/site-packages'))
    assert exists(sp)
    setup(homedir, *args, **kw)
    from django.core.wsgi import get_wsgi_application

def setup(homedir, settings_module=None):
    if settings_module is None:
        # If homedir is '/path/to/mysites/prj1/', set settings_module
        # to 'mysites.prj1.settings':
        parts = split(homedir)
        prj = parts[-1]
        prefix = split(parts[-2])[-1] + '.'
        settings_module = prefix + prj + '.settings'
    os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
    os.environ['LINO_SITE_MODULE'] = 'lino_local'

def setup_site(self):
    # Site-wide default Django settings.
    # Called when the Site object has been initialized. The Django
    # settings module cannot yet be imported but we can write to its
    # global namespace.
    self.csv_params = dict(delimiter=',', encoding='utf-16')
    self.build_js_cache_on_startup = False

        EMAIL_SUBJECT_PREFIX='['+self.project_name+'] ',
        ADMINS=[["John Doe", ""]],

Adapt that content to your site.

This will be your file.

More about this in Site-wide default settings.

Project directories

Every new project directory must have at least four files:

  • an empty file making it able for apache to import your settings:

    $ touch /usr/local/src/lino/prod_sites/prj1/
  • a file Note: Replace the 'prj1' in this file with the name of the project:

    # -*- coding: UTF-8 -*-
    from lino.projects.std.settings import *
    import logging
    logging.getLogger('weasyprint').setLevel("ERROR") # see #1462
    class Site(Site):
        title = "Lino@prj1"
        # server_url = ""
    SITE = Site(globals())
    # locally override attributes of individual plugins
    # SITE.plugins.finan.suggest_future_vouchers = True
    # MySQL
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'mysite', #database name
            'USER': 'django',
            'PASSWORD': 'my cool password',
            'HOST': 'localhost',                  
            'PORT': 3306,
            'OPTIONS': {
               "init_command": "SET storage_engine=MyISAM",
  • a file

    #!/usr/bin/env python
    if __name__ == "__main__":
        import sys ; sys.path.append('/usr/local/src/lino')
        from lino_local import manage ; manage(__file__, 'settings')
  • a file Note: Replace the 'prj1' in this file with the name of the project:

    import sys ; sys.path.append('/usr/local/src/lino')
    from lino_local import wsgi ; wsgi(globals(), 'lino_sites.prj1.settings')

We recommend the convention of having in each project a symbolic link named env which points to the virtualenv.

Which database backend to use

Our example assumes you are using Django's MySQL backend. For other backends, adapt your DATABASES accordingly.

The database backend of your choice is not automatically installed. If you plan to use Django's MySQL backend, see MySQL cheat sheet.

Follow the Django documentation at Get your database running

Activate file logging

See About logging.

Setting up Apache2

The following is an example of a apache config for our prj1 site.

This example is setup for a single Lino site, if you plan to host more than one Lino site we advise you to move your static files to /usr/local/src/lino/static/ and to update the config accordingly.

<VirtualHost *:80>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/access.log combined

  WSGIScriptAlias / /usr/local/src/lino/prod_sites/prj1/
  WSGIDaemonProcess lino threads=15 python-path=/usr/local/src/lino/prod_sites/prj1/env/local/lib/python2.7/site-packages
  WSGIProcessGroup lino

  <Location />
  Require all granted

  Alias /media/ /usr/local/src/lino/prod_sites/prj1/media/

  <Location /media/>
     SetHandler none

  Alias /static/ /usr/local/src/lino/prod_sites/prj1/static/

  <Location /static/>
     SetHandler none

#RewriteEngine on
#RewriteCond %{SERVER_NAME}
#RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]


Do the following in order to activate the site with Apache:

$ sudo nano /etc/apache2/sites-available/prj1.conf
$ sudo a2ensite prj1.conf
$ sudo a2dissite 000-default
$ sudo a2enmod wsgi
$ sudo service apache2 restart

Apache also needs write access to the media folder of each site.:

$ sudo chown www-data /usr/local/src/lino/prod_sites/prj1/media/

Now you should be able to navigate to your domain and see a barebones lino-app.

Install TinyMCE language packs

(Needs revision)

If you plan to use Lino in other languages than English, you must manually install language packs for TinyMCE from

Simplified instructions for a language pack containing my personal selection (de, fr, nl and et):

# cd /usr/share/tinymce/www
# wget
# unzip