3.6. Configuration background information


This section contains deeper background information about server configuration. If you installed LinOTP via the virtual appliance or Debian packages, you probably do not need to read this.

You only need to read this chapter, if you installed LinOTP manually or want to adapt your LinOTP setup very specifically.

3.6.1. LinOTP Server configuration Token database

The simple SQLite database may be well used for installations up to 100 tokens. This file based sql database can only be accessed locally. Being a simple file, it can be easily backed up but it features no additional access settings. Nevertheless all sensitive data are encrypted with the encKey file. But keep in mind, that this file is located on the same machine like the SQLite database file. You might have a dedicated database department that is running databases like Oracle or MS SQL. Please note, that LinOTP make use of the SQLAlchemy framework. You may find the supported databases here at http://www.sqlalchemy.org/docs/dialects/index.html.

You will then need to change the sqlalchemy.url in your linotp.ini file, which is usually located at /etc/linotp2/linotp.ini.

For Oracle change it to:

sqlalchemy.url = oracle://<user>:<password>@<servername>/<database>

Be assured that you set up the encKey before creating the database tables. The database tables are then created by calling:

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

A more detailed setup description for running LinOTP with Oracle or DB2 can be found at section Database connection. Python search path

The path where your LinOTP components are installed must be contained in your python search path. This will be given, when you installed LinOTP by either of the described ways.

Anyway if the command paster setup-app linotp.ini returns the error message:

pkg_resources.DistributionNotFound: LinOTP

then your python search path needs to be fixed.

Then start a python shell:

# python
Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/local/lib/python2.6/dist-packages/docutils-0.5-py2.6.egg',
 '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk',
 '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload',
 '/usr/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages/PIL',
 '/home/koelbel', '/usr/lib/python2.6/dist-packages/gst-0.10',
 '/usr/lib/pymodules/python2.6', '/usr/lib/python2.6/dist-packages/gtk-2.0',
 '/usr/lib/python2.6/dist-packages/wx383  2.6-gtk2-unicode',

Check the output for your path. If it is not contained, you need to append your directory to the search path.

Press Ctrl-D to exit the python shell.

To append a new path to the Python search path, you need to place a file linotp.pth into an existing directory of the python search path. So create a file e.g. /usr/lib/python2.6/site-packages/linotp.pth with the following content:

/usr/local/lib/python2.6/dist-packages/ RADIUS token communication

Starting with LinOTP 2.4 you can also define RADIUS Tokens, that forward the authentication request to another RADIUS server. This can be another OTP backend or any other RADIUS server. In the file /etc/linotp2/linotp.ini you can define two parameters for this:

radius.dictfile= /etc/linotp2/dictionary
radius.nas_identifier = LinOTP

The radius.dictfile is the file that contains the RADIUS attributes definitions. LinOTP comes with a default one. But you can extend it according to special vendor attributes if necessary. The radius.nas_identifier is the NAS_Identifier that is also send within the RADIUS Auth Request. All other parameters are configured in the RADIUS token itself.

Please see the section Enroll RADIUS Token for further information on this. Paster

To get a quick result easily you may use the python-paste and just start the paster with the following command:

paster serve /etc/linotp2/linotp.ini

You should at least enable ssl_pem in your linotp.ini to have an encrypted communication between the authentication module or the management clients and LinOTP. Nevertheless, this will provide you with no authentication for the management, i.e. everyone having IP access to your LinOTP Server will be able to manage the tokens.


Paster is also used to create the database tables (see Token database) Start script

A Red Hat style start script is contained in the packages:


This will start the paster as user linotp.


In the default configuration the paster would listen on all IP addresses, which means that the LinOTP server would be visible without encryption and authentication!


When running with Apache2, you do not need this start script!

You can start the paster during boot time automatically by issuing the following commands:

chkconfig --add linotp2-paster
chkconfig linotp2-paster on Apache2

To enable encryption and authentication for the LinOTP Server LinOTP can run in a web server. LinOTP will run as WSGI [1] and thus you can use any web server that supports WSGI. This section describes how to setup your Apache2 to serve LinOTP in an encrypted and authenticated manner.

  1. Install apache2,

  2. install libapache2-mod-wsgi [2],

  3. enable mod-wsgi and mod-ssl with your apache:

    a2enmod wsgi
    a2enmod ssl
  4. If you want to authenticate with username/password do a:

    a2enmod auth_digest
  5. With LinOTP an example Apache2 configuration was installed to /usr/share/doc/linotp/examples/apache2-linotp2. You can copy this file to /etc/apache2/sites-available/linotp2.

  6. Activate this configuration by:

    a2ensite linotp2
  7. You may disable any other default site:

[2]This is the Debian package name. Might be different!

In the following section we discuss the Apache2 configuration file, which you might want to adapt to your needs. Apache2 configuration file

This example configuration applies to Apache2 version 2.2. Please refer to the official documentation of Apache2 for differences between Apache2 version 2.2 and 2.4:


The sample configuration file:

<VirtualHost _default_:443>
   ServerAdmin webmaster@localhost
   WSGIScriptAlias /       /usr/local/etc/linotp/linotpapp.wsgi

The WSGIScriptAlias binds the linotpapp.wsgi script to the web server root. You only should change the location of the linotpapp.wsgi script, but you should not change the web server root, since the corresponding web server paths are also included in the LinOTP Management Clients:

# 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

A distinct WSGI daemon process will be started to which the LinOTP wsgi will be delegated. This speeds up responses. Note, that the user=<user> needs to have write access to the log file specified in linotp.ini (default /var/log/linotp/) and read access to the encKey file specified in linotp.ini.

We now can setup the authentication for the different LinOTP interfaces. LinOTP provides the interfaces which reflect in the URL path:


This is used for all token management tasks like enrolling, assigning, deleting tokens. You should protect this interface either by password authentication provided by apache2 or by client certificate authentication. The Management Clients communicate via this interface.


This interface is used to configure the LinOTP Server. You should protect this interface either by password authentication provided by apache2 or by client certificate authentication. The Management Clients (server configuration dialog) communicate via this interface. You can restrict access to this interface for a special user group, so that several users may manage the tokens but only a few users may configure server settings.


This interface is used to authenticate the users. The authentication modules pam_linotp and rlm_linotp2 communicate via this interface. You should encrypt the communication with this interface (running apache ssl) and you may also setup authentication to this interface, but it is not that crucial as the /admin and the /system interfaces.

You might want to restrict the IP addresses that are allowed to contact this interface. This can be achieved by a configuration like:

<Location /validate>
   Order deny,allow
   Deny from all
   Allow from


This interface is used to load licenses to the LinOTP server and to retrieve license information. It should be protected in the same authentication manner like /admin or /system.


This interface is used for the end user to manage his own OTP tokens. This interface provides its own authentication, so there is no special need to protect it within the apache configuration. The user is authenticated against the user database that is defined in the corresponding user ID resolver. As the user authenticates with a username to this interface, /selfservice should only be accessible from your local network.


This interface is used for administrative tasks. All tasks that can be done with the graphical management client – except enrolling eToken NG-OTP – can also be done with this web interface. The authentication to this web interface needs to be setup in the Apache configuration. You may also setup OTP authentication for the management interface. For how to do this see OTP Authentication with Apache2:

<Location /admin>
# We do this, when we do digest auth
# AuthType Digest
# AuthName "LinOTP2 admin area"
# AuthDigestProvider file
# AuthUserFile /usr/local/pylons/etc/admins
# Require valid-user
# Here we do client certificate auth
    SSLVerifyClient require
    SSLVerifyDepth  2
  # Who signed the client certificates
    SSLCACertificateFile /etc/ssl/certs/ca.crt
  # what client certs are allowed to log in?
    SSLRequire ( %{SSL_CLIENT_S_DN_OU} eq "az" and %{SSL_CLIENT_S_DN_CN} in {"linotpadm", "Manfred Mann"} )

<Location /license>
   AuthType Digest
   AuthName "LinOTP2 admin area"
   AuthDigestProvider file
   AuthUserFile /usr/local/pylons/etc/admins
   Require valid-user

<Location /selfservice>
    AuthType Digest
    AuthName "LinOTP2 self service"
    AuthDigestProvider file
    AuthUserFile /usr/local/pylons/etc/selfservice
    Require valid-user

<Location /system>
# We do this, when we do digest auth
#       AuthType Digest
#       AuthName "LinOTP2 admin area"
#       AuthDigestProvider file
#       AuthUserFile /usr/local/pylons/etc/admins
#       Require valid-user
# Here we do client certificate auth
    SSLVerifyClient require
    SSLVerifyDepth  2
    # Who signed the client certificates
    SSLCACertificateFile /etc/ssl/certs/ca.crt
    # what client certs are allowed to log in?
    SSLRequire ( %{SSL_CLIENT_S_DN_OU} eq "az" and %{SSL_CLIENT_S_DN_CN} in {"linotpadm", "Manfred Mann"} )
<Location /validate>
    # No Authentication

The above Location directives demonstrate how to do authentication either with digest authentication or with client certificate authentication. To create a AuthUserFile for digest authentication you should use the command htdigest.

