Simply deploy and run a privacyIDEA instance in a container environment.
Important
The base-image changed from python-slim
to Wolfi OS.
The old approach is still available in the python-slim
Branch.
privacyIDEA is an open solution for strong two-factor authentication like OTP tokens, SMS, smartphones or SSH keys.
This project is a complete build environment under linux to build and run privacyIDEA in a container environment. It uses the Wolfi OS image and the official privacyIDEA-Project from PyPi. The image uses gunicorn from PyPi to run the app.
The main goals of this project are to:
- Build and run the container image, simple and fast.
- Deploy different versions and/or stages (e.g. production, staging, devel ...) with the same or different configuration on the same host.
- Easy deploy a "full-stack" (e.g. privacyIDEA, radius, database and reverse proxy) with docker compose.
- Keep the container's image simple, slim and secure.
- To build images with no changes to the original privacyIDEA code and as less as possible additional scripts as possible inside the image to run the container.
What this project is not:
- A possible way to ignore the privacyIDEA Documentation
- A guide on how to use docker
- A guide how to configure and use privacyIDEA
Important
The image does not include a reverse proxy or a database backend. Running the default image as a standalone container uses gunicorn and a sqlite database. Using sqlite is not suitable for a production environment.
A more 'real-world' scenario, which is often used, is described in the Compose a privacyIDEA stack section.
Also check the Security considerations before running the image or stack in a production environment.
While decoupling the privacyIDEA image from dependencies like Nginx, Apache or database vendors ect., it is possible to run privacyIDEA with your favorite components.
Clone repository and start a full privacyIDEA stack:
git clone https://github.com/gpappsoft/privacyidea-docker.git
cd privacyidea-docker
make cert fullstack
Username / password: admin / admin
Starting the container for the first time could take a few seconds. Please reload the page after 20-30 seconds, if you get a 502 error from the reverse proxy.
Directory | Description |
---|---|
conf | contains pi.cfg and logging.cfg files which is included in the image build process. |
environment | contains different example-environment files for a whole stack via docker compose |
scripts | contains custom scripts for the privacyIDEA script-handler. The directory will be mounted into the container when composing a stack. Scripts must be executable (chmod +x) |
templates | contains files used for different services (nginx, radius ...) and also contains the ssl certificate for the reverse-proxy. Replace it with your own certificate and key file. Use PEM-Format without a passphrase. *.pfx is not supported. Name must be pi.pem and pi.key. |
Sample images from this project can be found here:
registry | repository |
---|---|
docker.io | docker pull docker.io/gpappsoft/privacyidea-docker:latest |
ghcr.io | docker pull ghcr.io/gpappsoft/privacyidea-docker:latest |
Note
latest
tagged image is maybe a pre- or development-release. Please use always a release number (like 3.10.1
)
- Installed a container runtime engine (docker / podman).
- Installed BuildKit, buildx and Compose V2 (docker-compose-v2) components
- The repository is tested with versions listed in COMPAT.md
- Podman is partially supported. Please refer to PODMAN.md for more details.
docker pull docker.io/gpappsoft/privacyidea-docker:latest
docker run -d --name privacyidea-docker\
-e PI_ADMIN=admin\
-e PI_ADMIN_PASS=admin\
-e PI_PEPPER=changeMe\
-e PI_SECRET=changeMe\
-v pidata:/privacyidea/etc/persistent:rw,Z\
-p 8080:8080\
gpappsoft/privacyidea-docker:latest
Web-UI: http://localhost:8080
User/password: admin/admin
To build and run a simple local privacyIDEA container (which can run standalone with sqlite):
git clone https://github.com/gpappsoft/privacyidea-docker.git
cd privacyidea-docker
make cert build push run
....
Default admin username: admin
Default admin password: admin
You can use Makefile targets to build different images with different privacyIDEA versions.
make build PI_VERSION=3.10.1
Use make push [REGISTRY=<registry>]
to tag and push the image1
Push image to local registry on port 50002
make push REGISTRY=localhost:5000
make clean
You can start the container with the same database (sqlite) and configuration and use make run
again without bootstrapping the instance.
make distclean
ⓘ This will wipe the whole container including the volumes!
target | optional ARGS | description | example |
---|---|---|---|
build |
PI_VERSION IMAGE_NAME |
Build an image. Optional: specify the version and image name | make build PI_VERSION=3.10 |
push |
REGISTRY |
Tag and push the image to the registry. Optional: specify the registry URI. Defaults to localhost:5000 | make push REGISTRY=docker.io/gpappsoft/privacyidea-docker |
run |
PORT TAG |
Run a standalone container with gunicorn and sqlite. Optional: specify the prefix tag of the container name and listen port. Defaults to pi and port 8080 | make run TAG=prod PORT=8888 |
secret |
Generate secrets to use in an environment file | make secret |
|
cert |
Generate a self-signed certificate for the reverse proxy container in ./templates and overwrite the existing one | make cert |
|
stack |
TAG PROFILE |
Run a whole stack with the environment file environment/application-TAG .env. Default is prod. Possible PROFILE values: stack,fullstack,ldap,radius |
make stack , make stack TAG=dev PROFILE=fullstack , make stack TAG=prod PROFILE=stack,radius |
fullstack |
Make a full stack with docker-compose.yml | make fullstack |
|
clean |
TAG |
Remove the container and network without removing the named volumes. Optional: change prefix tag of the container name. Defaults to prod | make clean TAG=prod |
distclean |
TAG |
Remove the container, network and named volumes. Optional: change prefix tag of the container name. Defaults to prod | make distclean TAG=prod |
Important
Using the image as a standalone container is not production ready. For a more like 'production ready' instance, please read the next section.
By using docker compose you can easily deploy a customized privacyIDEA instance, including Nginx as a reverse-proxy and MariaDB as a database backend.
With the use of different environment files for different full-stacks, you can deploy and run multiple stacks at the same time on different ports.
graph TD;
a2("--env-file=environment/application-dev.env");
w4(https://localhost:8444);
w5(RADIUS 2812);
w6(LDAP 2389);
subgraph s3 [ ];
r2(RADIUS);
n5(NGINX);
n6(LDAP);
n7(privacyIDEA);
n8(MariaDB);
st2[stack 2];
end;
a1("--env-file=environment/application-prod.env");
w1(https://localhost:8443);
w2(RADIUS 1812);
w3(LDAP 1389);
subgraph s1 [ ];
r1(RADIUS);
n1(NGINX);
n2(LDAP);
n3(privacyIDEA);
n4(MariaDB);
st1[Stack 1];
end;
a1~~~w1;
a1~~~w2;
a1~~~w3;
a2~~~w4;
a2~~~w5;
a2~~~w6;
w1<-- API / WebUI -->n1<-- reverse proxy -->n3(privacyIDEA)<-->n4
w2<-- radius auth -->r1<-- privacyIDEA Radius -->n3
w3<-- for clients -->n2<-- resolver -->n3
w4<-- API / WebUI -->n5<-- reverse proxy -->n7(privacyIDEA)<-->n8
w5<-- radius auth -->r2<-- privacyIDEA Radius -->n7
w6<-- for clients -->n6<-- resolver -->n7
classDef plain font-size:12px,fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
classDef heading font-size:12px,fill:#9db668,stroke:#fff,stroke-width:1px,color:#fff;
classDef title font-size:16px,color:#000,background-color:#9db668,stroke:#ffff;
classDef docker fill:#265a88,stroke:#fff,stroke-width:2px,color:#fff;
classDef second fill:#dba614,stroke:#fff,stroke-width:2px,color:#fff;
classDef tags fill:#dba614,stroke:#fff,stroke-width:2px,color:#fff;
classDef cluster fill:#fff,stroke:#888,stroke-width:2px,color:#265a88;
class w1,w2,w3,w4,w5,w6 plain;
class r1,n2,r2,n6 second;
class n1,n3,n4,n5,n6,n7,n8,r2,t1 docker;
class s1,s2,s3,s4 title;
class a1,a2,st1,st2 heading;
Find example .env files in the environment directory.
Note
The optional RADIUS and LDAP container is only available with PROFILE=fullstack|ldap|radius
. See examples below.
- The radius container use the image from privacyidea-freeradius.
- The openldap use the osicia/docker-openldap image.
Note
The docker-compose.yaml, used in this example, always use images from external registries. Change docker-compose.yaml to use your own images.
Run a stack with project the name prod and environment variables files from environment/application-prod.env
$ make cert #run only once to generate certificate
$ docker compose --env-file=environment/application-prod.env -p prod up
Or simple run a make
target.
This example will start a stack including privacyIDEA, reverse_proxy and mariadb container:
make cert stack
This example will start a full stack including privacyIDEA, reverse_proxy, mariadb, ldap and radius including sample data with users,realms. Project tag is prod
make cert fullstack
Note
The ldap have sample users. The resolvers and realm are already configured in privacyIDEA when stack is ready.
Shutdown the stack with the project name prod and remove all resources (container,networks, etc.) except the volumes.
docker compose -p prod down
You can start the stack in the background with console detached using the -d parameter.
$ docker compose --env-file=environment/application-prod.env -p prod up -d
Full example including build with make
targets:
make cert build push stack PI_VERSION=3.10 TAG=pidev
Now you can deploy additional containers like OpenLDAP for user realms or Owncloud as a client to test 2FA authentication.
Have fun!
Important
- Volumes will not be deleted.
- Delete the files in */privacyidea/etc/persistent/ *inside the privacyIDEA container if you want to bootstrap again. This will not delete an existing database expect sqlite databases!
- Compose a stack takes some time until the database tables are deplolyed and privacyIDEA is ready to run. Check health status of the container.
Variable | Default | Description |
---|---|---|
ENVIRONMENT |
environment/application-prod.env | Used to set the correct environment file (env_file) in the docker compose, which is used by the container. Use a relative filename here. |
PI_VERSION |
latest | Set the used image version |
PI_ADMIN |
admin | login name of the initial administrator |
PI_ADMIN_PASS |
admin | password for the initial administrator |
PI_PASSWORD |
admin | Password for the admin user. See Security considerations for more information. |
PI_PEPPER |
changeMe | Used for PI_PEPPER in pi.cfg. The filename, including the path, to the file inside the container, with the secret. Use make secrets to generate new random secrets to use with an environment file See Security considerations for more information. |
PI_SECRET |
changeMe | Used for SECRET_KEY in pi.cfg. Use make secrets to generate new random secrets to use with an environment file. See Security considerations for more information. |
PI_ENCKEY |
The enckey file for DB-encryption (base64). Only used if exists. Otherwise it will be generatetd using the pi-manage command. See privacy documentation how to create a key. |
|
PI_PORT |
8080 | Port used by gunicorn. Don't use this directly in productive environments. Use a reverse proxy.. |
PI_LOGLEVEL |
INFO | Log level in uppercase (DEBUG, INFO, WARNING, ect.). |
SUPERUSER_REALM |
"admin,helpdesk" | Admin realms, which can be used for policies in privacyIDEA. Comma separated list. See the privacyIDEA documentation for more information. |
PI_SQLALCHEMY_ENGINE_OPTIONS |
False | Set pool_pre_ping option. Set to True for DB clusters (like Galera). |
Variable | Description |
---|---|
DB_HOST |
Database host |
DB_PORT |
Database port |
DB_NAME |
Database name |
DB_USER |
Database user |
DB_PASSWORD |
The database password. |
DB_API |
Database driver (e.g. mysql+pymysql ) |
DB_EXTRA_PARAM |
Extra parameter (e.g. "?charset=utf8" ). Will be appended to the SQLAlchemy URI (see pi.cfg) |
Variable | Default | Description |
---|---|---|
PROXY_PORT |
8443 | Exposed HTTPS port |
PROXY_SERVERNAME |
localhost | Set the reverse-proxy server name. Should be the common name used in the certificate. |
Variable | Default | Description |
---|---|---|
RADIUS_PORT |
1812 | Exposed (external) radius port tcp/udp |
RADIUS_PORT |
1813 | Additional exposed (external) radius port udp |
Variable | Default | Description |
---|---|---|
LDAP_PORT |
1389 | Exposed (external) ldap port |
- Openldap admin user:
cn=admin,dc=example,dc=org
with passwordopenldap
- Password for ldap user always givenName in lowercase (e.g. Sandra Bullock = sandra)
- Additional user
helpdesk
with passwordhelpdesk
andadmin
with passwordadmin
available in ldap.
The current concept of using secrets with environment variables is not recommended in a docker-swarm/k8s/cloud environment. You should use secrets in such an environment. You can modify and re-write the pi.cfg to read secret files inside the container/pod via python.
- There is only the most essential and often-used parameters included. You can add more variables to the conf/pi.conf file and build your own image.
- Simply use a cron job on the host system with docker exec and the pi-manage command:
docker exec -it pi-privacyidea-1 pi-manage audit rotate_audit --age 90
- Use docker log:
docker logs pi-privacyidea-1
- Build a new image, make a push and pull. Re-create the container with additional argument
PIUPDATE
. This will run the schema update script to update the database. Or use theprivacyidea-schema-upgrade
script.
- Yes, by providing the sql dump to the db container. Please refer to the "Initializing the database contents" section from the official MariaDB docker documentation.
- Check the Prerequisites and requirements. Often there is a missing plugin (buildx, compose) - install the plugins and try again:
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
curl -SL https://github.com/docker/buildx/releases/download/v0.12.0/buildx-v0.12.0.linux-amd64 -o $DOCKER_CONFIG/cli-plugins/docker-buildx
chmod +x $DOCKER_CONFIG/cli-plugins/docker-{buildx,compose}
Check selinux and change the permissions like:
chcon -R -t container_file_t PATHTOHOSTDIR
PATHTOHOSTDIR
should point to the privacyidea-docker folder.
- Maybe you try to use ssl: Use the insecure option in your /etc/containers/registries.conf:
[[registry]] prefix="localhost" location="localhost:5000" insecure=true
- Save environment files (enckey ect.) which are stored persistent in the containers volume.
- Dump your database manually:
For the example stack, use the db container:
docker exec -it pi-db-1 mariadb-dump -u pi -psuperSecret pi
Will follow soon
This project is my private project doing in my free time. This project is not from the NetKnights company. The project uses the open-source version of privacyIDEA. There is no official support from NetKnights for this project.