Skip to content

Java behind IIS or Nginx: proxy headers, WebSocket and memory

Verified 1 min read

Put Tomcat behind IIS ARR or Nginx, forward the real host/proto/client IP, keep WebSocket alive, and size the JVM instead of guessing.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

Terminate TLS at IIS/Nginx, proxy to Tomcat on 127.0.0.1:8080:

  • forward Host, X-Forwarded-For, X-Forwarded-Proto;
  • configure Tomcat’s RemoteIpValve so the app sees the client, not the proxy;
  • allow WebSocket upgrades and long read timeouts;
  • size the JVM (-Xms/-Xmx) and Tomcat threads separately.
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}

WebSocket:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;

map $http_upgrade $connection_upgrade goes in the http block.

  • Create a server farm pointing at 127.0.0.1:8080.
  • Preserve Host; forward X-Forwarded-For/X-Forwarded-Proto.
  • Increase proxy timeout for long requests; enable WebSocket if needed.
  • Do not expose Tomcat’s 8080 directly to the internet.

Enable RemoteIpValve in server.xml (inside the Host):

<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
protocolHeader="x-forwarded-proto"
protocolHeaderHttpsValue="https" />

Without it, request.getRemoteAddr() returns 127.0.0.1, and request.isSecure() may be false unless the connector is configured for scheme="https".

Terminal window
set "JAVA_OPTS=-Xms1g -Xmx1g -XX:+UseG1GC"
  • Set -Xms = -Xmx for a server with dedicated memory; avoids heap growth pauses.
  • Leave headroom for Metaspace, thread stacks, direct buffers and the OS.
  • Tomcat maxThreads is request concurrency, not heap. Raising threads does not fix a memory leak.
  • Check GC logs and jcmd <pid> GC.heap_info before changing numbers.
Terminal window
curl.exe -I https://lab.example/
Get-Content C:\tomcat\logs\localhost.*.log -Tail 50
jcmd <pid> VM.system_properties | Select-String "java.home|java.version"

Check the app logs the real client IP and https scheme; check the JVM is the pinned JDK.

E1. The lab did not run Tomcat or a Java app; the configuration is the proxy pattern to verify on Server 2025.

Sources