Technical Guide
Detailed guide on how to deploy the cloud backend and frontend files on your servers.
1. BridgeXR
The BridgeXR management application consists of a simple frontend and backend. We provide everything needed to deploy both applications and an example configuration in the deployment package. Keep in mind that the provided configuration is an example and needs to be adjusted to be deployed for production use if you choose to do so. The provided configuration example showcases all mandatory settings needed to run the application.
2. Azure Integration
We provide integration with Azure Active Directory B2C SSO (3. SSO Integration), Azure Key Vault (5.2 Configuration) and Azure Blob Storage (5.1.2 Object Storage).
3. SSO Integration
3.1 Azure Active Directory B2C
In order to integrate with Azure Active Directory B2C SSO we need the following parameters:
Frontend:
Application (client) ID
Authority URL
Backend:
JWKS URI (found in the openid-configuration of the Azure AD B2C tenant)
For the frontend, the Application (client) ID and Authority URL are needed to configure the MSAL library used for authentication and have to be set in the msal.json found in the public directory of the supplied frontend files.
For the backend, the JWKS URI is needed to validate the tokens issued by Azure AD B2C and has to be set in the OidcKeysURL configuration key.
The API permissions needed are as follows:
User.Reademailprofile
The redirect URIs under Authentication need to be configured as follows:
Single-page application
https://<host>/msal-login-popup— needed for the Web Dashboardhttp://localhost:51273/StreamingAssets/callback.html— needed for the Unity Wizard
Android
msauth://com.zoe.bridgexr.client/<hash>— needed for the Android client (for more information about the hash consult the app documentation or contact us)
Mobile and desktop applications
unityhub://editor/authentication.editorAddons.editorLink/oauth2/http://localhost:8080/zoe/bridgexr/oauth2/
Refer to msal-client-application-configuration for more information.
3.2 Others
If a different SSO integration is needed, please contact us.
If no SSO integration is provided, the only way to log in is with credentials manually managed in the database. BridgeXR does not provide management facilities for user credentials.
4. Frontend
The frontend application is delivered as a folder of static files that must be served as a Single Page Application (SPA) on your own infrastructure.
The routing is handled client-side, so the web server should always return the index.html file for any unknown paths, rather than a 404.
The frontend requires /api to be mapped to the backend while stripping the /api prefix (e.g., https://frontend.local/api/foo/bar gets redirected to http[s]://backend.local/foo/bar internally).
The frontend files must be served over HTTPS, and the following headers must be set to allow the WebGPU component to work:
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
Refer to SharedArrayBuffer#security_requirements for more information.
For files served from /WebGL/ the appropriate gzip headers must be set for the browser to transparently use the compressed files.
We provide an example nginx configuration for serving the frontend and proxying to the backend. If you use a different web server and encounter deployment issues, please contact us.
5. Backend
The backend consists of a standalone binary for x86-64-linux that can be deployed via most contemporary mechanisms. If a different target is needed, please contact us.
Configuration is handled via environment variables, configuration files, or integrations with configuration providers, as outlined in §5.2 Configuration.
There are no additional requirements regarding the deployment method, so deploying on a Virtual Machine or Container from any provider should be possible.
We provide a prefilled (as far as possible) example config file and Dockerfile for the backend. If you encounter issues running the provided binary on your chosen infrastructure, please contact us.
5.1 Dependencies on External Services
Postgres
The backend uses a Postgres database to store most of its data.
Database migrations are handled by the backend, which assumes full access to the database defined in the application's connection string.
We do not provide backups on our side, so setting up a backup strategy for the database is the responsibility of the deployer.
Object Storage
For binary data, we defer to mature object storage solutions, and provide integrations with Azure Blob Storage and S3-compatible object storage.
We do not provide backups on our side, so setting up a backup strategy for the object storage is the responsibility of the deployer.
Azure Blob Storage
We provide integration with Azure Blob Storage for storing data. If you encounter issues with our Azure Blob Storage integration, please contact us.
S3-compatible Object Storage
We provide integration with S3-compatible object storage solutions for storing data.
This is tested using MinIO and AWS S3. If you encounter issues with a different S3-compatible storage solution, please contact us.
5.2 Configuration
The backend can be configured via:
Configuration files (
config.{json,yaml},.env)Command-line flags
Environment variables
Azure Key Vault
The specific keys which can be configured are found in the Appendix.
Appendix: Configuration Keys
Host
Host the main api server binds to
--host 0.0.0.0
{"HOST": "0.0.0.0"}
RCL_HOST=0.0.0.0
Name: host | Secret Value: 0.0.0.0
Port
Port the main api server binds to
--port 8080
{"PORT": "8080"}
RCL_PORT=8080
Name: port | Secret Value: 8080
Log Level
Log level for the server
--log-level INFO
{"LOG_LEVEL": "INFO"}
RCL_LOG_LEVEL=INFO
Name: log-level | Secret Value: INFO
Jwt Duration
Duration of JWT tokens created by the application
--jwt-duration 1h
{"JWT_DURATION": "1h"}
RCL_JWT_DURATION=1h
Name: jwt-duration | Secret Value: 1h
Refresh Duration
Duration of refresh tokens created by the application
--refresh-duration 0
{"REFRESH_DURATION": "0"}
RCL_REFRESH_DURATION=0
Name: refresh-duration | Secret Value: 0
Jwt Private Key Path
Path to JWT private key
--jwt-private-key-path /opt/jwt.pem
{"JWT_PRIVATE_KEY_PATH": "/opt/jwt.pem"}
RCL_JWT_PRIVATE_KEY_PATH=/opt/jwt.pem
Name: jwt-private-key-path | Secret Value: /opt/jwt.pem
Db Connection String
Connection string to the postgres database
--db-connection-string postgres://user:pass@localhost:5432/BridgeXR
{"DB_CONNECTION_STRING": "postgres://user:pass@localhost:5432/BridgeXR"}
RCL_DB_CONNECTION_STRING=postgres://user:pass@localhost:5432/BridgeXR
Name: db-connection-string | Secret Value: postgres://user:pass@localhost:5432/BridgeXR
Aws Endpoint
AWS endpoint parameter for S3-compatible object storage
--aws-endpoint minio.example.com:9900
{"AWS_ENDPOINT": "minio.example.com:9900"}
RCL_AWS_ENDPOINT=minio.example.com:9900
Name: aws-endpoint | Secret Value: minio.example.com:9900
Aws Access Key ID
AWS access key id parameter for S3-compatible object storage
--aws-access-key-id minio_user
{"AWS_ACCESS_KEY_ID": "minio_user"}
RCL_AWS_ACCESS_KEY_ID=minio_user
Name: aws-access-key-id | Secret Value: minio_user
Aws Secret Access Key
AWS secret access key parameter for S3-compatible object storage
--aws-secret-access-key minio_password
{"AWS_SECRET_ACCESS_KEY": "minio_password"}
RCL_AWS_SECRET_ACCESS_KEY=minio_password
Name: aws-secret-access-key | Secret Value: minio_password
Aws Bucket Name
AWS bucket parameter for S3-compatible object storage
--aws-bucket-name bridge-xr
{"AWS_BUCKET_NAME": "bridge-xr"}
RCL_AWS_BUCKET_NAME=bridge-xr
Name: aws-bucket-name | Secret Value: bridge-xr
Aws Endpoint Secure
Use HTTPS for access to S3-compatible object storage
--aws-endpoint-secure true
{"AWS_ENDPOINT_SECURE": "true"}
RCL_AWS_ENDPOINT_SECURE=true
Name: aws-endpoint-secure | Secret Value: true
Aws Endpoint Public Secure
Use HTTPS for access to the public url of the S3-compatible object storage
--aws-endpoint-public-secure true
{"AWS_ENDPOINT_PUBLIC_SECURE": "true"}
RCL_AWS_ENDPOINT_PUBLIC_SECURE=true
Name: aws-endpoint-public-secure | Secret Value: true
Key Vault Url
URL to the key vault
--key-vault-url https://example.vault.azure.net/
{"KEY_VAULT_URL": "https://example.vault.azure.net/"}
RCL_KEY_VAULT_URL=https://example.vault.azure.net/
This parameter cannot be configured via Azure Key Vault
Jwt Azure Key Name
Name of the key in Azure Key Vault used for JWT signing and verification
--jwt-azure-key-name jwt-key
{"JWT_AZURE_KEY_NAME": "jwt-key"}
RCL_JWT_AZURE_KEY_NAME=jwt-key
Name: jwt-azure-key-name | Secret Value: jwt-key
Azure Blob Container Name
Name of the Azure Blob Storage container
--azure-blob-container-name ExampleContainer
{"AZURE_BLOB_CONTAINER_NAME": "ExampleContainer"}
RCL_AZURE_BLOB_CONTAINER_NAME=ExampleContainer
Name: azure-blob-container-name | Secret Value: ExampleContainer
Azure Blob Account Name
Name of the Azure Blob Storage account
--azure-blob-account-name ExampleAccount
{"AZURE_BLOB_ACCOUNT_NAME": "ExampleAccount"}
RCL_AZURE_BLOB_ACCOUNT_NAME=ExampleAccount
Name: azure-blob-account-name | Secret Value: ExampleAccount
Azure Blob Account Key
Account key for the Azure Blob Storage account
--azure-blob-account-key ExampleKey
{"AZURE_BLOB_ACCOUNT_KEY": "ExampleKey"}
RCL_AZURE_BLOB_ACCOUNT_KEY=ExampleKey
Name: azure-blob-account-key | Secret Value: ExampleKey
Azure Blob Account URL
URL of the Azure Blob Storage account
--azure-blob-account-url https://example.blob.core.windows.net/
{"AZURE_BLOB_ACCOUNT_URL": "https://example.blob.core.windows.net/"}
RCL_AZURE_BLOB_ACCOUNT_URL=https://example.blob.core.windows.net/
Name: azure-blob-account-url | Secret Value: https://example.blob.core.windows.net/
Oidc Keys URL
URL to fetch OIDC keys used for Microsoft identity platform integration
--oidc-keys-url example.com/discovery/v2.0/keys
{"OIDC_KEYS_URL": "example.com/discovery/v2.0/keys"}
RCL_OIDC_KEYS_URL=example.com/discovery/v2.0/keys
Name: oidc-keys-url | Secret Value: example.com/discovery/v2.0/keys
Oidc Keys Refresh Interval
Interval to refresh the OIDC keys
--oidc-keys-refresh-interval 1h
{"OIDC_KEYS_REFRESH_INTERVAL": "1h"}
RCL_OIDC_KEYS_REFRESH_INTERVAL=1h
Name: oidc-keys-refresh-interval | Secret Value: 1h
Licensing Host
Host the licensing server listens on
--licensing-host
{"LICENSING_HOST": ""}
RCL_LICENSING_HOST=
Name: licensing-host | Secret Value:
Licensing Port
Port the licensing server listens on
--licensing-port
{"LICENSING_PORT": ""}
RCL_LICENSING_PORT=
Name: licensing-port | Secret Value:
Licensing Client Cert Path
Path to the licensing client certificate
--licensing-client-cert-path /opt/licensing_client_cert.pem
{"LICENSING_CLIENT_CERT_PATH": "/opt/licensing_client_cert.pem"}
RCL_LICENSING_CLIENT_CERT_PATH=/opt/licensing_client_cert.pem
Name: licensing-client-cert-path | Secret Value: /opt/licensing_client_cert.pem
Licensing Client Key Path
Path to the licensing client key
--licensing-client-key-path /opt/licensing_client_key.pem
{"LICENSING_CLIENT_KEY_PATH": "/opt/licensing_client_key.pem"}
RCL_LICENSING_CLIENT_KEY_PATH=/opt/licensing_client_key.pem
Name: licensing-client-key-path | Secret Value: /opt/licensing_client_key.pem
Last updated