3.3.4. LinOTP Server configuration background#


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.

LinOTP Server configuration#

Token database#

During the installation a database connection is configured by the package linotp. It is assumed that the MariaDB server is installed.

The configuration of the database and its connection is done automatically.

If you want to use an alternative you have to configure the database connection in:

/etc/linotp/linotp.cfg or


The attribute DATABASE_URI is used for configuration.

The DATABASE_URI starts with the driver/module to be selected for the database. This is followed by the user with database access and password, and ends with the database hostname and the database name itself.

If the configuration is adapted accordingly the tool linotp can create the database with tables and give the user the rights.

Our example shows the configuration of a PostgreSQL database for LinOTP.

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 makes 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.cfg file.

For PostgreSQL change it to:

DATABASE_URI = "postgresql://linotpuser:linotppass@localhost/linotp_db"

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

linotp init database

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

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 linotp.cfg you can define a parameters for this:


The RADIUS_NAS_IDENTIFIER is the NAS_Identifier that is 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.

linotp server#

To get a quick result easily you may use the LinOTP command line tool and start a linotp development server with the following command:

linotp run

This will start a linotp server for you but is not suitable for production.


you need to init a token database upfront (see Token database)


you need add some linotp administrators (see Authentication)

Apache web server#


TODO: This part is outdated and needs to be updated to work with LinOTP 3.

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. 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.

  1. Activate this configuration by:

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


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.

Next we group the different LinOTP web interfaces and APIs (represented by their URL paths), based on the access level they should allow.

/manage, /system, /license, /audit and /admin

/manage is a web interface that uses the APIs provided by /system, /license, /audit and /admin.

These interfaces allow the management and configuration of LinOTP and should be restricted to admin-grade users. They are secured with JSON Web Tokens (JWT) and require setting up a local administrator account. The easiest way to achieve this is to use the LinOTP CLI commands; please refer to the respective man page, linotp-local-admins(1).

There is no need to set up additional server-level security features, so the respection section in the configuration may look like this:

<LocationMatch /(manage|system|license|audit|admin)>

# The authentication for administration requests is done from within the LinOTP application



This interface is used to retrieve a list of OTP values. By default, no one is allowed to use the interface and access must be explicitly granted, as it exposes highly sensitive information.

<Location /gettoken>

Require all denied


To allow access only from a certain location, you can use the “Require ip” statement:

<Location /gettoken>

Require ip


/selfservice and /userservice

These interfaces are provided to end users for managing their methods of authentication. The web interface at /selfservice uses the /userservice API, which authenticates the user against a user identity source defined in LinOTP by configuring a user ID resolver.

As this mechanism provides user authentication, there is no need to configure additional security measures:

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

Please ensure that these two interfaces have the same access settings and can be reached by token users.


This interface is used to validate multifactor authentication attempts.

The PAM authentication module pam_linotp and the RADIUS authentication module rlm_linotp2 are using this interface and you should therefore encrypt the communication between modules and interface with SSL.

You may also want to setup additional security steps. For example, you may restrict the IP addresses that are allowed to contact this interface, which can be achieved with a configuration like:

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

By default, however, there are no additional protection measures, so the configuration template should look like this:

<Location /validate>
   # No Authentication

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_ssl_certs.

Authenticating to the Management Interface#

The Management Interface, as well as all related administration APIs, always require authentication based on JSON Web Tokens (JWT).

To activate this setup, run::

a2ensite linotp2

There are three available sites: linotp2, linotp2-radius and linotp2-certs. The latter two additionally provide optional authentication measures which we describe below.


Ensure that only one site is active at a time. You can deactivate a site by using a2dissite.


By default, only users configured in a special administrators realm can obtain a JWT by providing correct login

credentials. The users on this administrative realm are at first only configurable via the LinOTP CLI but you can later on promote other resolvers to admininistrator level. They may then include users from external directories via e.g. LDAP.

Optional: additional authentication measures

You can use RADIUS authentication or client certificates as an extra security factor so that unauthorized users cannot access the Management Interface login endpoint. This is how you can configure the Apache webserver for the extra steps:

1. First deactivate other sites by using a2dissite. For example, if you have previously activated the “linotp2” site, run a2dissite linotp2.

  1. Activate the respective site:

  1. RADIUS authentication: activate RADIUS authentication to authenticate with OTP tokens by running:

    a2ensite linotp2-radius
  2. Client certificates: the LinOTP server will use the Common Name of the Distinguished Name of the client certificate. The client certificate can also be located on a smartcard. Activate this method by running:

    a2ensite linotp2-certs

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.