diff --git a/cluster_mssql/README.md b/cluster_mssql/README.md
new file mode 100644
index 0000000..6a38dce
--- /dev/null
+++ b/cluster_mssql/README.md
@@ -0,0 +1,149 @@
+# Clustered configuration
+
+Running `./start.sh -c` will perform some cleanup then start the containers in a clustered configuration.
+When running, the system looks like this:
+
+```
+ +--------------------------------------------------+
+ | 172.60.0.99 |
+ | +----------------+ |
+ | | |+--------------+ |
+(XMPP-C2S) 55222 -|-------| Load Balancer |+-------+ | |
+(BOSH) 57070 -| | | | | |
+(BOSHS) 57443 -| +----------------+ | | |
+ | | | 172.60.0.30 |
+ | | | +--------+ |
+ | | +=============+ | |- 5223 (XMPP-C2S)
+ | | | | | XMPP 3 |----|- 5263 (XMPP-S2S)
+ | | | | | | |- 9093 (HTTP-Admin)
+ | | | | +------+-+ |- 7073 (BOSH)
+ | | | | | |
+ | 172.60.0.10 | 172.60.0.20 | |
+ | +--------+ | +--------+ | |
+(XMPP-C2S) 5221 -| | +======+ | |=====+ |- 5222 (XMPP-C2S)
+(XMPP-S2S) 5261 -|------| XMPP 1 +============+ XMPP 2 | |- 5262 (XMPP-S2S)
+(HTTP-Admin) 9091 -| | | | |------------|- 9092 (HTTP-Admin)
+(BOSH) 7071 -| +----+---+ +----+---+ |- 7072 (BOSH)
+ | | | |
+ | | | |
+ | +---+--+ | |
+ | | | | |
+(Database) 1433 -|-------| DB +------------------+ |
+ | | | |
+ | +------+ |
+ | 172.60.0.11 |
+ | |
+ +----------------172.60.0.0/24---------------------+
+```
+
+Note that the load balancer is configured to be less flappy, with the flappiness controlled by the nginx config,
+simulating simple round-robin DNS load balancing. Ports from individual servers are exposed and can be hit directly.
+
+Openfire is configured with the following XMPP domain:
+
+* `xmpp.localhost.example`
+
+Openfire is configured with the following hostnames:
+
+* `xmpp1.localhost.example`
+* `xmpp2.localhost.example`
+* `xmpp3.localhost.example`
+
+The following users are configured:
+
+* `user1` `password`
+* `user2` `password`
+* `user3` `password`
+
+The following MUC rooms are configured:
+
+* `muc1`
+* `muc2`
+
+
+## Hosts file entries
+To access the XMPP servers and load balancer from your local machine you should
+add entries to your hosts file:
+
+```
+127.0.0.1 openfire-lb-1
+127.0.0.1 xmpp.localhost.example
+127.0.0.1 xmpp1.localhost.example
+127.0.0.1 xmpp2.localhost.example
+127.0.0.1 xmpp3.localhost.example
+```
+
+## Client configuration
+Depending on your requirements, you can configure your client to connect via the load balancer
+at `openfire-lb-1:55222` or directly to the individual servers at:
+- `xmpp1.localhost.example:5221`
+- `xmpp2.localhost.example:5222`
+- `xmpp3.localhost.example:5223`
+
+## Network
+
+The Docker compose file defines a custom bridge network with a single subnet of `172.60.0.0/24` for the clustered configuration.
+
+When the `-6` argument to `./start.sh` is provided, then an additional subnet of `fd23:0d79:d076::/64` is configured.
+Then, IPv6 is preferred for internal networking. Note that the IPv4 network remains in place, as Docker does not support
+IPv6-only containers.
+
+When running with the optional `-6` flag (that adds IPv6 support) the system looks like this:
+
+```
+ +--------------------------------------------------+
+ | [fd23:d79:d076::99] |
+ | 172.60.0.99 |
+ | +----------------+ |
+ | | |+--------------+ |
+(XMPP-C2S) 55222 -|-------| Load Balancer |+-------+ | |
+(BOSH) 57070 -| | | | | |
+(BOSHS) 57443 -| +----------------+ | | |
+ | | | [fd23:d79:d076::30]
+ | | | 172.60.0.30 |
+ | | | +--------+ |
+ | | +=============+ | |- 5223 (XMPP-C2S)
+ | | | | | XMPP 3 |----|- 5263 (XMPP-S2S)
+ | | | | | | |- 9093 (HTTP-Admin)
+ | | | | +------+-+ |- 7073 (BOSH)
+ | | | | | |
+ | [fd23:d79:d076::10] | [fd23:d79:d076::20]| |
+ | 172.60.0.10 | 172.60.0.20 | |
+ | +--------+ | +--------+ | |
+(XMPP-C2S) 5221 -| | +======+ | |=====+ |- 5222 (XMPP-C2S)
+(XMPP-S2S) 5261 -|------| XMPP 1 +============+ XMPP 2 | |- 5262 (XMPP-S2S)
+(HTTP-Admin) 9091 -| | | | |------------|- 9092 (HTTP-Admin)
+(BOSH) 7071 -| +----+---+ +----+---+ |- 7072 (BOSH)
+ | | | |
+ | | | |
+ | +---+--+ | |
+ | | | | |
+(Database) 1433 -|-------| DB +------------------+ |
+ | | | |
+ | +------+ |
+ | 172.60.0.11 |
+ | [fd23:d79:d076::11] |
+ | |
+ +----------------172.60.0.0/24---------------------+
+ fd23:0d79:d076::/64
+```
+
+### Removing a node from the network
+
+To remove a node from the network run the following command:
+
+`docker network disconnect NETWORK-NAME CONTAINER-NAME`
+
+For example:
+
+`docker network disconnect openfire-testing_openfire-federated-net openfire-testing_xmpp1_1`
+
+### Adding a node to the network
+
+To add a node to the network fun the following command:
+
+`docker network connect NETWORK-NAME CONTAINER-NAME`
+
+For example:
+
+`docker network connect openfire-testing_openfire-federated-net openfire-testing_xmpp1_1`
\ No newline at end of file
diff --git a/cluster_mssql/docker-compose-clustered.yml b/cluster_mssql/docker-compose-clustered.yml
new file mode 100644
index 0000000..6d1b537
--- /dev/null
+++ b/cluster_mssql/docker-compose-clustered.yml
@@ -0,0 +1,109 @@
+services:
+
+ db:
+ platform: linux/amd64
+ image: mcr.microsoft.com/mssql/server:2019-latest
+ container_name: mssql_server
+ networks:
+ - app-network
+ ports:
+ - "1433:1433"
+ environment:
+ - ACCEPT_EULA=Y
+ - SA_PASSWORD=MyStrongPassword1
+ volumes:
+ - mssql_data:/var/opt/mssql
+ - ./sql:/init-scripts
+ healthcheck:
+ test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$SA_PASSWORD" -Q "SELECT 1" -C || exit 1
+ interval: 10s
+ retries: 10
+ start_period: 10s
+ timeout: 5s
+
+ db-init:
+ platform: linux/amd64
+ image: mcr.microsoft.com/mssql/server:2019-latest
+ networks:
+ - app-network
+ depends_on:
+ db:
+ condition: service_healthy
+ environment:
+ - SA_PASSWORD=MyStrongPassword1
+ volumes:
+ - ./sql:/init-scripts
+ # Override entrypoint to run your updated script
+ entrypoint: /bin/bash /init-scripts/init-db.sh
+
+ lb:
+ image: nginx:stable
+ ports:
+ - "55222:55222"
+ - "57070:57070"
+ - "57443:57443"
+ volumes:
+ - ./nginx/nginx.conf:/etc/nginx/nginx.conf
+
+ xmpp1:
+ image: "${OPENFIRE_IMAGE}:${OPENFIRE_TAG}"
+ ports:
+ - "5221:5222"
+ - "5261:5269"
+ - "7071:7070"
+ - "7441:7443"
+ - "9091:9090"
+ depends_on:
+ - "db-init"
+ volumes:
+ - ./_data/xmpp/1/conf:/var/lib/openfire/conf
+ - ./_data/plugins:/opt/plugins
+ - ../_common/wait-for-it.sh:/wait-for-it.sh
+ command: ["/wait-for-it.sh", "-s", "db:1433", "--", "/sbin/entrypoint.sh", "-Dhazelcast.prefer.ipv4.stack=${PREFER_IPV4} -Djava.net.preferIPv6Addresses=${PREFER_IPV6}"]
+
+ xmpp2:
+ image: "${OPENFIRE_IMAGE}:${OPENFIRE_TAG}"
+ ports:
+ - "5222:5222"
+ - "5262:5269"
+ - "7072:7070"
+ - "7442:7443"
+ - "9092:9090"
+ depends_on:
+ - "db-init"
+ volumes:
+ - ./_data/xmpp/2/conf:/var/lib/openfire/conf
+ - ./_data/plugins:/opt/plugins
+ - ../_common/wait-for-it.sh:/wait-for-it.sh
+ command: ["/wait-for-it.sh", "-s", "db:1433", "--", "/sbin/entrypoint.sh", "-Dhazelcast.prefer.ipv4.stack=${PREFER_IPV4} -Djava.net.preferIPv6Addresses=${PREFER_IPV6}"]
+
+ xmpp3:
+ image: "${OPENFIRE_IMAGE}:${OPENFIRE_TAG}"
+ ports:
+ - "5223:5222"
+ - "5263:5269"
+ - "7073:7070"
+ - "7443:7443"
+ - "9093:9090"
+ depends_on:
+ - "db-init"
+ volumes:
+ - ./_data/xmpp/3/conf:/var/lib/openfire/conf
+ - ./_data/plugins:/opt/plugins
+ - ../_common/wait-for-it.sh:/wait-for-it.sh
+ command: ["/wait-for-it.sh", "-s", "db:1433", "--", "/sbin/entrypoint.sh", "-Dhazelcast.prefer.ipv4.stack=${PREFER_IPV4} -Djava.net.preferIPv6Addresses=${PREFER_IPV6}"]
+
+ dozzle:
+ image: amir20/dozzle:latest
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ ports:
+ - 9999:8080
+
+volumes:
+ mssql_data:
+
+# Define the network at the bottom
+networks:
+ app-network:
+ driver: bridge
\ No newline at end of file
diff --git a/cluster_mssql/docker-compose-db.yml b/cluster_mssql/docker-compose-db.yml
new file mode 100644
index 0000000..b83cf64
--- /dev/null
+++ b/cluster_mssql/docker-compose-db.yml
@@ -0,0 +1,34 @@
+services:
+ db:
+ platform: linux/amd64
+ image: mcr.microsoft.com/mssql/server:2019-latest
+ container_name: mssql_server
+ ports:
+ - "1433:1433"
+ environment:
+ - ACCEPT_EULA=Y
+ - SA_PASSWORD=MyStrongPassword1
+ volumes:
+ - mssql_data:/var/opt/mssql
+ healthcheck:
+ test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$SA_PASSWORD" -Q "SELECT 1" -C || exit 1
+ interval: 10s
+ retries: 10
+ start_period: 10s
+ timeout: 5s
+
+ db-init:
+ platform: linux/amd64
+ image: mcr.microsoft.com/mssql/server:2019-latest
+ depends_on:
+ db:
+ condition: service_healthy
+ environment:
+ - SA_PASSWORD=MyStrongPassword1
+ volumes:
+ - ./sql:/init-scripts
+ # Override entrypoint to run your updated script
+ entrypoint: /bin/bash /init-scripts/init-db.sh
+
+volumes:
+ mssql_data:
\ No newline at end of file
diff --git a/cluster_mssql/docker-compose-network-dualstack.yml b/cluster_mssql/docker-compose-network-dualstack.yml
new file mode 100644
index 0000000..513670d
--- /dev/null
+++ b/cluster_mssql/docker-compose-network-dualstack.yml
@@ -0,0 +1,63 @@
+services:
+
+ db:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.11
+ ipv6_address: fd23:d79:d076::11
+
+ lb:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.99
+ ipv6_address: fd23:d79:d076::99
+
+ xmpp1:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.10
+ ipv6_address: fd23:d79:d076::10
+ extra_hosts:
+ - "xmpp1.localhost.example=fd23:d79:d076::10"
+ - "conference.xmpp1.localhost.example=fd23:d79:d076::10"
+ - "xmpp2.localhost.example=fd23:d79:d076::20"
+ - "conference.xmpp2.localhost.example=fd23:d79:d076::20"
+ - "xmpp3.localhost.example=fd23:d79:d076::30"
+ - "conference.xmpp3.localhost.example=fd23:d79:d076::30"
+
+ xmpp2:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.20
+ ipv6_address: fd23:d79:d076::20
+ extra_hosts:
+ - "xmpp1.localhost.example=fd23:d79:d076::10"
+ - "conference.xmpp1.localhost.example=fd23:d79:d076::10"
+ - "xmpp2.localhost.example=fd23:d79:d076::20"
+ - "conference.xmpp2.localhost.example=fd23:d79:d076::20"
+ - "xmpp3.localhost.example=fd23:d79:d076::30"
+ - "conference.xmpp3.localhost.example=fd23:d79:d076::30"
+
+ xmpp3:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.30
+ ipv6_address: fd23:d79:d076::30
+
+ extra_hosts:
+ - "xmpp1.localhost.example=fd23:d79:d076::10"
+ - "conference.xmpp1.localhost.example=fd23:d79:d076::10"
+ - "xmpp2.localhost.example=172.60.0.20"
+ - "conference.xmpp2.localhost.example=fd23:d79:d076::20"
+ - "xmpp3.localhost.example=172.60.0.30"
+ - "conference.xmpp3.localhost.example=fd23:d79:d076::30"
+
+networks:
+ openfire-clustered-net:
+ driver: bridge
+ enable_ipv6: true
+ ipam:
+ driver: default
+ config:
+ - subnet: 172.60.0.0/24
+ - subnet: fd23:0d79:d076::/64
diff --git a/cluster_mssql/docker-compose-network-ipv4-only.yml b/cluster_mssql/docker-compose-network-ipv4-only.yml
new file mode 100644
index 0000000..c58526a
--- /dev/null
+++ b/cluster_mssql/docker-compose-network-ipv4-only.yml
@@ -0,0 +1,56 @@
+services:
+
+ db:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.11
+
+ lb:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.99
+
+ xmpp1:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.10
+ extra_hosts:
+ - "xmpp1.localhost.example=172.60.0.10"
+ - "conference.xmpp1.localhost.example=172.60.0.10"
+ - "xmpp2.localhost.example=172.60.0.20"
+ - "conference.xmpp2.localhost.example=172.60.0.20"
+ - "xmpp3.localhost.example=172.60.0.30"
+ - "conference.xmpp3.localhost.example=172.60.0.30"
+
+ xmpp2:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.20
+ extra_hosts:
+ - "xmpp1.localhost.example=172.60.0.10"
+ - "conference.xmpp1.localhost.example=172.60.0.10"
+ - "xmpp2.localhost.example=172.60.0.20"
+ - "conference.xmpp2.localhost.example=172.60.0.20"
+ - "xmpp3.localhost.example=172.60.0.30"
+ - "conference.xmpp3.localhost.example=172.60.0.30"
+
+ xmpp3:
+ networks:
+ openfire-clustered-net:
+ ipv4_address: 172.60.0.30
+ extra_hosts:
+ - "xmpp1.localhost.example=172.60.0.10"
+ - "conference.xmpp1.localhost.example=172.60.0.10"
+ - "xmpp2.localhost.example=172.60.0.20"
+ - "conference.xmpp2.localhost.example=172.60.0.20"
+ - "xmpp3.localhost.example=172.60.0.30"
+ - "conference.xmpp3.localhost.example=172.60.0.30"
+
+networks:
+ openfire-clustered-net:
+ driver: bridge
+ ipam:
+ driver: default
+ config:
+ - subnet: 172.60.0.0/24
+
diff --git a/cluster_mssql/nginx/nginx.conf b/cluster_mssql/nginx/nginx.conf
new file mode 100644
index 0000000..ab905c3
--- /dev/null
+++ b/cluster_mssql/nginx/nginx.conf
@@ -0,0 +1,85 @@
+# error_log stdout debug;
+
+stream {
+ upstream xmpp {
+ server 172.60.0.10:5222;
+ server 172.60.0.20:5222;
+ server 172.60.0.30:5222;
+ server [fd23:d79:d076::10]:5222;
+ server [fd23:d79:d076::20]:5222;
+ server [fd23:d79:d076::30]:5222;
+ }
+ server {
+ listen 55222;
+ tcp_nodelay on;
+ proxy_connect_timeout 10s;
+ proxy_timeout 12h; # Set this lower to be more flappy
+ proxy_pass xmpp;
+ }
+
+ upstream bosh {
+ server 172.60.0.10:7070;
+ server 172.60.0.20:7070;
+ server 172.60.0.30:7070;
+ server [fd23:d79:d076::10]:7070;
+ server [fd23:d79:d076::20]:7070;
+ server [fd23:d79:d076::30]:7070;
+ }
+ server {
+ listen 57070;
+ tcp_nodelay on;
+ proxy_connect_timeout 10s;
+ proxy_timeout 12h; # Set this lower to be more flappy
+ proxy_pass bosh;
+ }
+
+ upstream boshs {
+ server 172.60.0.10:7443;
+ server 172.60.0.20:7443;
+ server 172.60.0.30:7443;
+ server [fd23:d79:d076::10]:7443;
+ server [fd23:d79:d076::20]:7443;
+ server [fd23:d79:d076::30]:7443;
+ }
+ server {
+ listen 57443;
+ tcp_nodelay on;
+ proxy_connect_timeout 10s;
+ proxy_timeout 30s;
+ proxy_pass boshs;
+ }
+
+ upstream s2s {
+ server 172.60.0.10:5269;
+ server 172.60.0.20:5269;
+ server 172.60.0.30:5269;
+ server [fd23:d79:d076::10]:5269;
+ server [fd23:d79:d076::20]:5269;
+ server [fd23:d79:d076::30]:5269;
+ }
+ server {
+ listen 5269;
+ tcp_nodelay on;
+ proxy_connect_timeout 10s;
+ proxy_timeout 1m;
+ proxy_pass s2s;
+ }
+
+ upstream s2slegacy {
+ server 172.60.0.10:5270;
+ server 172.60.0.20:5270;
+ server 172.60.0.30:5270;
+ server [fd23:d79:d076::10]:5270;
+ server [fd23:d79:d076::20]:5270;
+ server [fd23:d79:d076::30]:5270;
+ }
+ server {
+ listen 5270;
+ tcp_nodelay on;
+ proxy_connect_timeout 10s;
+ proxy_timeout 1m;
+ proxy_pass s2slegacy;
+ }
+}
+
+events {}
diff --git a/cluster_mssql/plugins/hazelcast.jar b/cluster_mssql/plugins/hazelcast.jar
new file mode 100644
index 0000000..efc7837
Binary files /dev/null and b/cluster_mssql/plugins/hazelcast.jar differ
diff --git a/cluster_mssql/plugins/heapdump.jar b/cluster_mssql/plugins/heapdump.jar
new file mode 100644
index 0000000..3c3267e
Binary files /dev/null and b/cluster_mssql/plugins/heapdump.jar differ
diff --git a/cluster_mssql/plugins/jsxc.jar b/cluster_mssql/plugins/jsxc.jar
new file mode 100644
index 0000000..9449640
Binary files /dev/null and b/cluster_mssql/plugins/jsxc.jar differ
diff --git a/cluster_mssql/sql/init-db.sh b/cluster_mssql/sql/init-db.sh
new file mode 100755
index 0000000..5249fb1
--- /dev/null
+++ b/cluster_mssql/sql/init-db.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+SQLCMD="/opt/mssql-tools18/bin/sqlcmd"
+DB_HOST="db"
+
+# 1. Wait for SQL Server
+echo "Waiting for SQL Server to be ready..."
+until $SQLCMD -S tcp:$DB_HOST,1433 -U sa -P "$SA_PASSWORD" -Q "SELECT 1" -C &> /dev/null
+do
+ echo -n "."
+ sleep 1
+done
+echo "SQL Server is ready."
+
+# 2. Check if DB exists. If NOT, Restore.
+# We check sys.databases for 'openfire'
+DB_EXISTS=$($SQLCMD -S tcp:$DB_HOST,1433 -U sa -P "$SA_PASSWORD" -Q "IF DB_ID('openfire') IS NOT NULL PRINT 'YES'" -C -h -1 | tr -d '[:space:]')
+
+if [ "$DB_EXISTS" == "YES" ]; then
+ echo "Database 'openfire' already exists. Skipping restore."
+else
+ echo "Restoring 'openfire' database from backup..."
+
+ # RESTORE COMMAND
+ # We use WITH REPLACE to overwrite any conflicts and ensure it loads.
+ # Note: /init-scripts/ maps to your local ./sql folder via Docker Compose
+ $SQLCMD -S tcp:$DB_HOST,1433 -U sa -P "$SA_PASSWORD" \
+ -Q "RESTORE DATABASE [openfire] FROM DISK = '/init-scripts/openfire_initial.bak' WITH REPLACE" \
+ -C
+
+ echo "Restore completed."
+fi
\ No newline at end of file
diff --git a/cluster_mssql/sql/openfire_initial.bak b/cluster_mssql/sql/openfire_initial.bak
new file mode 100644
index 0000000..d026ad9
Binary files /dev/null and b/cluster_mssql/sql/openfire_initial.bak differ
diff --git a/cluster_mssql/start-db.sh b/cluster_mssql/start-db.sh
new file mode 100755
index 0000000..da9618e
--- /dev/null
+++ b/cluster_mssql/start-db.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+PROJECT="openfire"
+COMPOSE_FILE_COMMAND=("docker" "compose")
+COMPOSE_FILE_COMMAND+=("--env-file" "../_common/.env")
+COMPOSE_FILE_COMMAND+=("--project-name" "$PROJECT")
+
+
+# Where is this script? It could be called from anywhere, so use this to get full paths.
+SCRIPTPATH="$( cd "$(dirname "$0")"; pwd -P )"
+
+source "$SCRIPTPATH/../_common/functions.sh"
+
+
+
+echo "Starting a clustered environment."
+COMPOSE_FILE_COMMAND+=("-f" "docker-compose-db.yml")
+
+pushd "$SCRIPTPATH"
+
+"$SCRIPTPATH"/../stop.sh
+"${COMPOSE_FILE_COMMAND[@]}" pull --ignore-pull-failures
+
+# Clean up temporary persistence data
+if ! rm -rf _data; then
+ echo "ERROR: Failed to delete the _data directory. Try with sudo, then re-run." && popd && exit 1
+fi
+mkdir _data
+cp -r xmpp _data/
+cp -r plugins _data/
+
+"${COMPOSE_FILE_COMMAND[@]}" up -d || popd
+popd
\ No newline at end of file
diff --git a/cluster_mssql/start.sh b/cluster_mssql/start.sh
new file mode 100755
index 0000000..4b42d31
--- /dev/null
+++ b/cluster_mssql/start.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+usage() { echo "Usage: $0 [-n openfire-tag] [-6] [-h]
+ -n openfire-tag Launches all Openfire instances with the specified tag. This overrides the value in .env
+ -6 Replace standard IPv4-based bridge networking with IPv6.
+ -h Show this helpful information
+"; exit 0; }
+
+PROJECT="openfire"
+COMPOSE_FILE_COMMAND=("docker" "compose")
+COMPOSE_FILE_COMMAND+=("--env-file" "../_common/.env")
+COMPOSE_FILE_COMMAND+=("--project-name" "$PROJECT")
+
+NETWORK_COMPOSE_FILE="docker-compose-network-ipv4-only.yml"
+PREFER_IPV4="true"
+PREFER_IPV6="false"
+
+# Where is this script? It could be called from anywhere, so use this to get full paths.
+SCRIPTPATH="$( cd "$(dirname "$0")"; pwd -P )"
+
+source "$SCRIPTPATH/../_common/functions.sh"
+
+check_deps
+
+while getopts n:6h o; do
+ case "$o" in
+ n)
+ if [[ $OPTARG =~ " " ]]; then
+ echo "Docker tags cannot contain spaces"
+ exit 1
+ fi
+ echo "Using Openfire tag: $OPTARG"
+ export OPENFIRE_TAG="$OPTARG"
+ ;;
+ 6)
+ echo "Using IPv6"
+ NETWORK_COMPOSE_FILE="docker-compose-network-dualstack.yml"
+ PREFER_IPV4="false"
+ PREFER_IPV6="true"
+ ;;
+ h)
+ usage
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+export PREFER_IPV4
+export PREFER_IPV6
+
+echo "Starting a clustered environment."
+COMPOSE_FILE_COMMAND+=("-f" "docker-compose-clustered.yml")
+COMPOSE_FILE_COMMAND+=("-f" "$NETWORK_COMPOSE_FILE")
+
+pushd "$SCRIPTPATH"
+
+"$SCRIPTPATH"/../stop.sh
+"${COMPOSE_FILE_COMMAND[@]}" pull --ignore-pull-failures
+
+# Clean up temporary persistence data
+if ! rm -rf _data; then
+ echo "ERROR: Failed to delete the _data directory. Try with sudo, then re-run." && popd && exit 1
+fi
+mkdir _data
+cp -r xmpp _data/
+cp -r plugins _data/
+
+"${COMPOSE_FILE_COMMAND[@]}" up -d || popd
+popd
\ No newline at end of file
diff --git a/cluster_mssql/xmpp/1/conf/hazelcast-local-config.xml b/cluster_mssql/xmpp/1/conf/hazelcast-local-config.xml
new file mode 100644
index 0000000..dd30271
--- /dev/null
+++ b/cluster_mssql/xmpp/1/conf/hazelcast-local-config.xml
@@ -0,0 +1,60 @@
+
+
+
+ 5701
+
+ 0
+
+
+
+
+
+
+ 172.60.0.10
+ fd23:d79:d076:0:0:0:0:10
+
+
+
+
+
+ PBEWithMD5AndDES
+
+ thesalt
+
+ thepass
+
+ 19
+
+
+
diff --git a/cluster_mssql/xmpp/1/conf/openfire.xml b/cluster_mssql/xmpp/1/conf/openfire.xml
new file mode 100644
index 0000000..fde1caf
--- /dev/null
+++ b/cluster_mssql/xmpp/1/conf/openfire.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+ 9090
+ 9091
+
+ en
+
+
+
+
+
+ org.jivesoftware.database.DefaultConnectionProvider
+
+
+
+ com.microsoft.sqlserver.jdbc.SQLServerDriver
+ jdbc:sqlserver://db:1433;databaseName=openfire;encrypt=true;trustServerCertificate=true;
+ sa
+ MyStrongPassword1
+ select 1
+ false
+ false
+ PT0.5S
+ PT30S
+ PT15M
+ PT0.5S
+ 5
+ 25
+ 1.0
+
+
+ true
+ xmpp1.localhost.example
+
+ true
+
+
diff --git a/cluster_mssql/xmpp/1/conf/security.xml b/cluster_mssql/xmpp/1/conf/security.xml
new file mode 100644
index 0000000..4185021
--- /dev/null
+++ b/cluster_mssql/xmpp/1/conf/security.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+ Blowfish
+
+
+
+
+
+
+ database.defaultProvider.username
+ database.defaultProvider.password
+
+
+
+
diff --git a/cluster_mssql/xmpp/1/conf/security/archive/readme.txt b/cluster_mssql/xmpp/1/conf/security/archive/readme.txt
new file mode 100644
index 0000000..62573a5
--- /dev/null
+++ b/cluster_mssql/xmpp/1/conf/security/archive/readme.txt
@@ -0,0 +1 @@
+This directory is used as a default location in which Openfire stores backups of keystore files.
diff --git a/cluster_mssql/xmpp/1/conf/security/client.truststore b/cluster_mssql/xmpp/1/conf/security/client.truststore
new file mode 100644
index 0000000..c408465
Binary files /dev/null and b/cluster_mssql/xmpp/1/conf/security/client.truststore differ
diff --git a/cluster_mssql/xmpp/1/conf/security/keystore b/cluster_mssql/xmpp/1/conf/security/keystore
new file mode 100644
index 0000000..8ac6ed6
Binary files /dev/null and b/cluster_mssql/xmpp/1/conf/security/keystore differ
diff --git a/cluster_mssql/xmpp/1/conf/security/truststore b/cluster_mssql/xmpp/1/conf/security/truststore
new file mode 100644
index 0000000..cc04a65
Binary files /dev/null and b/cluster_mssql/xmpp/1/conf/security/truststore differ
diff --git a/cluster_mssql/xmpp/2/conf/hazelcast-local-config.xml b/cluster_mssql/xmpp/2/conf/hazelcast-local-config.xml
new file mode 100644
index 0000000..e800c4b
--- /dev/null
+++ b/cluster_mssql/xmpp/2/conf/hazelcast-local-config.xml
@@ -0,0 +1,60 @@
+
+
+
+ 5701
+
+ 0
+
+
+
+
+
+
+ fd23:d79:d076:0:0:0:0:20
+ 172.60.0.20
+
+
+
+
+
+ PBEWithMD5AndDES
+
+ thesalt
+
+ thepass
+
+ 19
+
+
+
diff --git a/cluster_mssql/xmpp/2/conf/openfire.xml b/cluster_mssql/xmpp/2/conf/openfire.xml
new file mode 100644
index 0000000..57422d2
--- /dev/null
+++ b/cluster_mssql/xmpp/2/conf/openfire.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+ 9090
+ 9091
+
+ en
+
+
+
+
+
+ org.jivesoftware.database.DefaultConnectionProvider
+
+
+
+ com.microsoft.sqlserver.jdbc.SQLServerDriver
+ jdbc:sqlserver://db:1433;databaseName=openfire;encrypt=true;trustServerCertificate=true;
+ sa
+ MyStrongPassword1
+ select 1
+ false
+ false
+ PT0.5S
+ PT30S
+ PT15M
+ PT0.5S
+ 5
+ 25
+ 1.0
+
+
+ true
+ xmpp2.localhost.example
+
+ true
+
+
diff --git a/cluster_mssql/xmpp/2/conf/security.xml b/cluster_mssql/xmpp/2/conf/security.xml
new file mode 100644
index 0000000..4185021
--- /dev/null
+++ b/cluster_mssql/xmpp/2/conf/security.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+ Blowfish
+
+
+
+
+
+
+ database.defaultProvider.username
+ database.defaultProvider.password
+
+
+
+
diff --git a/cluster_mssql/xmpp/2/conf/security/archive/readme.txt b/cluster_mssql/xmpp/2/conf/security/archive/readme.txt
new file mode 100644
index 0000000..62573a5
--- /dev/null
+++ b/cluster_mssql/xmpp/2/conf/security/archive/readme.txt
@@ -0,0 +1 @@
+This directory is used as a default location in which Openfire stores backups of keystore files.
diff --git a/cluster_mssql/xmpp/2/conf/security/client.truststore b/cluster_mssql/xmpp/2/conf/security/client.truststore
new file mode 100644
index 0000000..c408465
Binary files /dev/null and b/cluster_mssql/xmpp/2/conf/security/client.truststore differ
diff --git a/cluster_mssql/xmpp/2/conf/security/keystore b/cluster_mssql/xmpp/2/conf/security/keystore
new file mode 100644
index 0000000..8ac6ed6
Binary files /dev/null and b/cluster_mssql/xmpp/2/conf/security/keystore differ
diff --git a/cluster_mssql/xmpp/2/conf/security/truststore b/cluster_mssql/xmpp/2/conf/security/truststore
new file mode 100644
index 0000000..cc04a65
Binary files /dev/null and b/cluster_mssql/xmpp/2/conf/security/truststore differ
diff --git a/cluster_mssql/xmpp/3/conf/hazelcast-local-config.xml b/cluster_mssql/xmpp/3/conf/hazelcast-local-config.xml
new file mode 100644
index 0000000..f30017e
--- /dev/null
+++ b/cluster_mssql/xmpp/3/conf/hazelcast-local-config.xml
@@ -0,0 +1,60 @@
+
+
+
+ 5701
+
+ 0
+
+
+
+
+
+
+ fd23:d79:d076:0:0:0:0:30
+ 172.60.0.30
+
+
+
+
+
+ PBEWithMD5AndDES
+
+ thesalt
+
+ thepass
+
+ 19
+
+
+
diff --git a/cluster_mssql/xmpp/3/conf/openfire.xml b/cluster_mssql/xmpp/3/conf/openfire.xml
new file mode 100644
index 0000000..10b057a
--- /dev/null
+++ b/cluster_mssql/xmpp/3/conf/openfire.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+ 9090
+ 9091
+
+ en
+
+
+
+
+
+ org.jivesoftware.database.DefaultConnectionProvider
+
+
+
+ com.microsoft.sqlserver.jdbc.SQLServerDriver
+ jdbc:sqlserver://db:1433;databaseName=openfire;encrypt=true;trustServerCertificate=true;
+ sa
+ MyStrongPassword1
+ select 1
+ false
+ false
+ PT0.5S
+ PT30S
+ PT15M
+ PT0.5S
+ 5
+ 25
+ 1.0
+
+
+ true
+ xmpp3.localhost.example
+
+ true
+
+
diff --git a/cluster_mssql/xmpp/3/conf/security.xml b/cluster_mssql/xmpp/3/conf/security.xml
new file mode 100644
index 0000000..4185021
--- /dev/null
+++ b/cluster_mssql/xmpp/3/conf/security.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+ Blowfish
+
+
+
+
+
+
+ database.defaultProvider.username
+ database.defaultProvider.password
+
+
+
+
diff --git a/cluster_mssql/xmpp/3/conf/security/archive/readme.txt b/cluster_mssql/xmpp/3/conf/security/archive/readme.txt
new file mode 100644
index 0000000..62573a5
--- /dev/null
+++ b/cluster_mssql/xmpp/3/conf/security/archive/readme.txt
@@ -0,0 +1 @@
+This directory is used as a default location in which Openfire stores backups of keystore files.
diff --git a/cluster_mssql/xmpp/3/conf/security/client.truststore b/cluster_mssql/xmpp/3/conf/security/client.truststore
new file mode 100644
index 0000000..c408465
Binary files /dev/null and b/cluster_mssql/xmpp/3/conf/security/client.truststore differ
diff --git a/cluster_mssql/xmpp/3/conf/security/keystore b/cluster_mssql/xmpp/3/conf/security/keystore
new file mode 100644
index 0000000..8ac6ed6
Binary files /dev/null and b/cluster_mssql/xmpp/3/conf/security/keystore differ
diff --git a/cluster_mssql/xmpp/3/conf/security/truststore b/cluster_mssql/xmpp/3/conf/security/truststore
new file mode 100644
index 0000000..cc04a65
Binary files /dev/null and b/cluster_mssql/xmpp/3/conf/security/truststore differ