3.4. LinOTP Server Installation – the tar.gz, virtualenv and pip way

LinOTP can also run on many other distributions using the virtualenv for python. “virtualenv is a tool to create isolated python environments.” [1] This setup was run successfully on RedHat Enterprise Linux 6.2, 6.3 and CentOS 6. But due to the isolated environment it could run an many other distributions.

First you need to create a directory where the whole LinOTP installation will be located. We choose /opt/LINOTP. You might need to download the virtualenv tool here [2]

If you activated the EPEL repository [3] you may simply install the package:

yum install python-virtualenv

Create the virtualenv:

mkdir -p /opt/LINOTP
virtualenv --no-site-packages /opt/LINOTP

This will create an environment that does not use any python packages of your base linux installation.

Now enter this virtual environment:

cd /opt/LINOTP
source bin/activate


You should update your pip before you proceed:

pip install --upgrade pip pip-tools

In fact this virtual environment is just a rewriting of several environment variables. You can leave this virtual environment any time by issuing the command deactivate. To be able to install all packages to this virtual environment you first need to install the following packages in your distribution using the required tool like apt-get, yum or yast...

  • python-dev or python-devel
  • swig
  • gcc
  • libssl-dev or openssl-devel
  • openldap-dev, libldap2-dev or openldap-devel
  • mysql-server and libmysqlclient-dev or mysql-devel if you want to use mysql as token database
  • On Ubuntu 13.10 (possibly other OS’s) you need to install libsasl2-dev as well

Depending on your distribution the names may vary.

Now we are going to install all LinOTP stuff:

pip install linotp

...will install the LinOTP base packages with the base useridresolver from the python package index pypi.python.org. This public package index holds the same packages online as you might download from the KeyIdentity customer portal. If you prefer to install a manually downloaded linotp package you may as well issue a command pip install linotp-<current-version>.tar.gz.

If you want to enroll tokens via QR Code like the Google Authenticator you need to either install:

pip install pil

Or on newer distributions you should install:

pip install pillow
pip install pillow-pil

pillow-pil may fail to install since as of April 2014 there only is an unstable version available. If you want to install it anyway use the --pre option for pip.

If you want to use the Audit module, you need to install:

pip install m2crypto

On some distributions (known with Ubuntu) m2crypto may fail to install. Then you can install python-m2crypto in your distribution and copy the corresponding files to /opt/LINOTP/lib/python2.7/site-packages.

To configure and activate the audit trail see Audit Trail Configuration.

Depending on where you want to store your token database you need to install database packages:

pip install pysqlite
pip install psycopg2
pip install MySQL-python

If you want to use SMS-Tokens you need to install the SMSProvider package:

pip install SMSProvider

You should update your pip environment with the help of the script linotp-pip-update:


At this very moment you got a full working LinOTP. To check which packages are installed in your virtual environment you can issue the command:

pip freeze


In this example we assume that you copy all config files to /etc/linotp2/. You could also use the directory /opt/LINOTP/etc/linotp2 where some example files already exist. On some systems you may find the files under /usr/etc/linotp2/.


The pip installation does not update itself automatically. LinOTP comes with a helper script linotp-pip-update which you can run to update your virtualenv. Of course you first need to enter the virtualenv before you can run the script.

3.4.1. Setup token database

You need to create the database, where the token information will be stored. This database can also be on a remote database server.

If you e.g. want to use mysql you could do it like this:

mysql -u root -p mysql
create database L2demo;
grant all privileges on L2demo.* to 'linotp'@'localhost' identified by 'mySecret';
flush privileges;


The linotp package came with a config file /etc/linotp2/linotp.ini.example. You need to copy this file to your preferred location like /etc/linotp2/linotp.ini.

Change the following line accordingly:

sqlalchemy.url = mysql://linotp:mySecret@localhost/L2demo

You probably got no encryption key yet. So generate a new encryption key:

dd if=/dev/urandom of=/etc/linotp2/encKey bs=1 count=96


You can use the tool linotp-create-enckey -f <linotp.ini file> to create the encryption key.

Create the LinOTP log directory:

mkdir /var/log/linotp

Now you can create the database tables:

paster setup-app /etc/linotp2/linotp.ini

Check the ownership of the files

  • /etc/linotp2/encKey (only readable for owner)
  • /etc/linotp2/token.db (if used)
  • /var/log/linotp/ and /var/log/linotp/linotp.log.

These files should be owned by the service account linotp.


You can fix ownership and access rights using the tool linotp-fix-access-rights -f <linotp.ini file> -u <linotp user>.

You can test this setup easily as described in Testing LinOTP Server installation.

3.4.2. LinOTP and the Apache webserver

More information about setting up LinOTP with Apache2 can be found in section Apache2.

The configuration depends on the distribution you are using. Debian based distributions split up the configuration in many different files for each site while RedHat based distributions use one big httpd.conf file.

With Apache we want to use authentication to the management web UI. For starters we choose to do digest authentication and create a file accordingly:

htdigest /etc/linotp2/admins "LinOTP2 admin area" admin

The following modules need to be installed and activated:

  • mod_wsgi
  • mod_ssl


On systems using SELinux like RedHat 6 you need to deactivate SELinux to get LinOTP up and running. You may activate and reconfigure SELinux later on. In /etc/sysconfig/selinux set permissive and reboot the machine.

On RedHat 6 based systems you need to create a directory, otherwise the WSGI module will fail with Service Temporarily Unavailable:

mkdir /var/run/wsgi

Now we can configure the apache server. This example configuration applies to Apache version 2.2. Please refer to the official documentation of Apache for differences between Apache version 2.2 and 2.4:


