Configuring WildFly as Reverse Proxy

TL;DR: In WildFly 41, Undertow serves as a non-blocking, high-throughput reverse proxy capable of routing requests to backend microservices, legacy EAP instances, or external APIs. You can set it up dynamically via JBoss CLI by defining an outbound-socket-binding, registering a reverse-proxy handler with http/https schemes, and mapping it to a virtual host path location. For cloud and Kubernetes environments, always configure client IP forwarding (proxy-address-forwarding="true") and backend TLS verification via Elytron SSL contexts.

In enterprise deployments, routing incoming client requests through an intermediary layer is essential for isolating application clusters, balancing workloads, and enforcing centralized security policies. While dedicated ingress gateways like NGINX, Envoy, or HAProxy are commonly deployed at perimeter edges, WildFly 41 can act as a fully capable, low-latency Reverse Proxy directly through its embedded Undertow engine.

This allows architects to eliminate redundant infrastructure components, consolidate Java middleware management under a single administrative model (JBoss CLI / HAL Console), and route traffic across legacy monoliths and containerized microservices seamlessly.


Reverse Proxy vs. Forward Proxy

Before configuring Undertow's handler pipeline, it is important to distinguish the roles:

  • Forward Proxy: Sits in front of internal clients to manage, cache, or inspect outbound access to external networks (the internet). The client explicitly knows about the proxy.
  • Reverse Proxy: Sits in front of backend origin servers. To external clients, the reverse proxy appears as the authoritative server. It intercepts incoming requests and dispatches them across backend services, remaining transparent to clients.

Typical production use cases include:

  • Unified URL Namespace: Aggregating disparate backend systems (e.g., Quarkus microservices, Node.js frontends, legacy WildFly deployments) under a single host domain.
  • Security Boundary & TLS Offloading: Terminating public HTTPS traffic at the perimeter and routing internal traffic over private cloud networks.
  • Layer 7 Routing & Load Balancing: Distributing client requests across clustered worker nodes with sticky session tracking.

1. Configuring Undertow Reverse Proxy via JBoss CLI

In modern WildFly architectures, we route traffic using standard HTTP/1.1 or HTTP/2 over the wire. Let us configure a scenario where incoming requests to /api are forwarded to an internal backend service running at internal-api.service.local:8080.

Step 1: Define the Remote Outbound Socket Binding

The outbound socket binding defines the physical target hostname (or IP) and destination port:

/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=backend-api:add(host="internal-api.service.local", port=8080)

Step 2: Create the Reverse Proxy Handler

Register the reverse-proxy handler inside Undertow's configuration. We define a connection-idle-timeout (in seconds), maximum connection request limits, and standard session affinity cookies:

/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy:add(connection-idle-timeout=60, max-request-time=30000, session-cookie-names="JSESSIONID,SESSION")

Step 3: Register the Target Backend Node

Attach the outbound socket binding to your reverse proxy handler. In WildFly 41, prefer the http or https scheme:

/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy/host=backend-node1:add(outbound-socket-binding=backend-api, scheme=http, instance-id=node1, path="/api")
Protocol Recommendation (AJP vs HTTP/HTTPS): While Undertow still supports the legacy ajp scheme for backward compatibility with Apache mod_jk/mod_proxy_ajp, contemporary architectures favor http or https. AJP lacks native TLS encryption, does not support HTTP/2 or gRPC, and presents unnecessary operational risks in zero-trust environments.

Step 4: Map the Handler to Undertow Virtual Host

Finally, bind the handler to the desired path location within your default virtual host:

/subsystem=undertow/server=default-server/host=default-host/location=\/api:add(handler=ApiProxy)

2. Resulting XML Configuration Breakdown

Executing the CLI commands above updates your standalone.xml (under urn:jboss:domain:undertow:14.0 or later):

<subsystem xmlns="urn:jboss:domain:undertow:14.0" default-virtual-host="default-host" default-servlet-container="default" default-server="default-server">
    <server name="default-server">
        <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
        <https-listener name="https" socket-binding="https" ssl-context="applicationSSC" enable-http2="true"/>
        
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <!-- Reverse proxy mapping -->
            <location name="/api" handler="ApiProxy"/>
            <http-invoker http-authentication-factory="application-http-authentication"/>
        </host>
    </server>

    <handlers>
        <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
        <reverse-proxy name="ApiProxy" session-cookie-names="JSESSIONID,SESSION" connection-idle-timeout="60" max-request-time="30000">
            <host name="backend-node1" outbound-socket-binding="backend-api" scheme="http" instance-id="node1" path="/api"/>
        </reverse-proxy>
    </handlers>
</subsystem>

And under the <socket-binding-group> element:

