We recommend using a guided installation with CAXperts for UDiTH
Portal. Please contact support@caxperts.com for information The docker images are available under quay.io/caxperts/portal and
quay.io/caxperts/caxturn While it is possible to use Portal directly exposed with HTTPS this
is not recommended. Please use a reverse proxy in front of Portal. Goto the keycloak installation and update the defaultadmin password
in the realm you specified Goto https://<alias/(sub)domain>/Portal
and login via defaultadmin and your defined password You can add additional users via the webinterface or link to a SSO
provider. All variables can also be read from a file like docker secrets. For
this add a postfix of _file to the variable and reference the file where
the secret is contained. Some settings represent an array. In this case please use the
following format. They start with 0 and increment. In future settings
array identifiers will be marked with They can also be multiple arrays in place As with every web server, we recommend to keep it updated with the
newest security fixes.
Setup Portal Linux
Requirements
Installation Requirements
Installation
Reverse Proxy
Installation Steps
Sample docker-compose.yml
file
services:
portal_demo:
image: quay.io/caxperts/portal:${PORTAL_VERSION:-latest}
restart: unless-stopped
environment:
- KeycloakAdmin__Name=${KEYCLOAK_ADMIN_USER}
- KeycloakAdmin__Password_file=${KEYCLOAK_ADMIN_PASSWORD}
- KeycloakUrl=https://${KEYCLOAK_DOMAIN}${KEYCLOAK_PATH:-/}
- KeycloakRealm=${KEYCLOAK_REALM}
- ConnectionStrings__AdminConnection=${PORTAL_CONNECTION_STRING}
- ServerUrl=https://${PORTAL_DOMAIN}
- LicenseKey_file=${PORTAL_LICENSEKEY}
networks:
- sqlserver
- external
volumes:
- ${PORTAL_IMPORT_FOLDER}:/import
- ${PORTAL_STORAGE_FOLDER}:/storage
networks:
external:
external: true
name: external
sqlserver:
external: true
name: sqlserverSample
docker-compose.yml file with CAX Turn for BBV
services:
portal_demo:
image: quay.io/caxperts/portal:${PORTAL_VERSION:-latest}
restart: unless-stopped
environment:
- KeycloakAdmin__Name=${KEYCLOAK_ADMIN_USER}
- KeycloakAdmin__Password_file=${KEYCLOAK_ADMIN_PASSWORD}
- KeycloakUrl=https://${KEYCLOAK_DOMAIN}${KEYCLOAK_PATH:-/}
- KeycloakRealm=${KEYCLOAK_REALM}
- ConnectionStrings__AdminConnection=${PORTAL_CONNECTION_STRING}
- ServerUrl=https://${PORTAL_DOMAIN}
- StreamingConfig__IceConfig__IceServers__0__Urls__0=turn:${TURNSERVER_ADDRESS}:${TURNSERVER_UDP_PORT}
- StreamingConfig__IceConfig__IceServers__0__Urls__1=turn:${TURNSERVER_ADDRESS}:${TURNSERVER_TCP_PORT}?transport=tcp
- StreamingConfig__IceConfig__IceServers__0__CredentialType=password
- StreamingConfig__IceConfig__IceServers__0__Username=${TURNSERVER_USERNAME}
- StreamingConfig__IceConfig__IceServers__0__Credential=${TURNSERVER_PASSWORD}
- LicenseKey_file=${PORTAL_LICENSEKEY}
networks:
- sqlserver
- external
volumes:
- ${PORTAL_IMPORT_FOLDER}:/import
- ${PORTAL_STORAGE_FOLDER}:/storage
turn:
image: quay.io/caxperts/caxturn:${CAXTURN_VERSION:-latest}
# Port range mapping is very slow so we use network_mode: host
network_mode: host
environment:
- CAXTURN_ENABLE_UDP=true
- CAXTURN_ENABLE_TCP=true
- CAXTURN_UDP_PORT=${CAXTURN_UDP_PORT}
- CAXTURN_TCP_PORT=${CAXTURN_TCP_PORT}
- CAXTURN_MIN_PORT=${CAXTURN_MIN_PORT}
- CAXTURN_MAX_PORT=${CAXTURN_MAX_PORT}
- CAXTURN_PUBLIC_IP=${CAXTURN_PUBLIC_IP}
- CAXTURN_USERNAME=${CAXTURN_USERNAME}
- CAXTURN_PASSWORD=${CAXTURN_PASSWORD}
restart: unless-stopped
networks:
external:
external: true
name: external
sqlserver:
external: true
name: sqlserverSample docker-compose
Keycloak
services:
keycloak:
image: quay.io/keycloak/keycloak:${KEYCLOAK_VERSION:-26.4.0}
restart: unless-stopped
environment:
# >= 26
KC_BOOTSTRAP_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USER}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
# <26
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN_USER}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
KC_DB: mssql
KC_DB_URL: "jdbc:sqlserver://${KEYCLOAK_SQLSERVER_ADDRESS:-mssql:1433};databaseName=${KEYCLOAK_SQLSERVER_DATABASENAME};encrypt=true;trustServerCertificate=true;"
KC_DB_USERNAME: ${KEYCLOAK_SQLSERVER_USER}
KC_DB_PASSWORD: ${KEYCLOAK_SQLSERVER_PASSWORD}
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
KC_HTTP_ENABLED: true
KC_PROXY_HEADERS: xforwarded
KC_HOSTNAME: https://${KEYCLOAK_DOMAIN}${KEYCLOAK_PATH:-/}
KC_HTTP_RELATIVE_PATH: ${KEYCLOAK_RELATIVE_PATH:-/}
command: start
networks:
- "sqlserver"
- "external"
healthcheck:
test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:9000${KEYCLOAK_RELATIVE_PATH:-/}/health/live']
interval: 5s
timeout: 3s
retries: 3
start_period: 1m
volumes:
- /root/storage/keycloak/providers:/opt/keycloak/providers
networks:
external:
external: true
name: "external"
sqlserver:
external: true
name: "sqlserver"Sample docker-compose.yml
for MSSQL
services:
mssql:
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
environment:
SA_PASSWORD: ${SQLSERVER_SA_PASSWORD}
ACCEPT_EULA: "Y"
volumes:
- ${SQLSERVER_STORAGE_FOLDER}:/var/opt/mssql
ports:
- 1433:1433 #not required. But useful for remote connection. Secure this
restart: unless-stopped
healthcheck:
# -C disable checks for encryption
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -C -U sa -P "$SQLSERVER_SA_PASSWORD" -Q "SELECT 1" -b -o /dev/null
interval: 5s
timeout: 3s
retries: 3
start_period: 10m
networks:
default:
external: true
name: sqlserverAccessing Portal
Environment Variables
File secrets
KeycloakAdmin__Password=<pw>
KeycloakAdmin__Password_file=/run/secrets/keycloak_passwordArray based
[]Serilog__WriteTo__0__Name=Console
Serilog__WriteTo__1__Name=OpenTelemetryStreamingConfig__IceConfig__IceServers__0__Urls__0=turn:server1:3478
StreamingConfig__IceConfig__IceServers__0__Urls__1=turn:server1:3478?transport=tcpVariables
# URL used to connect to keycloak. This is the same url as clients will use to authenticate
KeycloakUrl=https://...
# Keycloak Realm to use for authentications
KeycloakRealm=portal
# Keycloak Admin user name
KeycloakAdmin__Name=admin
# Keycloak Admin user password
KeycloakAdmin__Password=...
# MSSQL Database connection
ConnectionStrings__AdminConnection=...
# URL which the server will be reachable under
ServerUrl=https://
# If you are using a proxy you need to define this if it modifies the url to a new relative path
RelativePath=/ (default)
# The port Portal will listen on
ServerPort=5000 (default)
# UDiTH License key to use. Can also be configured via the interface
LicenseKey=...
# Ignore Certificate errors for connections to Keycloak
IgnoreCertificateErrors=false (default)
# Log usernames for requests and BBV sessions
ShowPII=false (default)
# For what domains to add CORS allow origions
AccessControlAllowOrigin__[]=...
# if for Keycloak or Licensing a proxy server is required please specify
Proxy__Address=...
Proxy__UserName=...
Proxy__Password=...
# If you are running without a ReverseProxy or require fully encrypted connections you can specify either a PFX file or PEM key and cert. For PFX a password is required, for PEM its required if a encrypted PEM is used
StandaloneHttpsSettings__PfxFile=...
StandaloneHttpsSettings__PemKeyFile=...
StandaloneHttpsSettings__PemCertFile=...
StandaloneHttpsSettings__Password=...
# From which folder to import models from
ModelImport__ImportDirectory=/import (default)
# Where will imported models be placed
ModelImport__ProviderStoragePath=/storage (default)
# Fow often are ... checked
ModelImport__IntervalInMilliseconds=5000 (default)
# Dont allow model attributes to be imported into the database
ModelProcessing__ForcedSkipProcessing=false
# With modeloverwrites you can specify files which should be overwritten for each model
ModelFileOverwrites__Values__Data_default.upvf=/overwrittendefault.upvf
# For BBV an ICE server needs to be configured
StreamingConfig__IceConfig__IceServers__[]__CredentialType=password (default)
StreamingConfig__IceConfig__IceServers__[]__Urls__[]=turn:
StreamingConfig__IceConfig__IceServers__[]__Username=caxturn
StreamingConfig__IceConfig__IceServers__[]__Credential=...
#Logging&Monitoring
Serilog__Enrich__0=FromLogContext
Serilog__MinimumLevel__Default=Debug
Serilog__MinimumLevel__Override__Microsoft.AspNetCore.SignalR=Information
Serilog__MinimumLevel__Override__Microsoft Warning
Serilog__MinimumLevel__Override__System Warning
Serilog__MinimumLevel__Override__Windows=Warning
Serilog__WriteTo__0__Name=Console
Serilog__WriteTo__1__Args__Endpoint=https://
Serilog__WriteTo__1__Args__IncludedData=157
Serilog__WriteTo__1__Args__Protocol=HttpProtobuf
Serilog__WriteTo__1__Name=OpenTelemetry
OTEL_EXPORTER_OTLP_ENDPOINT=https://...
OTEL_EXPORTER_OTLP_HEADERS=Authorization=...
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf
OTEL_METRIC_EXPORT_INTERVAL=10000
OTEL_RESOURCE_ATTRIBUTES=environment=...
OTEL_SERVICE_NAME=...
#Dont touch unless instructed
StreamingConfig__WatchdogSessionTimeOut=30000
StreamingConfig__ConnectionHandshakeTimeout=0
StreamingConfig__MaximumReceiveMessageSize=0
ModelHosting__ZipArchivePoolInitialSize=2
ModelHosting__ZipArchivePoolMinSize=2
ModelHosting__ZipArchivePoolMaxSize=10
ModelHosting__ZipArchiveCreateDuration=1000
ModelHosting__ZipArchiveRemoveDuration=5000
RunAsStandAlone=true (default)
RunMigrationsOnStartup=true (default)Security