Multi-Tenant Architecture

The qwc-services ecosystem allows you to use the Multi-Tenant architecture, that is, a single QWC2 instance (installation) can host different viewers, each with its own configuration of Themes, appearance, Plugins, users, etc.

Each tenant must have the configuration files config.json and tenantConfig.json. The directory where they are stored is configurable, but by default they are in qwc-docker/volumes/config-in/<tenant>/.

┌─────────────────────────────────────────────────────────────┐
│                    QWC2 MULTI-TENANT                        │
│                  (Una sola instalación)                     │
└─────────────────────────────────────────────────────────────┘
                              │
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌───────────────┐     ┌───────────────┐     ┌───────────────┐
│   TENANT 1    │     │   TENANT 2    │     │   TENANT 3    │
│  (tenant a)   │     │  (tenant b)   │     │  (tenant c)   │
└───────────────┘     └───────────────┘     └───────────────┘
        │                     │                     │
        ├─ config.json        ├─ config.json        ├─ config.json
        ├─ tenantConfig.json  ├─ tenantConfig.json  ├─ tenantConfig.json
        │                     │                     │
        ├─ Temas propios      ├─ Temas propios      ├─ Temas propios
        ├─ Usuarios propios   ├─ Usuarios propios   ├─ Usuarios propios
        ├─ Roles propios      ├─ Roles propios      ├─ Roles propios
        └─ Autenticación      └─ Autenticación      └─ Autenticación

The API-Gateway nginx.conf configuration extracts the tenant name, which must be defined, to route requests to the services.

server {
    listen       80;
    server_name  localhost;

    proxy_redirect off;
    server_tokens off;

    location ~ ^/(?<t>tenant1|tenant2)/ {
        # Extract tenant
        proxy_set_header Tenant $t;
        # Set headers for original request host
        proxy_set_header   Host              $http_host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        location ~ ^/[^/]+/auth {
            rewrite ^/[^/]+(.+) $1 break;
            proxy_pass http://qwc-auth-service:9090;
        }

        location ~ ^/[^/]+/ows {
            rewrite ^/[^/]+(.+) $1 break;
            proxy_pass http://qwc-ogc-service:9090;
        }

        location ~ ^/[^/]+/api/v1/featureinfo {
            rewrite ^/[^/]+(.+) $1 break;
            proxy_pass http://qwc-feature-info-service:9090;
        }

        # etc...

        location ~ ^/[^/]+/qwc_admin {
            rewrite ^/[^/]+(.+) $1 break;
            proxy_pass http://qwc-admin-gui:9090;
        }

        # Place these last to give precedence to the other rules:

        # Redirect request without trailing slash
        location ~ ^(/[^/]+)$ {
            return 301 $scheme://$http_host$1/;
        }
        location ~ ^/[^/]+/ {
            rewrite ^/[^/]+(.+) $1 break;
            proxy_pass http://qwc-map-viewer:9090;
        }
    }
}

Therefore, with a single QWC2 installation we can have different viewers with different behaviors. For example:

And for each of them, different authentication, different themes, etc.