<outbound-socket-binding name="backend-api">
    <remote-destination host="internal-api.service.local" port="8080"/>
</outbound-socket-binding>

3. Cloud-Native & Containerized Considerations (WildFly 41)

Running WildFly as a reverse proxy in cloud containers (Kubernetes, Red Hat OpenShift, AWS ECS, or Docker Compose) introduces specific operational challenges that do not exist on bare metal:

A. Proxy Address Forwarding (Preserving Real Client IPs)

When WildFly runs behind cloud load balancers (AWS ALB, Kubernetes Ingress, Traefik), the reverse proxy must know the original client IP and protocol rather than the cluster load balancer's internal IP. Enable address forwarding on your HTTP/HTTPS listeners:

/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding, value=true)
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=proxy-address-forwarding, value=true)

This instructs Undertow to inspect and honor incoming X-Forwarded-For, X-Forwarded-Proto, and standard RFC 7239 Forwarded headers, passing them cleanly downstream to your backend targets.

B. Dynamic DNS Resolution & Kubernetes Services

In Kubernetes, backend Pod IPs are ephemeral and subject to frequent rolling updates. If you point your outbound socket binding to a Kubernetes Service DNS name (e.g., customer-service.default.svc.cluster.local), you must configure DNS resolution behavior properly:

  • JVM DNS TTL: By default, the JVM may cache DNS lookups indefinitely. In container environments, set network address cache TTL in $JAVA_HOME/conf/security/java.security:
    networkaddress.cache.ttl=10
    networkaddress.cache.negative.ttl=5
  • Dynamic Peer Hosts: When routing to upstream targets whose hostnames resolve to multiple changing IP endpoints, enable host resolution refreshes in Undertow to prevent stale connection socket failures.

C. Secure Backend Communications via Elytron SSL Context

In zero-trust enterprise meshes, traffic between the reverse proxy and internal backends must remain encrypted. In WildFly 41, configure secure upstream connections with the https scheme coupled with an Elytron client SSL context:

/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy/host=backend-node1:write-attribute(name=scheme, value=https)
/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy/host=backend-node1:write-attribute(name=ssl-context, value=clientSSLContext)

This ensures certificates presented by backend servers are verified against a dedicated truststore managed within WildFly's Elytron subsystem.

D. Connection Pooling & Resource Throttling

In high-concurrency microservice ecosystems, preventing thread starvation and connection saturation is vital. Tune your reverse proxy handler's pooling parameters:

/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy:write-attribute(name=connections-per-thread, value=30)
/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy:write-attribute(name=max-request-time, value=25000)
/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy:write-attribute(name=request-queue-size, value=100)

4. Load Balancing Across Clustered Backends

Undertow’s reverse proxy handler can balance load across multiple backend nodes with sticky session affinity. Simply register multiple host elements under the same reverse proxy handler:

# Register node 2 outbound socket
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=backend-api-node2:add(host="10.0.1.25", port=8080)

# Attach node 2 to reverse-proxy handler
/subsystem=undertow/configuration=handler/reverse-proxy=ApiProxy/host=backend-node2:add(outbound-socket-binding=backend-api-node2, scheme=http, instance-id=node2, path="/api")

Undertow parses the session identifier cookie (e.g., JSESSIONID.node1) to pin subsequent client requests to the active target node, failing over automatically if a node becomes unresponsive.


Summary & Best Practices

  • Migrate Away from AJP: For modern architectures in WildFly 41, use http or https instead of ajp to leverage HTTP/2 and modern TLS capabilities.
  • Always Enable proxy-address-forwarding: Essential in cloud, container, and Kubernetes deployments to prevent losing caller origin data.
  • Set Aggressive Connection Timeouts: Use connection-idle-timeout and max-request-time to free idle client connections and protect your worker thread pools.
  • Zero-Trust Internal TLS: Secure sensitive downstream communications by attaching an Elytron ssl-context to backend host definitions.

Recommended Articles

Enhance Your Java Applications with JBoss Undertow: A Comprehensive Guide

Learn how to embed JBoss Undertow in your applications and leverage its high-performance features for better web server capabilities. #Java #Middleware #CloudNative

Undertow Migration Guide: Mapping JBoss Web Valves to Undertow Handlers

Easily migrate JBoss Web valves to Undertow handlers for improved performance. Learn about key mappings here.

Create a Custom Undertow Handler for WildFly using Java

Learn how to create a custom Undertow handler in Java, package it as a WildFly module, and deploy it on WildFly.

Configure Undertow Filters on WildFly 31 for Custom HTTP Handling

Learn how to create a custom Undertow Filter in WildFly 31, including connection limit and gzip filters, and implement your own filter for capturing HostName requests.