[[mod_cluster_Subsystem]]
= mod_cluster Subsystem

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

The mod_cluster integration is provided by the `org.wildfly.extension.mod_cluster` extension and the `modcluster` subsystem.

For more information about the project visit the https://www.modcluster.io/[project website (modcluster.io)] and the https://docs.modcluster.io/[documentation website (docs.modcluster.io)].

[[mod_cluster_subsystem_configuration]]
== Configuration

[[instance-id-or-jvmroute]]
=== Instance ID

The `instance-id` (also called `jvmRoute` in the JBoss Web / Tomcat nomenclature) defaults to the `jboss.node.name` property passed on server startup (e.g. via `-Djboss.node.name=myroute`).

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=undertow:read-attribute(name=instance-id)
{
    "outcome" => "success",
    "result" => expression "${jboss.node.name}"
}
----

To configure `instance-id` statically, configure the corresponding attribute in the Undertow subsystem:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=undertow:write-attribute(name=instance-id, value=myroute)
{
    "outcome" => "success",
    "response-headers" => {
        "operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}

[standalone@localhost:9990 /] reload
----

[[proxies]]
=== Proxies

By default, mod_cluster is configured for discovery based on UDP Multicast.
To specify a static list of proxies, create a `remote-socket-binding` for each proxy and then reference them by the `proxies` attribute.
See the following configuration example:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=proxy1:add(host=10.21.152.86, port=6666)
{"outcome" => "success"}

[standalone@localhost:9990 /] /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=proxy2:add(host=10.21.152.87, port=6666)
{"outcome" => "success"}

[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:write-attribute(name=proxies, value=[proxy1, proxy2])
{
    "outcome" => "success",
    "response-headers" => {
        "operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}

[standalone@localhost:9990 /] reload
----

=== Multiple mod_cluster Configurations

Since WildFly 14 mod_cluster subsystem supports multiple named proxy configurations also allowing for registering
non-default Undertow servers with the reverse proxies. Moreover, this allows single application server node to register with
different groups of proxy servers.

See the following example which adds another Undertow AJP listener, server and a host and adds a new mod_cluster configuration
which registers this host using advertise mechanism.

[source,options="nowrap"]
----
/socket-binding-group=standard-sockets/socket-binding=ajp-other:add(port=8010)
/subsystem=undertow/server=other-server:add
/subsystem=undertow/server=other-server/ajp-listener=ajp-other:add(socket-binding=ajp-other)
/subsystem=undertow/server=other-server/host=other-host:add(default-web-module=root-other.war)
/subsystem=undertow/server=other-server/host=other-host/location=other:add(handler=welcome-content)
/subsystem=undertow/server=other-server/host=other-host:write-attribute(name=alias, value=[localhost])
/socket-binding-group=standard-sockets/socket-binding=modcluster-other:add(multicast-address=224.0.1.106, multicast-port=23364)
/subsystem=modcluster/proxy=other:add(advertise-socket=modcluster-other, balancer=other-balancer, listener=ajp-other)
reload
----

[[runtime-operations]]
== Runtime Operations

The mod_cluster subsystem supports several runtime operations on the proxy:

* add-proxy
* disable
* disable-context
* enable
* enable-context
* query
* read-proxies-configuration
* read-proxies-info
* refresh
* remove-proxy
* reset
* stop
* stop-context

The operations specific to the mod_cluster subsystem are divided into 3 categories:

* ones that affect the configuration and require a restart of the subsystem
* ones that just modify the behaviour temporarily,
* and the ones that display information from the proxy.

[[operations-displaying-httpd-informations]]
=== Operations displaying reverse proxy information

There are 2 operations that display how the proxy sees the node:

[[read-proxies-configuration]]
==== read-proxies-configuration

Sends a `DUMP` message to all reverse proxies the node is connected to, and displays the message received from them.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:read-proxies-configuration
{
    "outcome" => "success",
    "result" => [
        "neo3:6666",
        "balancer: [1] Name: mycluster Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 1 Timeout: 0 Maxtry: 1
node: [1:1],Balancer: mycluster,JVMRoute: 498bb1f0-00d9-3436-a341-7f012bc2e7ec,Domain: [],Host: 127.0.0.1,Port: 8080,Type: http,flushpackets: 0,flushwait: 10,ping: 10,smax: 26,ttl: 60,timeout: 0
host: 1 [example.com] vhost: 1 node: 1
host: 2 [localhost] vhost: 1 node: 1
host: 3 [default-host] vhost: 1 node: 1
context: 1 [/myapp] vhost: 1 node: 1 status: 1
context: 2 [/] vhost: 1 node: 1 status: 1
",
        "jfcpc:6666",
        "balancer: [1] Name: mycluster Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 1 Timeout: 0 maxAttempts: 1
node: [1:1],Balancer: mycluster,JVMRoute: 498bb1f0-00d9-3436-a341-7f012bc2e7ec,LBGroup: [],Host: 127.0.0.1,Port: 8080,Type: http,flushpackets: 0,flushwait: 10,ping: 10,smax: 26,ttl: 60,timeout: 0
host: 1 [default-host] vhost: 1 node: 1
host: 2 [localhost] vhost: 1 node: 1
host: 3 [example.com] vhost: 1 node: 1
context: 1 [/] vhost: 1 node: 1 status: 1
context: 2 [/myapp] vhost: 1 node: 1 status: 1
"
    ]
}
----

[[read-proxies-info]]
==== read-proxies-info

Sends an `INFO` message to all reverse proxies the node is connected to, and displays the message received from them.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:read-proxies-info
{
    "outcome" => "success",
    "result" => [
        "neo3:6666",
        "Node: [1],Name: 498bb1f0-00d9-3436-a341-7f012bc2e7ec,Balancer: mycluster,Domain: ,Host: 127.0.0.1,Port: 8080,Type: http,Flushpackets: Off,Flushwait: 10000,Ping: 10000000,Smax: 26,Ttl: 60000000,Elected: 0,Read: 0,Transfered: 0,Connected: 0,Load: -1
Vhost: [1:1:1], Alias: example.com
Vhost: [1:1:2], Alias: localhost
Vhost: [1:1:3], Alias: default-host
Context: [1:1:1], Context: /myapp, Status: ENABLED
Context: [1:1:2], Context: /, Status: ENABLED
",
        "jfcpc:6666",
        "Node: [1],Name: 498bb1f0-00d9-3436-a341-7f012bc2e7ec,Balancer: mycluster,LBGroup: ,Host: 127.0.0.1,Port: 8080,Type: http,Flushpackets: Off,Flushwait: 10,Ping: 10,Smax: 26,Ttl: 60,Elected: 0,Read: 0,Transfered: 0,Connected: 0,Load: 1
Vhost: [1:1:1], Alias: default-host
Vhost: [1:1:2], Alias: localhost
Vhost: [1:1:3], Alias: example.com
Context: [1:1:1], Context: /, Status: ENABLED
Context: [1:1:2], Context: /myapp, Status: ENABLED
"
    ]
}
----

[[operations-that-handle-the-proxies-the-node-is-connected-too]]
==== Operations that handle the proxies the node is connected to

There are 3 operations that could be used to manipulate the list of reverse proxies the node is connected to.

[[list-proxies]]
==== list-proxies

Displays the reverse proxies that are connected to the node.
The proxies are either discovered by the advertise mechanism or by the configured `proxies` attribute.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:list-proxies
{
    "outcome" => "success",
    "result" => [
        "proxy1:6666",
        "proxy2:6666"
    ]
}
----

[[add-proxy]]
==== add-proxy

Adds a proxy to the discovered proxies at runtime without persisting to the server configuration:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:add-proxy(host=localhost, port=8090)
{"outcome" => "success"}
----

[[remove-proxy]]
==== remove-proxy

Removes a proxy from the discovered proxies at runtime without persisting to the server configuration:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:remove-proxy(host=localhost, port=8090)
{"outcome" => "success"}
----

[[context-related-operations]]
=== Context related operations

These operations allow you to send context related commands to the reverse proxies.
These are also issued automatically when deploying or un-deploying webapps.

[[enable-context]]
==== enable-context

Informs reverse proxies that the given web context is ready receive requests.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:enable-context(context=/myapp, virtualhost=default-host)
{"outcome" => "success"}
----

[[disable-context]]
==== disable-context

Informs reverse proxies that they should not send any new session requests to the specified web context.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:disable-context(context=/myapp, virtualhost=default-host)
{"outcome" => "success"}
----

[[stop-context]]
==== stop-context

Informs reverse proxies that they should not send requests to the web context.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:stop-context(context=/myapp, virtualhost=default-host, waittime=50)
{"outcome" => "success"}
----

[[node-related-operations]]
=== Node related operations

Those operations are like the context operation but they apply to all
webapps running on the node and operation that affect the whole node.

[[refresh]]
==== refresh

Refreshes the node by sending a new `CONFIG` message to the reverse proxies.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=modcluster/proxy=default:refresh
{"outcome" => "success"}
----

[[reset]]
==== reset

Reset the connection between the reverse proxy and the node.

include::SSL_Configuration_using_Elytron_Subsystem.adoc[leveloffset=+1]

== Remote User Authentication with Elytron

It is possible to accept a `REMOTE_USER` already authenticated by the Apache httpd server with Elytron via the AJP protocol.
This can be done by setting up Elytron to secure a WildFly deployment and specifying for the External HTTP mechanism to
be used. This is done by creating a security domain and specifying the External mechanism as one of the mechanism
configurations to be used by the `http-authentication-factory`:

----
/subsystem=elytron/http-authentication-factory=web-tests:add(security-domain=example-domain, http-server-mechanism-factory=example-factory, mechanism-configurations=[{mechanism-name=EXTERNAL}])
----

Elytron will accept the externally authenticated user and use the specified security domain to perform role mapping to
complete authorization.
