<VirtualHost *:443>
ServerName deid.datatailor.be
SSLEngine On
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/deid.datatailor.be/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/deid.datatailor.be/privkey.pem
##
## General proxy settinggs
##
<Proxy *>
Require all granted
</Proxy>
## Settings needed for Minio
ProxyPreserveHost On
ProxyVia Block
RemoteIPHeader X-Forwarded-For
##
## Put Web applications using ShinyProxy at path /apps/
## Put Inception at path /inception/
## Put API using FastAPI at path /API/, visit /API/docs to get the documentation
## Put Minio at path /s3/
## - 9001/9901 is the WebUI of Minio
## - 9000/9900 is the API of Minio
## Note: Sequence is important here as minio S3 API is always running at the root of the domain
##
RewriteEngine on
## Web apps
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /apps/(.*) ws://127.0.0.1:8280/apps/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /apps/(.*) http://127.0.0.1:8280/apps/$1 [P,L]
## Inception
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /inception/(.*) ws://localhost:8180/inception/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /inception/(.*) http://localhost:8180/inception/$1 [P,L]
## API
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /API/(.*) ws://127.0.0.1:8380/API/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /API/(.*) http://127.0.0.1:8380/API/$1 [P,L]
## Ollama
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /ollama/(.*) ws://127.0.0.1:11434/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /ollama/(.*) http://127.0.0.1:11434/$1 [P,L]
## Minio
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /s3/(.*) ws://localhost:9901/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /s3/(.*) http://localhost:9901/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} =websocket
RewriteRule /(.*) ws://localhost:9900/$1 [P,L]
RewriteCond %{HTTP:UPGRADE} !=websocket
RewriteRule /(.*) http://localhost:9900/$1 [P,L]
</VirtualHost>
Security
Authentication
There are several other ways to extend the authentication from simple password based authentication to more integrated authentication methods. The different components allow
- Inception: OIDC, LDAP, SAML, simple, external pre-authentication
- Frontend apps with ShinyProxy: OIDC, LDAP, SAML, simple, external pre-authentication, none
- Minio: provide the user/password as set in environment variables at container start, further users can be made in the Minio frontend
- API: provide the user/password as set in environment variables at container start
It is advised to put an Apache webserver which hosts your domain (e.g. https://deid.yourcompany.eu/) and extend the reverse proxy shown above where you integrate the authentication with the OIDC compliant mod_auth_openidc plugin. For support on setting this up, get in touch. An example of this setup is shown below.
SSL with a reverse proxy
You can run the docker containers behind a reverse proxy to offload the SSL hosting as shown below. The below Apache configuration puts
- Inception available under the url https://your.domain.name/inception/
- Minio at https://your.domain.name/s3/
- The blackbar webapps at https://your.domain.name/apps/
- The API at https://your.domain.name/API/API/docs
- Sets an Ollama webservice at https://your.domain.name/ollama/
If you define the Apache configuration as follows at /etc/apache2/sites-available/deid.conf where you have obtained SSL certificates from you local institution or from Letsencrypt.
Make sure you have enabled the Apache modules
sudo a2enmod ssl rewrite headers proxy proxy_http proxy_wstunnel proxy_html proxy_ajp remoteip
You can start up Apache and this will make the Minio environment available in the example at https://deid.datatailor.be/s3/ and Inception at https://deid.datatailor.be/inception/
sudo a2ensite deid
sudo apache2ctl configtest
sudo service apache2 restart
If you do this, you need to set the environment variable MINIO_BROWSER_REDIRECT_URL
when launching the blackbar-apps-inception
container such that the Minio console knows that it’s running behind a reverse proxy.
docker run -d --name blackbar-apps-inception \
-p 9901:9001 \
-p 9900:9000 \
-p 8180:8080 \
-v $(pwd)/s3:/data \
-v $(pwd)/inception:/export \
-e MINIO_BROWSER_REDIRECT_URL="https://deid.datatailor.be/s3/" \
--restart always \
--env-file .env \
ghcr.io/bnosac/blackbar-inception-minio
OIDC authentication
You can use the OIDC compliant mod_auth_openidc plugin to dispatch the authentication to e.g. Keycloak of Microsoft Entra ID by adding the following to the Apache configuration.
Alongside Keycloak
The example below uses Keycloak and puts the apps behind authentication governed by groups in Keycloak.
##
## Authentication using Keycloak
##
OIDCProviderMetadataURL https://deid.yourcompany.eu/auth/realms/deid/.well-known/openid-configuration
OIDCRedirectURI https://deid.yourcompany.eu/apps/secure
OIDCCryptoPassphrase XXXXXXXXXXXXXXXXXXXXXX
OIDCClientID blackbar-client
OIDCRemoteUserClaim preferred_username
OIDCAuthNHeader remote_user
OIDCInfoHook userinfo
OIDCSessionInactivityTimeout 28800
OIDCSessionMaxDuration 28800
<Location ~ "/apps*">
AuthType openid-connect
Require valid-user
</Location>
<Location ~ "/apps/app/rstudio*|/apps/app/vscode*">
AuthType openid-connect
Require claim klant:blackbar-admin
Require claim klant:blackbar-developer
</Location>
<Location ~ "/apps/app/anonymization-inspection*|/apps/app/pseudonymization-inspection*|/apps/app/blackbar-cockpit*">
AuthType openid-connect
Require claim klant:blackbar-admin
Require claim klant:blackbar-developer
Require claim klant:blackbar-user
</Location>
<Location ~ "/apps/app/blackbar-patients-document-chat*">
AuthType openid-connect
Require claim klant:blackbar-admin
Require claim klant:blackbar-developer
Require claim klant:blackbar-user
Require claim klant:blackbar-patients-document-chat
</Location>
Alongside Microsoft Entra ID
If you have an existing Microsoft Entra ID setup, you can perform the authentication using it with the following integration alongside mod_auth_openidc.
For this, in Entra ID setup up a client (or application in Entra ID terminology), get the tenant id and client id. Create a client secret in Entra ID and copy the value from the Entra ID user interface. Next add upn to the token configuration as optional claim as well as a group claim. Create security groups blackbar-admin, blackbar-developer, blackbar-user and blackbar-patients-document-chat and assign users to them. Get the security group id’s and use them in the apache configuration as group claims. Screenshots of these are shown below - see also documentation on Entra ID alongside mod_auth_openidc here.
An example of this setup is shown below where a file ´/etc/apache2/options-auth.conf´ is created. If you add ´Include /etc/apache2/options-auth.conf´ to your apache configuration, authentication will be done alongside Entra ID.
export OIDC_PROVIDER_METADATA_URL=https://login.microsoftonline.com/{tenant_id}/v2.0/.well-known/openid-configuration
export OIDC_REDIRECT_URI=https://{deid-apps.yourdomain.eu}/apps/secure
export OIDC_CLIENT_ID=client-id-application-id-from-entraid
export OIDC_CLIENT_SECRET=client-secret-from-entraid-in-client-credentials
export OIDC_CRYPTO_PASSPHRASE=random-string-of-length32-to-encrypt-the-oidc-token
export OIDC_REMOTE_USER_CLAIM=upn
export OIDC_AUTHN_HEADER=remote_user
export OIDC_INFO_HOOK=userinfo
export OIDC_CLAIM_BLACKBAR_ADMIN="claim groups:5cfe050b-82a4-4441-8cfe-bbea93cce8b0"
export OIDC_CLAIM_BLACKBAR_DEVELOPER="claim groups:4dd99544-799f-4180-924d-180e2a7af0d4"
export OIDC_CLAIM_BLACKBAR_USER="claim groups:4bf961c5-e5e7-4bd2-bb61-eb89c4a980b8"
export OIDC_CLAIM_BLACKBAR_PATIENT_DOCUMENT_CHAT="claim groups:93d7e6fe-a90a-452b-8d8f-da2b4b5c0e31"
cat << EOF | sudo tee /etc/apache2/options-auth.conf
OIDCProviderMetadataURL ${OIDC_PROVIDER_METADATA_URL}
OIDCRedirectURI ${OIDC_REDIRECT_URI}
OIDCCryptoPassphrase ${OIDC_CRYPTO_PASSPHRASE}
OIDCClientID ${OIDC_CLIENT_ID}
OIDCClientSecret ${OIDC_CLIENT_SECRET}
OIDCRemoteUserClaim ${OIDC_REMOTE_USER_CLAIM}
OIDCAuthNHeader ${OIDC_AUTHN_HEADER}
OIDCInfoHook ${OIDC_INFO_HOOK}
OIDCScope "openid profile"
<Location ~ "/apps*">
AuthType openid-connect
Require valid-user
#LogLevel debug
</Location>
<Location ~ "/apps*">
AuthType openid-connect
Require valid-user
</Location>
<Location ~ "/apps/app/rstudio*|/apps/app/vscode*">
AuthType openid-connect
Require ${OIDC_CLAIM_BLACKBAR_ADMIN}
Require ${OIDC_CLAIM_BLACKBAR_DEVELOPER}
</Location>
<Location ~ "/apps/app/anonymization-inspection*|/apps/app/pseudonymization-inspection*|/apps/app/blackbar-cockpit*">
AuthType openid-connect
Require ${OIDC_CLAIM_BLACKBAR_ADMIN}
Require ${OIDC_CLAIM_BLACKBAR_DEVELOPER}
Require ${OIDC_CLAIM_BLACKBAR_USER}
LogLevel debug
</Location>
<Location ~ "/apps/app/blackbar-patients-document-chat*">
AuthType openid-connect
Require ${OIDC_CLAIM_BLACKBAR_ADMIN}
Require ${OIDC_CLAIM_BLACKBAR_DEVELOPER}
Require ${OIDC_CLAIM_BLACKBAR_USER}
Require ${OIDC_CLAIM_BLACKBAR_PATIENT_DOCUMENT_CHAT}
</Location>
EOF