This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.
Setting Up Deployment Pattern 1
This page guides you through setting up deployment pattern 1, which is a HA clustered deployment of WSO2 Identity Server. For more information about deployment pattern 1 and its high level architecture, see  Deployment Patterns - Pattern 1. You can install multiple instances of WSO2 products in a cluster to ensure that if one instance becomes unavailable or is experiencing high traffic, another instance will seamlessly handle the requests. For complete information on clustering concepts, see Clustering Overview in the Common Product Administration Guide . Creating a cluster of WSO2 Identity Server instances involves a standard two node cluster for high availability. To ensure that the instances share governance registry artifacts, you must create a JDBC mount. At a high level, use the following options to cluster Identity Server with a minimum of two nodes. The first section includes instructions on setting up databases. The second section involves setting up a standard two node cluster, the third section involves setting up the Identity Server dashboard in a clustered environment and the third section includes additional configurations if you need to set up a load balancer to front your cluster.
WSO2 products allow you to configure multiple user stores to store your users and their roles. Your user store can be one of the following: A Directory Service that can communicate over LDAP protocol like OpenLDAP Active Directory A database that can communicate over JDBC Set up a user store named WSO2UserStore. Note: The instructions in this tutorial demonstrate configuring a JDBC user store. Point all cluster nodes to the same user store in the See Configuring User Stores for more information on how to set up other types of user stores. Copy the JDBC driver (in this case MySQL driver) to the By default, WSO2 Identity Server is started with an embedded LDAP which comes with the product. Disable the embedded LDAP of node 2 by modifying embedded-ldap.xml which can be found in the Create the databases. See Setting up the Physical Database in the WSO2 Administration Guide for db scripts and more information. Alternatively, you can create more databases for each type of data to separate the data logically. Note that this will NOT make a difference in performance and is not actually neccessary. However, if you do wish to separate the data logically into separate databases, see the Setting Up Separate Databases for Clustering topic. Configure the datasource for the databases in both nodes of your cluster in the master-datasources.xml file found in the Mount the governance and configuration registry in the For more information on mounting the registry, see Sharing Databases in a Cluster. Note: The production recommendation is to set the In the registry browser, verify that the governance collection is shown with the symlink icon. Follow the instructions below to cluster WSO2 Identity Server. Do the following changes to the Enable clustering on node 1 and node 2 by setting the clustering element to true: Use the well known address (WKA) based clustering method. In WKA-based clustering, we need to have a subset of cluster members configured in all the members of the cluster. At least one well known member has to be operational at all times. WSO2 supports the following membership schemes as well. For more information, see Clustering WSO2 Products - About Membership Schemes. Configure the Under the Note: You can also use IP address ranges for the Configure caching. From WSO2 Identity Server 5.2.0 onwards, distributed caching is disabled and it is not recommended to use this due to many practical issues that are related to configuring and running distributed caching properly. WSO2 Identity Server employs Hazelcast as the primary method of implementing cluster messages while using distributed caching in a simple setup. About Clustering For information on clustering, see Clustering WSO2 Products. About Caching Why caching Caching is an additional layer on top of databases. It enables to keep the recently used data that are fetched from the database in local memory, so that for subsequent data requests instead of fetching from the database the data can be served from the local memory. Caching has certain advantages and disadvantages that you need to evaluate when deciding on your caching strategy. The load on the underlying database or LDAP is reduced as data is served from already fetched data in memory. Improved performance due to the reduced number of database calls for repetitive data fetching. Coherency problems may occur when the data change is not immediately reflected on cached data if one node or an external system updates the database. Data in memory can become stale yet be served, e.g., serving data from memory while its corresponding record in the database is deleted. Caching in WSO2 Identity Server Historically WSO2 Identity Server used distributed caching to utilize the above-mentioned advantages as well as to minimize the coherence problem. However, in newer deployment patterns where the network is not tightly controlled, distributed caching fail in unexpected ways. Hence, we no longer recommend using distributed caching. Instead, it is recommended to have local caches (if required) and cache invalidation messages (if required) by considering the information given below. The ForceLocalCache property When Hazelcast clustering is enabled certain caches act as distributed caches. The Cache invalidation uses Hazelcast messaging to distribute the invalidation message over the cluster and invalidate the caches properly. This is used to minimize the coherence problem in a multi-node setup. Typical clustered deployment cache scenarios This is the recommended approach. Hazelcast messaging invalidates the caches. Invalidation clears only the caches in specific nodes. Other caches are cleared at cache expiration. Hazelcast communication is not used. As the decisions take time to propagate over nodes (default cache timeout is 15 minutes), there is a security risk in this method. To reduce the risk, reduce the default cache timeout period. To learn how to reduce the default cache timeout period, see Configuring Cache Layers - timeout. The data are directly acquired from the database. Eliminates the security risks caused due to not having cache invalidation. This method will create a performance degradation due to the lack of caching. To reduce the security risk created in the second scenario and to improve performance in comparison with the third scenario, disable the security-related caches and sustain the performance-related caches as local caches. This requires identification of these caches depending on the use case. This scenario is only recommended if the network has tight tolerance where the network infrastructure is capable of handling high bandwidth with very low latency. Typically this applies only when you deploy all the nodes in a single server rack having fiber-optic cables. In any other environments, this implementation will cause cache losses. Thus, this implementation is not recommended for general use. Configure the following. Change the datasource name to Change the datasource name to WSO2 products use Hazelcast as its default clustering engine. You can configure the hazelcast properties for the product nodes by following the steps given below. Create the The above configurations are explained below. If you have enabled log4j for hazelcast logging as shown above, be sure to enter the configuration shown below in the Configure the Identity Server node 1 using the following steps. Go to the Tip: If you are using an Openshift Docker container for the deployment, do the following. Add the following In the This hostname is used by the IS cluster. It must be specified in the Follow all the configuration steps that were done in node 1 for node 2 as well. To enable synchronization for runtime artifacts you must have a shared file system. You can use one of the following depending on your environment. Create a symlink from the Instead of mounting the file system directly to the Follow the steps given below to set up the dashboard for the WSO2 Identity Server in a clustered environment. Change the service provider configuration for the dashboard in the Configure the Configure the Optionally, configure the If you need to set up the above WSO2 Identity Server cluster with Nginx, you can follow the instructions given below (you must do this after setting up the cluster following the above instructions). When clustering WSO2 Identity Server with a load balancer, make sure to enable sticky sessions. This is required for the management console and the dashboard to work and if we disable temporary session data persistence in the Sticky sessions for SSO Sticky sessions are required to ensure a flawless SSO workflow when temporary session data persistence is disabled. It is recommended to use sticky sessions for SSO in order to have a higher throughput. For more information on sticky sessions, see Sticky Sessions with Manager Nodes. The following is the deployment diagram with the load balancer. Use the following steps to configure NGINX Plus version 1.7.11 or nginx community version 1.9.2 as the load balancer for WSO2 products. (In these steps, we refer to both versions collectively as "Nginx".) Configure Nginx to direct the HTTP requests to the two worker nodes via the HTTP 80 port using the Note: Shown below is a general Nginx configuration. Click this link for more specific configuration with exposing various endpoints: Now that you've configured HTTP requests, you must also configure HTTPS requests. Configure Nginx to direct the HTTPS requests to the two worker nodes via the HTTPS 443 port using Note: The configurations for nginx community version and NGINX Plus are different here since the community version does not support the Configure Nginx to access the Management Console as Reload the Nginx server. If you have made modifications to anything other than the VHost files, you may need to restart the Nginx server instead of reloading: Create SSL certificates for both the manager and worker nodes using the instructions that follow: Execute the following command to import the created certificate file to the client truststore: While creating keys, enter the host name ( By default, WSO2 Identity Server runs on 9443 port. The following steps describe how you can configure a proxy port of 443. Open It is not possible to configure proxy port from load balancer itself since there is a post request while authenticating to IS Dashboard. So, If you are planning to use Identity server Dashboard, you must do this configuration. Below configurations are also needed if you are using the dashboard. Configure proxy port and host in Configure proxy port and host in Configure proxy port and host in Now you can access the management console using the following URL: https://wso2.is.com/carbon/ If both nodes will be running on the same server, set the port offset to avoid port conflicts. Start the nodes using the following command on both nodes.Configuring the user store
master-datasources.xml
and user-mgt.xml
files. <IS_HOME>/repository/component/lib
directory of both nodes. To do this, download the MySQL Java connector JAR from here and place it in the <IS_HOME>/repository/components/lib
directory.<IS_HOME>/repository/conf/identity
directory.<EmbeddedLDAP>
<Property name="enable">false</Property>
<--------------------->
<EmbeddedLDAP>
Configuring the datasources
This tutorial demonstrates deployment with a user management database (WSO2UMDB
) and an identity database ( IDENTITYDB)
.<IS_HOME>/repository/conf/datasources
folder.
The code block below shows a sample configuration of the user mangement database and identity database for a mysql database. For instructions on how to configure the datasource depending on the type of database you created, see Changing the Carbon Database in the WSO2 Product Administration Guide. <datasources>
<datasource>
<name>WSO2_CARBON_DB</name>
<description>The datasource used for registry and user manager</description>
<jndiConfig>
<name>jdbc/WSO2CarbonDB</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:h2:./repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>org.h2.Driver</driverClassName>
<maxActive>50</maxActive>
<maxWait>60000</maxWait>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
<defaultAutoCommit>false</defaultAutoCommit>
</configuration>
</definition>
</datasource>
<datasource>
<name>WSO2UserStore</name>
<description>The User Store</description>
<jndiConfig>
<name>jdbc/WSO2UserStore</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://wso2is-pattern1-mysql-service:3306/WSO2UMDB?autoReconnect=true&useSSL=false</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>80</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
<defaultAutoCommit>false</defaultAutoCommit>
</configuration>
</definition>
</datasource>
<datasource>
<name>WSO2_IDENTITY_DB</name>
<description>The datasource used for registry, user management and identity</description>
<jndiConfig>
<name>jdbc/WSO2IdentityDS</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://wso2is-pattern1-mysql-service:3306/WSO2_IDENTITY_DB?autoReconnect=true&useSSL=false</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>80</maxActive>
<maxWait>60000</maxWait>
<minIdle>5</minIdle>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
<defaultAutoCommit>false</defaultAutoCommit>
</configuration>
</definition>
</datasource>
</datasources>
<datasource>
<name>BPS_DS</name>
<description></description>
<jndiConfig>
<name>bpsds</name>
</jndiConfig>
<definition type="RDBMS">
<configuration>
<url>jdbc:mysql://wso2is-pattern1-mysql-service:3306/WSO2_IDENTITY_DB autoReconnect=true&verifyServerCertificate=false&useSSL=true</url>
<username>wso2carbon</username>
<password>wso2carbon</password>
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<maxActive>100</maxActive>
<maxWait>10000</maxWait>
<maxIdle>20</maxIdle>
<testOnBorrow>true</testOnBorrow>
<validationQuery>SELECT 1</validationQuery>
<validationInterval>30000</validationInterval>
<useDataSourceFactory>false</useDataSourceFactory>
<defaultAutoCommit>false</defaultAutoCommit>
</configuration>
</definition>
</datasource>
Mounting the registry
registry.xml
file found in the <IS_HOME>/repository/conf
folder to share the registry across all nodes in the cluster. The code block below shows a sample configuration.<dbConfig name="sharedregistry">
<dataSource>jdbc/WSO2IdentityDS</dataSource>
</dbConfig>
<remoteInstance url="https://localhost:9443/registry">
<id>sharedregistry</id>
<dbConfig>sharedregistry</dbConfig>
<readOnly>false</readOnly>
<registryRoot>/</registryRoot>
<enableCache>true</enableCache>
<cacheId>jdbc:mysql://wso2is-pattern1-mysql-service:3306/WSO2_IDENTITY_DB</cacheId>
</remoteInstance>
<mount path="/_system/config" overwrite="true">
<instanceId>sharedregistry</instanceId>
<targetPath>/_system/config</targetPath>
</mount>
<mount path="/_system/governance" overwrite="true">
<instanceId>sharedregistry</instanceId>
<targetPath>/_system/governance</targetPath>
</mount>
<versionResourcesOnChange>
property in the registry.xml
file to false. This is because automatic versioning of resources can be an extremely expensive operation.<versionResourcesOnChange>false</versionResourcesOnChange>
Clustering Identity Server for high availability
<IS_HOME>/repository/conf/axis2/axis2.xml
file for both nodes.
<clustering class="org.wso2.carbon.core.clustering.hazelcast.HazelcastClusteringAgent" enable="true">Specify the name of the cluster this node will join.
<parameter name="domain">wso2.is.domain</parameter>
<
parameter
name
=
"membershipScheme"
>wka</
parameter
>
localMemberHost
and localMemberPort
entries. These must be different port values for the two nodes if they are on the same server to prevent any conflicts.<
parameter
name
=
"localMemberHost"
>127.0.0.1</
parameter
>
<
parameter
name
=
"localMemberPort"
>4000</
parameter
>
members
section, add the hostName
and port
for each WKA member. As we have only two nodes in our sample cluster configuration, we will configure both nodes as WKA nodes.<members>
<member>
<hostName>127.0.0.1</hostName>
<port>4000</port>
</member>
<member>
<hostName>127.0.0.2</hostName>
<port>4010</port>
</member>
</members>
hostName
. For example, 192.168.1.2-10. This should ensure that the cluster eventually recovers after failures. One shortcoming of doing this is that you can define a range only for the last portion of the IP address. You should also keep in mind that the smaller the range, the faster the time it takes to discover members since each node has to scan a lesser number of potential members.ForceLocalCache
property within the <cache>
section in the carbon.xml
file in the <IS_HOME>/repository/conf
directory is there to mark that all the caches should act like local caches even in a clustered setup. (This is by default set to true
)<ForceLocalCache>true</ForceLocalCache>
Scenario Local Caching Distributed Caching Hazelcast Clustering Distributed Invalidation Description 1. All caches are local with distributed cache invalidation Enabled Not Applicable Enabled Enabled 2. All caches are local without distributed cache invalidation Enabled Not Applicable Disabled Disabled 3. No caching Disabled Disabled Disabled Disabled 4. Certain caches are disabled while the remaining are local Enabled for the available local caches Not Applicable Enabled Enabled 5. Distributed caching enabled Disabled—the ForceLocalCache
property is set to false
.Enabled Enabled Not Applicable jdbc/WSO2UserStore
in user-mgt.xml (located in <IS_HOME>/repository/conf/
). This refers to the user store you configured in the Configuring the user store section above. <UserManager>
<Realm>
<Configuration>
...
<Property name="dataSource">jdbc/WSO2UserStore</Property>
</Configuration>
...
</Realm>
</UserManager>
jdbc/WSO2IDENTITYDB
in identity.xml (located in <IS_HOME>/repository/conf/identity
) of both node1 and node2. This refers to the datasource Configuring the datasources section above.<JDBCPersistenceManager>
<DataSource>
<Name>jdbc/WSO2IDENTITYDB</Name>
</DataSource>
<!-- <SkipDBSchemaCreation>false</SkipDBSchemaCreation> -->
</JDBCPersistenceManager>
Configuring Hazelcast properties
hazelcast.properties
file with the following property configurations, and copy the file to the <IS_HOME>/repository/conf/
directory. #Disabling the hazelcast shutdown hook
hazelcast.shutdownhook.enabled=false
#Setting the hazelcast logging type to log4j
hazelcast.logging.type=log4j
wso2carbon.log
file.log4j.properties
file (stored in the <IS_HOME>/repository/conf/
directory). This can be used to configure the log level for hazelcast logging. For a clustered production environment, it is recommended to use INFO as the log level as shown below.log4j.logger.com.hazelcast=INFO
Changing hostnames and ports
<IS_HOME>/repository/conf/tomcat/catalina-server.xml
file and add the proxy port as 443.<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
port="9443"
proxyPort="443"
........
<!--
optional attributes:
proxyPort="80"
-->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
port="9763"
proxyPort="80"
Tomcat
RemoteIPValve
to the <IS_HOME>/repository/conf/tomcat/catalina-server.xml
file.<Valve
className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="reg_ex_for_internal_docker_IPs"
remoteIpHeader="x-forwarded-for"
proxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto"
/>
<IS_HOME>/repository/conf/carbon.xml
directory, define the hostname for your server.<HostName>wso2.is.com</HostName>
<MgtHostName>wso2.is.com</MgtHostName>
/etc/hosts
file as:127.0.0.1 wso2.is.com
Enabling artifact synchronization
<IS_HOME>/repository/deployment
path to the "Deployment" directory of the shared file system that you created in step 2 of this section.<IS_HOME>/repository/tenants
path to the "Tenants" directory of the shared file system that you created in step 2 of this section.<IS_HOME>/repository/deployment
and <IS_HOME>/repository/tenants
paths, a symlink is created to avoid issues that may occur if you delete the product to redeploy it; in which case the file system would get mounted to a non existing path. Setting up the dashboard
<
IS_HOME>/repository/conf/identity/sso-idp-config.xml
file.<AssertionConsumerServiceURLs><AssertionConsumerServiceURL>https://is.wso2.com/dashboard/acs</AssertionConsumerServiceURL></AssertionConsumerServiceURLs>
<DefaultAssertionConsumerServiceURL>https://is.wso2.com/dashboard/acs</DefaultAssertionConsumerServiceURL>
proxyHost
and proxyHTTPSPort
in the <IS_HOME>/repository/deployment/server/jaggeryapps/dashboard/conf/site.json
file with your IP or hostname and the port."proxyHost" : "is.wso2.com",
"proxyHTTPSPort" : "443",
proxyHos
t and proxyHTTPSPort
in the <WSO2IS_HOME>/repository/deployment/server/webapps/shindig/WEB-INF/web.xml
file with your IP or hostname and the port.shindig.host=is.wso2.com
shindig.port=443
<IS_HOME>repository/conf/datasources/master-datasources.xml
file to set up the user dashboard.Fronting with a loadbalancer (Nginx)
<IS_HOME>/repository/conf/identity/identity.xml
file. Configuring Nginx
http://is.wso2.com/<service>
. To do this, create a VHost file (is.http.conf
) in the /etc/nginx/conf.d
directory and add the following configurations into it.upstream wso2.is.com {
server xxx.xxx.xxx.xx3:9763;
server xxx.xxx.xxx.xx4:9763;
}
server {
listen 80;
server_name is.wso2.com;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass http://wso2.is.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
https://is.wso2.com/<service>
. To do this, create a VHost file (is.https.conf
) in the /etc/nginx/conf.d
directory and add the following configurations into it.sticky
directive.
https://mgt.is.wso2.com/carbon
via HTTPS 443 port. This is to direct requests to the manager node. To do this, create a VHost file (
mgt.is.https.conf
) in the /etc/nginx/conf.d
directory and add the following configurations into it.server {
listen 443;
server_name mgt.is.wso2.com;
ssl on;
ssl_certificate /etc/nginx/ssl/mgt.crt;
ssl_certificate_key /etc/nginx/ssl/mgt.key;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_read_timeout 5m;
proxy_send_timeout 5m;
proxy_pass https://xxx.xxx.xxx.xx2:9443/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
error_log /var/log/nginx/mgt-error.log ;
access_log /var/log/nginx/mgt-access.log;
}
$sudo service nginx reload
$sudo service nginx restart
Create SSL certificates
$sudo openssl genrsa -des3 -out server.key 1024
$sudo openssl req -new -key server.key -out server.csr
$sudo cp server.key server.key.org
$sudo openssl rsa -in server.key.org -out server.key
$sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
keytool -import -trustcacerts -alias server -file server.crt -keystore client-truststore.jks
is.wso2.com
or mgt.is.wso2.com
) as the common name.Configure the Proxy Port in IS Nodes
<IS_HOME>/repository/conf/tomcat/catalina-server.xml
file and add the proxy port 443 in https connector as follows.<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
port="9443"
proxyPort="443"
<IS_HOME>/repository/deployment/server/jaggeryapps/dashboard/conf/site.json
file as follows:{
"proxy":{
"proxyHost":"nginx.mycomp.org"
"proxyHTTPSPort":"443",
"proxyContextPath":"",
"servicePath":"/services"
}
}
<IS_HOME>/repository/deployment/server/jaggeryapps/portal/conf/site.json
file as follows:{
"proxy":{
"proxyHost":"nginx.mycomp.org"
"proxyHTTPSPort":"443",
"proxyContextPath":""
},
"fido":{
"appId":""
}
}
<IS_HOME>/repository/deployment/server/webapps/shindig/WEB-INF/web.xml
<context-param>
<param-name> system.properties </param-name>
<param-value>
<![CDATA[
shindig.host=
shindig.port=443
aKey=/shindig/gadgets/proxy?container=default&url=
]]>
Running the cluster
Starting up and verifying product nodes