Create VM. 5GB disk, 1GB RAM, 1 CPU. Install Debian 12 from netinst ISO. Choose Software: Standard System Utilties, SSH Server (default)
Install apache2, freeradius, radius plugin dependencies, MariaDB and dev stuff, python venv and dev stuff, pgk-config:
apt install freeradius freeradius-utils python3 python3-venv virtualenv python3-virtualenv python3-wheel python3-all-dev apache2 pkg-config mariadb-server mariadb-client libmariadb-dev-compat libmariadb-dev libapache2-mod-wsgi-py3 gcc libconfig-inifiles-perl libdata-dump-perl libtry-tiny-perl libjson-perl liblwp-protocol-https-perl liburi-encode-perl
Add User and config directory:
adduser --system --group --home /opt/privacyidea/ privacyidea
mkdir /etc/privacyidea
chown privacyidea:privacyidea /etc/privacyidea
Configure MariaDB safely:
mysql_secure_installation
-Switch to unix_socket authentication [Y/n] choose NO!
-Choose defaults for remaining questions
Create Database and User:
mysql -u root -p
CREATE DATABASE pi;
CREATE USER "pi"@"localhost" IDENTIFIED BY "<pidbuserpassword>";
GRANT ALL PRIVILEGES ON pi.* TO "pi"@"localhost";
flush privileges;
exit
Create /etc/privacyidea/pi.cfg with following content:
import logging
# The realm, where users are allowed to login as administrators
SUPERUSER_REALM = ['super', 'administrators']
# Your database
SQLALCHEMY_DATABASE_URI = 'mysql://pi:<pidbuserpassword>@localhost/pi'
# This is used to encrypt the token data and token passwords
PI_ENCFILE = '/etc/privacyidea/enckey'
# This is used to sign the audit log
PI_AUDIT_KEY_PRIVATE = '/etc/privacyidea/private.pem'
PI_AUDIT_KEY_PUBLIC = '/etc/privacyidea/public.pem'
# Truncate Audit entries to fit into DB columns
PI_AUDIT_SQL_TRUNCATE = True
# The Class for managing the SQL connection pool
PI_ENGINE_REGISTRY_CLASS = "shared"
PI_AUDIT_POOL_SIZE = 20
# Logging options
PI_LOGFILE = '/var/log/privacyidea/privacyidea.log'
PI_LOGLEVEL = logging.INFO
# Set maximum identifier length to 128
# SQLALCHEMY_ENGINE_OPTIONS = {"max_identifier_length": 128}
# PI_AUDIT_MODULE = <python audit module>
# PI_AUDIT_SQL_URI = <special audit log DB uri>
# Options passed to the Audit DB engine (supersedes SQLALCHEMY_ENGINE_OPTIONS)
# PI_AUDIT_SQL_OPTIONS = {}
# PI_INIT_CHECK_HOOK = 'your.module.function'
# PI_UI_DEACTIVATED = True
# PI_CSS = '/location/of/theme.css'
Generate secrets and add them to pi.cfg:
PEPPER="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)"
echo "PI_PEPPER = '$PEPPER'" >> /etc/privacyidea/pi.cfg
SECRET="$(tr -dc A-Za-z0-9_ </dev/urandom | head -c24)"
echo "SECRET_KEY = '$SECRET'" >> /etc/privacyidea/pi.cfg
Create logfile and directory, change owner to privacyidea:
mkdir /var/log/privacyidea
chown privacyidea:privacyidea /var/log/privacyidea
touch /var/log/privacyidea/privacyidea.log
chown privacyidea:privacyidea /var/log/privacyidea/privacyidea.log
Add Apache config with following content:
touch /etc/apache2/sites-available/privacyidea.conf
ln -s /etc/apache2/sites-available/privacyidea.conf /etc/apache2/sites-enabled/privacyidea.conf
WSGIPythonHome /opt/privacyidea
<VirtualHost _default_:443>
ServerAdmin webmaster@localhost
# You might want to change this
ServerName yourhostname
DocumentRoot "/var/www/"
<Directory />
# For Apache 2.4 you need to set this:
Require all granted
Options FollowSymLinks
AllowOverride None
</Directory>
# Yubico servers use /wsapi/2.0/verify as the path in the
# validation URL. Some tools (e.g. Kolab 2fa) let the
# user/admin change the api host, but not the rest of
# the URL. Uncomment the following two lines to reroute
# the api URL internally to privacyideas /ttype/yubikey.
#RewriteEngine on
#RewriteRule "^/wsapi/2.0/verify" "/ttype/yubikey" [PT]
# We can run several instances on different paths with different configurations
WSGIScriptAlias / /opt/privacyidea/etc/privacyidea/privacyideaapp.wsgi
#WSGIScriptAlias /instance1 /home/privacyidea/deploy/privacyideaapp1.wsgi
#WSGIScriptAlias /instance2 /home/privacyidea/deploy/privacyideaapp2.wsgi
#WSGIScriptAlias /instance3 /home/privacyidea/deploy/privacyideaapp3.wsgi
#
# The daemon is running as user 'privacyidea'
# This user should have access to the encKey database encryption file
WSGIDaemonProcess privacyidea processes=1 threads=15 display-name=%{GROUP} user=privacyidea
WSGIProcessGroup privacyidea
WSGIPassAuthorization On
ErrorLog /var/log/apache2/error.log
LogLevel warn
# Do not use %q! This will reveal all parameters, including setting PINs and Keys!
# Using SSL_CLINET_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\"" privacyIDEA
CustomLog /var/log/apache2/ssl_access.log privacyIDEA
# SSL Engine Switch:
# Enable/Disable SSL for this virtual host.
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
Install freeradius plugin:
mkdir /usr/share/privacyidea
mkdir /usr/share/privacyidea/freeradius
cd /usr/share/privacyidea/freeradius
wget https://raw.githubusercontent.com/privacyidea/FreeRADIUS/refs/heads/master/privacyidea_radius.pm
Create /etc/privacyidea/rlm_perl.ini with following content:
[Default]
URL = https://localhost/validate/check
REALM =
#RESCONF = someResolver
#SSL_CHECK = false
#DEBUG = true
#TIMEOUT = 10
#[Mapping]
#serial = privacyIDEA-Serial
#
#[Mapping user]
#group = Class
Download freeradius privacyidea perl module config and activate:
cd /etc/freeradius/3.0/mods-available/
wget https://raw.githubusercontent.com/privacyidea/FreeRADIUS/refs/heads/master/config/freeradius3/mods-perl-privacyidea
ln -s /etc/freeradius/3.0/mods-available/mods-perl-privacyidea /etc/freeradius/3.0/mods-enabled/mods-perl-privacyidea
Download freeradius privacyidea authentication config and activate:
cd /etc/freeradius/3.0/sites-available/
wget https://raw.githubusercontent.com/privacyidea/FreeRADIUS/refs/heads/master/config/freeradius3/privacyidea
ln -s /etc/freeradius/3.0/sites-available/privacyidea /etc/freeradius/3.0/sites-enabled/privacyidea
delete default freeradius config links:
rm /etc/freeradius/3.0/sites-enabled/default
rm /etc/freeradius/3.0/sites-enabled/inner-tunnel
rm /etc/freeradius/3.0/mods-enabled/eap
Configure Freeradius /etc/freeradius/3.0/clients.conf, add the following:
client kemp {
ipaddr = 10.10.10.10
secret = <radiussecret>
}
Restart freeradius:
systemctl restart freeradius
Enable Apache WSGI and SSL modules and restart apache:
a2enmod wsgi
a2enmod ssl
systemctl restart apache2
Create and activate Virtual Python environment, as user “privacyidea”:
su -s /bin/bash privacyidea
python3 -m venv /opt/privacyidea/
cd /opt/privacyidea
source bin/activate
Install PrivacyIdea dependencies and PrivacyIdea:
pip3 install wheel
pip3 install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v3.10/requirements.txt
pip3 install privacyidea==3.10
pip3 install mysqlclient
pip3 cache purge # clear pip download cache to save some diskspace
Install webauthn client js:
mkdir /opt/privacyidea/lib/python3.11/site-packages/privacyidea/static/contrib/js/webauthn-client
cd /opt/privacyidea/lib/python3.11/site-packages/privacyidea/static/contrib/js/webauthn-client
wget https://raw.githubusercontent.com/privacyidea/webauthn-client/refs/heads/master/pi-webauthn.js
Generate keys:
pi-manage create_enckey # encryption key for the database
pi-manage create_audit_keys # key for verification of audit log entries
Create DB:
pi-manage createdb
pi-manage db stamp head -d /opt/privacyidea/lib/privacyidea/migrations/
Disable welcome screen:
pi-manage policy create welcome_disable webui hide_welcome_info
Create Admin user:
pi-manage admin add admin
Done, exit virtual environment and privacy user shell
exit