=== Setting Up a Load Balancer or Proxy This section discusses a number of things you need to configure before you can put a reverse proxy or load balancer in front of your clustered {{book.project.name}} deployment. It also covers configuring the built in load balancer that was <>. ==== Identifying Client IP Addresses A few features in {{book.project.name}} rely on the fact that the remote address of the HTTP client connecting to the authentication server is the real IP address of the client machine. This can be problematic when you have a reverse proxy or loadbalancer in front of your {{book.project.name}} authentication server. The usual setup is that you have a frontend proxy sitting on a public network that load balances and forwards requests to backend {{book.project.name}} server instances located in a private network. There is some extra configuration you have to do in this scenario so that the actual client IP address is forwarded to and processed by the {{book.project.name}} server instances. Specifically: * Configure your reverse proxy or loadbalancer to properly set `X-Forwarded-For` and `X-Forwarded-Proto` HTTP headers. * Configure your reverse proxy or loadbalancer to preserve the original 'Host' HTTP header. * Configure the authentication server to read the client's IP address from `X-Forwarded-For header`. Configuring your proxy to generate the `X-Forwarded-For` and `X-Forwarded-Proto` HTTP headers and preserving the original `Host` HTTP header is beyond the scope of this guide. Take extra precautions to ensure that the `X-Forwared-For` header is set by your proxy. If your proxy isn't configured correctly, then _rogue_ clients can set this header themselves and trick {{book.project.name}} into thinking the client is connecting from a different IP address than it actually is. This becomes really important if you are doing any black or white listing of IP addresses. Beyond the proxy itself, there are a few things you need to configure on the {{book.project.name}} side of things. If your proxy is forwarding requests via the HTTP protocol, then you need to configure {{book.project.name}} to pull the client's IP address from the `X-Forwarded-For` header rather than from the network packet. To do this, open up the profile configuration file (_standalone.xml_, _standalone-ha.xml_, or _domain.xml_ depending on your <>) and look for the `"urn:jboss:domain:undertow:3.0` XML block. .`X-Forwarded-For` HTTP Config [source,xml] ---- ... ... ---- Add the `proxy-address-forwarding` attribute to the `http-listener` element. Set the value to `true`. If your proxy is using the AJP protocol instead of HTTP to forward requests (i.e. Apache HTTPD + mod-cluster), then you have to configure things a little differently. Instead of modifying the `http-listener`, you need to add a filter to pull this information from the AJP packets. .`X-Forwarded-For` AJP Config [source,xml] ---- ... ... ... ---- ==== Enable HTTPS/SSL with a Reverse Proxy Assuming that your reverse proxy doesn't use port 8443 for SSL you also need to configure what port HTTPS traffic is redirected to. [source,xml] ---- ... ... ---- Add the `redirect-socket` attribute to the `http-listener` element. The value should be `proxy-https` which points to a socket binding you also need to define. Then add a new `socket-binding` element to the `socket-binding-group` element: [source,xml] ---- ... ... ---- ==== Verify Configuration You can verify the reverse proxy or load balancer configuration by opening the path `/auth/realms/master/.well-known/openid-configuration` through the reverse proxy. For example if the reverse proxy address is `https://acme.com/` then open the URL `https://acme.com/auth/realms/master/.well-known/openid-configuration`. This will show a JSON document listing a number of endpoints for {{book.project.name}}. Make sure the endpoints starts with the address (scheme, domain and port) of your reverse proxy or load balancer. By doing this you make sure that {{book.project.name}} is using the correct endpoint. You should also verify that {{book.project.name}} sees the correct source IP address for requests. Do check this you can try to login to the admin console with an invalid username and/or password. This should show a warning in the server log something like this: [source] ---- 08:14:21,287 WARN XNIO-1 task-45 [org.keycloak.events] type=LOGIN_ERROR, realmId=master, clientId=security-admin-console, userId=8f20d7ba-4974-4811-a695-242c8fbd1bf8, ipAddress=X.X.X.X, error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, redirect_uri=http://localhost:8080/auth/admin/master/console/?redirect_fragment=%2Frealms%2Fmaster%2Fevents-settings, code_id=a3d48b67-a439-4546-b992-e93311d6493e, username=admin ---- Check that the value of `ipAddress` is the IP address of the machine you tried to login with and not the IP address of the reverse proxy or load balancer. ==== Using the Built-In Load Balancer This section covers configuring the built in load balancer that is discussed in the <>. The <> is only designed to run on one machine. To bring up a slave on another host, you'll need to . Edit the _domain.xml_ file to point to your new host slave . Copy the server distribution. You don't need the _domain.xml_, _host.xml_, or _host-master.xml_ files. Nor do you need the _standalone/_ directory. . Edit the _host-slave.xml_ file to change the bind addresses used or override them on the command line ===== Register a New Host With Load Balancer Let's look first at registering the new host slave with the load balancer configuration in _domain.xml_. Open this file and go to the undertow configuration in the `load-balancer` profile. Add a new `host` definition called `remote-host3` within the `reverse-proxy` XML block. .domain.xml reverse-proxy config [source,xml] ---- ... ... ---- The `output-socket-binding` is a logical name pointing to a `socket-binding` configured later in the _domain.xml_ file. the `instance-id` attribute must also be unique to the new host as this value is used by a cookie to enable sticky sessions when load balancing. Next go down to the `load-balancer-sockets` `socket-binding-group` and add the `outbound-socket-binding` for `remote-host3`. This new binding needs to point to the host and port of the new host. .domain.xml outbound-socket-binding [source,xml] ---- ... ---- ===== Master Bind Addresses Next thing you'll have to do is to change the `public` and `management` bind addresses for the master host. Either edit the _domain.xml_ file as discussed in the <> chapter or specify these bind addresses on the command line as follows: [source] ---- $ domain.sh --host-config=host-master.xml -Djboss.bind.address=192.168.0.2 -Djboss.bind.address.management=192.168.0.2 ---- ===== Host Slave Bind Addresses Next you'll have to change the `public`, `management`, and domain controller bind addresses (`jboss.domain.master-address`). Either edit the _host-slave.xml_ file or specify them on the command line as follows: [source] ---- $ domain.sh --host-config=host-slave.xml -Djboss.bind.address=192.168.0.5 -Djboss.bind.address.management=192.168.0.5 -Djboss.domain.master.address=192.168.0.2 ---- The values of `jboss.bind.address` and `jboss.bind.addres.management` pertain to the host slave's IP address. The value of `jboss.domain.master.address` need to be the IP address of the domain controller which is the management address of the master host. ==== Configuring Other Load Balancers See link:{{book.appserver.doc_base_url}}{{book.appserver.version}}{{book.appserver.loadbalancer_ref.link}}[{{book.appserver.loadbalancer_ref.name}}] in the _{{book.appserver.admindoc.name}}_ for information how to use other software-based load balancers.