If you are using client certificate authentication you can restrict access for certain client certificates using the SSLRequire directive. For a guideline on how to setup SSL and to issue certificates see section Issuing Certificate Authority:

     ErrorLog /var/log/apache2/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\" \
         \"%{SSL_CLIENT_S_DN_CN}x\""" LinOTP2
     CustomLog /var/log/apache2/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/lse-lap001.pem
     SSLCertificateKeyFile /etc/ssl/private/lse-lap001.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
</VirtualHost> Different authentication schemes for Management Interface

There are several different methods to authenticate to the management interface. All three methods are supported by the WebUI and the command line client.


This can be either basic authentication or digest authentication.


If you want to authenticate against LDAP (see section Authenticating users against LDAP or Active Directory), you need to do basic authentication.

You can activate this by:

a2ensite linotp2

You need to deactivate other schemes by using a2dissite.

RADIUS Authentication

You can use the RADIUS authentication to authenticate with OTP tokens to the LinOTP Management.

Activate this by:

a2ensite linotp2-radius

You need to deactivate other schemes by using a2dissite.

Client Certificates

You can also authenticate to the LinOTP management by using client certificates. Please note, that the LinOTP server then will use the Common Name of the Distinguished Name of the client certificate.

Using the WebUI the client certificate can also be located on a smartcard.

Activate this by:

a2ensite linotp2-certs

You need to deactivate other schemes by using a2dissite. Authenticating users against LDAP or Active Directory

You may also want to authenticate to your LinOTP server with already existing accounts in your LDAP or Active Directory. To accomplish that, you need to configure the corresponding Location directive and do the following steps:

Activate authnz_ldap for Apache2:

a2enmod authnz_ldap

Configure the Location directive. This could be the /admin, /system and /license controller. To do this edit the file /etc/apache2/sites-enabled/linotp2:

 <Location /admin>
        AuthBasicProvider ldap
        AuthType Basic
        AuthName "LinOTP 2 admin area"
        AuthLDAPURL "ldap://,dc=linotp-test,dc=local?sAMAccountName?sub?(objectClass=user)" NONE
        AuthLDAPBindDN "LDAPserviceUser@linotp-test"
        AuthLDAPBindPassword "test123!"
        Require ldap-group cn=linotp_admin_users, ou=linotp, dc=linotp-test, dc=local

In this case all members of the group linotp_admin_users are allowed to manage LinOTP and its tokens. For other possible filters and restrictions see the authnz_ldap documentation at http://httpd.apache.org/docs/2.1/mod/mod_authnz_ldap.html .

To activate the changes restart Apache2:

/etc/init.d/apache2 restart Issuing Certificate Authority

If you want to setup Apache2 to run with SSL you need to have a CA (certificate authority) certificate, a web server certificate and the private key to the web server certificate. If you do not have a CA and a web server certificate available, there is also a sample CA contained in the LinOTPdoc package.

You can find the CA depending on your installation at /usr/share/doc/linotp/examples/CA or /usr/local/share/doc/linotp/examples/CA.

The sample just consists of two files:

  • Makefile
  • openssl.cnf

Either change to this directory or copy the files to a location you like.

Prior to using the CA, you need to have your distribution packages make and openssl installed.



gives you an overview, what you can do with this sample CA. To get started with LinOTP and Apache2 + SSL you need to do the following steps:

  1. Create your new CA:

    make initca

    This will create a subdirectory keys and it will create the CA certificate. The file keys/ca.crt is the CA certificate for the apache directive SSLCACertificateFile.

  2. Create a request for your web server:

    make req ext=server name=<servername>
  3. Sign the request for the web server / issue the certificate for the web server:

    make sign ext=server name=<servername>

    This will create the file keys/<servername>.pem for the apache directive SSLCertificateFile and the file keys/<servername>.key for the apache directive SSLCertificateKeyFile.

  4. Create a request for a admin user if you want to use client certificate authentication:

    make req ext=user name=<adminname>
  5. Sign the request for the admin user / issue the certificate for the admin user:

    make sign ext=user name=<adminname>

6. The files keys/<adminname>.pem and keys/<adminname>.key need to be transferred to the client and configured in the LinOTP Management Client GUI.


The private key files created in this process are passphrase protected. If you need to remove the passphrase use:

openssl rsa -in adminname.key -out adminname-wop.key

which will create a key file adminname-wop.key without a passphrase.


linotpadm.py supports key files with passphrases at the command line. glinotpadm.py does not handle passphrases nicely at the moment. The request for the passphrase will be echoed to the terminal, where you started glinotpadm.py. The passphrase will be requested for every connect to the LinOTP Server, which naturally are a lot. Digest authentication and client certificate authentication can not be used at the same time.