Things get easier, when we create an authentication file /etc/[httpd|apache2]/linotp-auth.conf, that can be included when need:

AuthType Digest
AuthName "LinOTP2 admin area"
AuthDigestProvider file
AuthUserFile /etc/linotp2/admins
Require valid-user

The configuration for your LinOTP site whether you configure it in httpd.conf directly or in an sites-enabled directory should contain the following. You might need to adapt directory names:

Listen 443
WSGIPythonHome /opt/LINOTP
WSGISocketPrefix /var/run/wsgi
<VirtualHost _default_:443>
   ServerAdmin webmaster@localhost
   DocumentRoot /var/www
   <Directory />
      Options FollowSymLinks
      AllowOverride None
   <Directory /var/www/>
      Options Indexes FollowSymLinks MultiViews
      AllowOverride None
      Order allow,deny
      allow from all

   WSGIScriptAlias /       /etc/linotp2/linotpapp.wsgi
   # The daemon is running as user 'linotp'
   # This user should have access to the encKey database encryption file
   WSGIDaemonProcess linotp processes=1 threads=15 display-name=%{GROUP} user=linotp
   WSGIProcessGroup linotp
   WSGIPassAuthorization On

   <Location /admin>
      Include /etc/httpd/linotp-auth.conf
   <Location /audit>
      Include /etc/httpd/linotp-auth.conf
   <Location /gettoken>
      AuthType Digest
      AuthName "LinOTP2 gettoken"
      AuthDigestProvider file
      AuthUserFile /etc/linotp2/gettoken-api
      Require valid-user
   <Location /manage>
             Include /etc/httpd/linotp-auth.conf
   <Location /selfservice>
      # The authentication for selfservice is done from within the application
   <Location /system>
     Include /etc/httpd/linotp-auth.conf
   <Location /license>
     Include /etc/httpd/linotp-auth.conf
   <Location /validate>
      # No Authentication

   ErrorLog /var/log/httpd/error.log
   LogLevel warn

   # Do not use %q! This will reveal all parameters, including setting PINs and Keys!
   # Using SSL_CLIENT_S_DN_CN will show you, which administrator did what task
   LogFormat "%h %l %u %t %>s \"%m %U %H\"  %b \"%{Referer}i\" \"%{User-agent}i\" " LinOTP2
   CustomLog /var/log/httpd/ssl_access.log LinOTP2

   #   SSL Engine Switch:
   #   Enable/Disable SSL for this virtual host.
   SSLEngine on

   #   If both key and certificate are stored in the same file, only the
   #   SSLCertificateFile directive is needed.
   SSLCertificateFile    /etc/ssl/certs/linotpserver.pem
   SSLCertificateKeyFile /etc/ssl/private/linotpserver.key
   <FilesMatch "\.(cgi|shtml|phtml|php)$">
      SSLOptions +StdEnvVars
   <Directory /usr/lib/cgi-bin>
      SSLOptions +StdEnvVars
   BrowserMatch ".*MSIE.*" \
     nokeepalive ssl-unclean-shutdown \
     downgrade-1.0 force-response-1.0

   ErrorDocument 500 "<h1>Internal Server Error</h1> Possible reasons can be missing modules or bad access rights \
                     on LinOTP configuration files or log files. Please check the apache logfile \
                     <pre>/var/log/httpd/error_log</pre> for more details."



On RHEL and CentOS mod_ssl comes with a file /etc/httpd/conf.d/ssl.conf that already contains a VirtualHost definition. You also can adapts this accordingly.


The example uses the SSL certificate linotpserver.pem. If you do not have a certificate authority that provides you the certificate, you might create a self signed test certificate as described in Creating self signed SSL certificate.

The WSGI daemon process will run as the user linotp. So you should have a system account or otherwise create it:

useradd -r linotp -d /opt/LINOTP

Copy the linotpapp.wsgi file from the local etc directory in your virtualenv to /etc/linotp2 or adapt the WSGIScriptAlias in the apache configuration accordingly.

Check the permissions of the files

  • /etc/linotp2/linotp.ini - linotp should have read access
  • /etc/linotp2/encKey - linotp should have read access
  • /etc/linotp2/data/ - This is a template directory, linotp should have write access
  • /var/log/linotp/ - linotp should have write access


You can add the user linotp and fix the access rights using the tool linotp-fix-access-rights -f <linotp.ini file> -u linotp.

You should now be able to restart the apache and login to the management web UI via https://<yourserver>/manage.

3.4.3. Further changes for RedHat and CentOS 6

You might want to adapt your firewall configuration in /etc/sysconfig/iptables to allow port 443 to be accessed.

Moreover you should verify, that your services httpd and mysqld (if you are using MySQL) are running after a reboot:

chkconfig mysqld on
chkconfig httpd on

3.4.4. Testing LinOTP Server installation

You are now ready to go. You might now want to start LinOTP temporarily from the command line:

paster serve /etc/linotp2/linotp.ini

LinOTP will now listen on the port you configured in the linotp.ini file.

If you configured Apache2 to serve LinOTP you just need to assure, that the apache server is started. Point your browser to http://<yourserverIP>:5001/manage and you will get the Management Interface.


In the case of using paster serve, there is no authentication and encryption while talking to the LinOTP server. You should use this only for testing purposes! Please read the section LinOTP and the Apache webserver and Apache2 on how to setup encryption and authentication.

3.4.5. Creating self signed SSL certificate

For testing purposes you can create a self signed certificate like this:

openssl req -new -x509 -key /etc/ssl/private/linotpserver.key \
        -out /etc/ssl/certs/linotpserver.pem -days 365

You should adapt the access rights of the private key!