PACS and VIEW multitenancy
WARNING
Before starting a multi-tenant installation and configuration, a fundamental knowledge of tenants, multitenancy, and reverse proxying is needed.
Both PACS and VIEW can work with this concept, but it is much more complex and challenging from a technical standpoint than single-tenant setups.
Properly configuring the reverse proxy to function as required demands a thorough understanding and solid knowledge of reverse proxying and traffic redirecting. It's crucial to have a strong foundational knowledge before attempting such an installation. In addition, to handle an installation that uses subdomains it is required to know how to manage Cloud infrastructures.
We do not recommend embarking on this setup without a robust base in these concepts.
Multitenancy is a software architecture pattern where a single instance of an application serves multiple tenants. In a multi-tenant architecture, the application is designed to logically partition its data and configuration so that each tenant's data remains isolated and secure. Despite sharing the same application infrastructure and codebase, each tenant perceives the application as their dedicated environment.
Each tenant has its own separate and isolated data, configuration settings, user management, and other specific customizations. Tenants operate independently from one another within the same application environment.
In the case of PACS and VIEW, databases for each tenant are separated, and physical storage should be separated as well. This ensures that each tenant's data is isolated and secure. Detailed information on how to configure the storage areas will be provided in the PACS configuration | Adding-a-physical-medium section.
Advantages of multitenancy:
Cost efficiency: running a single instance of the application reduces operational costs, as resources are shared among tenants.
Simplified maintenance: upgrades, bug fixes, and new features can be deployed centrally, benefiting all tenants simultaneously.
Consistent performance: efficient resource management ensures that the application performs consistently for all tenants.
Multitenancy modes
There are two primary modes of operation for the applications:
By URL contexts: in this mode, the application uses URL contexts to match the incoming request and redirect it to the correct tenant (e.g.
{IP}:{PORT}/{TENANT}/pacs). The tenant context is configured at the reverse proxy level (e.g. NGINX).By subdomains: alternatively, the application can use a matcher with subdomains. This mode is configurable within the PACS and VIEW configuration page. The matcher will direct requests based on subdomain patterns to the appropriate tenant. By default, the matcher will obtain the tenant from the second subdomain (e.g. pacs.tenant.zeeromed.com).
After configuring a multi-tenant architecture, global configurations and tenant management for the PACS and VIEW systems will be handled by accessing the tenant admin, which is created by default for each system.
Basic example of URL contexts configuration
Below is a basic example of an URL contexts configuration that uses NGINX as a reverse proxy.
docker-compose.yml file
services:
nginx:
image: ${NGINX_IMAGE}
container_name: nginx
volumes:
- ${STORAGE}/compose/nginx/default.conf:/etc/nginx/conf.d/default.conf
environment:
- TZ=${TIMEZONE}
ports:
- 80:80
networks:
- o3net
NGINX default configuration (default.conf)
upstream view {
server view:8181;
}
upstream pacs {
server pacs:8080;
}
server {
listen 80;
server_name '_';
client_max_body_size 0;
location ~ /(?<tenant>.*)/(?<app>view|pacs) {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Tenant $tenant;
if ($app = 'view') {
rewrite ^/(.*)/view/ngv$ /$1/view/ngv/webdv.html redirect;
rewrite ^/(.*)/view$ /$1/view/ngv/webdv.html redirect;
rewrite ^/(.*)/view/$ /$1/view/ngv/webdv.html redirect;
rewrite ^/(.*)/view/(.*)$ /$2 break;
}
if ($app = 'pacs') {
rewrite ^/(.*)/pacs/o3-ipm-web$ /$1/pacs/o3-ipm-web/index.html redirect;
rewrite ^/(.*)/pacs$ /$1/pacs/o3-ipm-web/index.html redirect;
rewrite ^/(.*)/pacs/$ /$1/pacs/o3-ipm-web/index.html redirect;
rewrite ^/(.*)/pacs/(.*)$ /$2 break;
}
proxy_pass http://$app;
}
}