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 Apache, 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 Apache web server

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 Apache 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 Apache 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:


This is the Debian package name. Might be different!

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

This example configuration applies to Apache version 2.4.

The configuration file starts with the VirtualHost definition:

<VirtualHost _default_:443>
   ServerAdmin webmaster@localhost

Security-relevant HTTP headers are set:

Header always edit Set-Cookie ^(.*)$ $1;secure
Header always set X-Frame-Options "DENY"
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=315360000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Permitted-Cross-Domain-Policies "none"

For security, server access rights are denied globally and only given where necessary:

<Directory />
   AllowOverride None
   Require all denied

LinOTP documentation:

<Directory /usr/share/doc/linotpdoc/html>
   Require all granted
Alias /doc/html /usr/share/doc/linotpdoc/html

LinOTP WSGI application link:

<Directory /etc/linotp2>
   <Files linotpapp.wsgi>
      Require all granted
WSGIScriptAlias / /etc/linotp2/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 path to something other than /, because all supported LinOTP clients assume that LinOTP can be reached there.

For efficiency, LinOTP will be run in a separate set of WSGI daemon processes rather than as part of Apache itself:

# 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

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 set up authentication for the different LinOTP interfaces, based on their URL paths:


This interface provides the user interface 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 an Apache web server.

The manage application uses the following data interfaces: /system, /license, /audit, and /admin. It is, by default, configured in a single LocationMatch directive so that all the interfaces belonging together are secured with the same access rights.


This interface is used to configure the LinOTP Server. You should protect this interface either by password authentication provided by Apache 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 upload license files to the LinOTP server, and to retrieve licensing information. It should be protected with authentication similar to that of /admin or /system.


This interface is used to search the audit trail to monitor operations. It should be protected in the same authentication manner like /admin or /system.


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


This interface is used by the linotp-helpdesk web application. It is secured with a different digest auth file than the administrative interfaces. If you change the auth type for this interface, be sure to keep the linotp-helpdesk auth configuration in sync to ensure seamless interaction between the backend and frontend of the helpdesk.


This interface is used to retrieve OTP values. It is secured with a different digest auth file than the administrative interfaces. This means that, by default, no one is allowed to use the interface if no access is explicitly permitted.


This interface is used by end users to manage their own OTP tokens. This interface uses the /userservice interface that provides its own authentication, so there is no special need to protect it within the Apache configuration. As the user authenticates with a username to this interface, /selfservice should only be accessible from your local network.


This interface is used by the selfservice application. 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, /userservice should only be accessible from your local network but must match the same settings as /selfservice.


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 with SSL) and you may also setup authentication to this interface, but it is not that crucial as it is with /admin and /system.

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

The complete default access configuration looks as follows:

<LocationMatch /(manage|system|license|audit|admin)>
   AuthType Digest
   AuthName "LinOTP2 admin area"
   AuthDigestProvider file
   AuthUserFile /etc/linotp2/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 /api/helpdesk>
   AuthType Digest
   AuthName "LinOTP2 helpdesk area"
   AuthDigestProvider file
   AuthUserFile /etc/linotp2/auth_helpdesk
   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 /gettoken>
   AuthType Digest
   AuthName "LinOTP2 gettoken"
   AuthDigestProvider file
   AuthUserFile /etc/linotp2/gettoken-api
   Require valid-user

<LocationMatch /(selfservice|userservice)>
   # The authentication of the selfservice is done from within the application

<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/linotpserver.pem
SSLCertificateKeyFile /etc/ssl/private/linotpserver.key

Lastly, error responses can be defined. By default, we only configure the code 500 document:

   ErrorDocument 500 "<h1>Internal Server Error</h1> …"



The example uses the SSL certificate linotpserver.pem. If you do not have a certificate authority that provides you with a proper certificate, you may create a self signed test certificate as described in Creating self signed SSL certificate. 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 Apache:

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 the Apache web server:

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

If you want to setup the Apache web server to run with TLS, you need to have a CA (certificate authority) certificate, a 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 Apache + 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.