Configure Tomcat to Find Proxy Headers
Steps
Behind a reverse proxy, every request reaches Tomcat from the proxy over plain HTTP, so that is what Tomcat reports: the proxy's address as the client address, and http as the protocol. Tomcat's RemoteIpValve makes it read the headers the proxy adds instead, and report what the reader actually sent. XWiki does not depend on it, since it reads those same headers itself when it builds URLs, but everything that asks the container rather than XWiki does: Tomcat's own access log, and any code calling getRemoteAddr, getScheme or isSecure.
- Set up a reverse proxy that sends the forwarded headers, following Configure Apache HTTP Server as a Proxy on a Linux OS or Set up NginX Proxy Server.
- Open the TOMCAT_HOME/conf/server.xml file.
- Add the valve directly inside the Engine element:
<Engine name="Catalina" defaultHost="localhost"> <Valve className="org.apache.catalina.valves.RemoteIpValve" /> </Engine> - If the proxy runs on another machine, add an internalProxies attribute that its address matches, for example
internalProxies="203\.0\.113\.7". The value replaces the default, which covers the loopback and the private address ranges and is why the valve above needs nothing when the proxy sits on the same host, so the expression has to match every proxy the wiki is served through. Tomcat 10.1 reads the attribute as a regular expression; Tomcat 11 also accepts a list of CIDR blocks, for exampleinternalProxies="203.0.113.7/32", and deprecates the regular expression form. - Add requestAttributesEnabled="true" to the AccessLogValve element of the host, further down the same file, so that the access log uses what the valve found rather than the connection the request arrived on. This is the one place the attribute has to be written out: it defaults to false there and to true on the valve above.
- Restart Tomcat.
- Open a wiki page through the proxy. In the access log under TOMCAT_HOME/logs/, for example localhost_access_log.2026-08-17.txt, the first field of that request is now the reader's address instead of the proxy's, and the wiki keeps generating the links it already generated.
FAQ
Do I need this for the wiki to generate HTTPS links?
No. XWiki reads the Forwarded, X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-For headers itself and builds its URLs from them, with no container-side configuration at all. If links are still plain HTTP, the cause is elsewhere: the proxy is not sending X-Forwarded-Proto, or xwiki.home and xwiki.url.protocol in the xwiki.cfg configuration file name http. Configure this valve so that Tomcat's own view of the request matches, not to fix the wiki's links.
Why is the logged client address still the proxy's?
Either the proxy's address does not match internalProxies, so the valve leaves the header alone, or the access log is not using what the valve found: AccessLogValve needs requestAttributesEnabled="true" as well.
Which attributes does the valve need?
Only className. Tomcat already reads x-forwarded-for as remoteIpHeader, X-Forwarded-Proto as protocolHeader and https as protocolHeaderHttpsValue, and requestAttributesEnabled is already true on the valve, so writing any of the four out changes nothing. hostHeader and portHeader are the attributes that default to nothing: set them to x-forwarded-host and x-forwarded-port if the host and port Tomcat reports must match the public ones too, and have the proxy send the port, which neither the NginX nor the Apache block does on its own. See the Remote IP Valve documentation.
Is the same configuration needed on Jetty?
No. XWiki's Jetty distributions enable Jetty's forwarded module, which processes the Forwarded header and its X-Forwarded-* predecessors, so nothing has to be added there.