Configure XWiki in Docker Behind a Reverse Proxy

Last modified by Vincent Massol on 2026/07/27 15:24

Steps

To serve XWiki through a reverse proxy, make the proxy send the forwarded headers and declare a RemoteIpValve in the Tomcat bundled in the XWiki image, so that it trusts them. HTTPS for XWiki in Docker explains why the valve is needed and what XWiki generates without it.

  1. Set up the reverse proxy and its TLS certificate, following HTTP Reverse Proxy for XWiki.
  2. Forward the proxy to port 8080 of the XWiki container. A proxy running as a container on the same Docker network reaches it by container name, for example http://xwiki:8080/, without any port being published on the host, while a proxy running on the host itself reaches it on the loopback address.
  3. Configure the proxy to send the forwarded headers, since the valve has nothing to read otherwise. With Nginx, for instance, as follows:
    proxy_set_header Host              $host;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  4. Create a context.xml file on your host, declaring the valve alongside the entries that the context.xml of the image already has, as follows:
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
        <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
        <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    
        <Valve className="org.apache.catalina.valves.RemoteIpValve"
               remoteIpHeader="x-forwarded-for"
               protocolHeader="x-forwarded-proto"/>
    </Context>
  5. Mount that file over the one in the image, with -v /my/xwiki/config/path/context.xml:/usr/local/tomcat/conf/context.xml for docker run, or with a volume on the web service for docker compose, as follows:
        volumes:
          - ./context.xml:/usr/local/tomcat/conf/context.xml
  6. Stop publishing port 8080 on the host, so that the wiki is reachable only through the proxy: remove -p 8080:8080 from the docker run command, or the ports entry of the web service in docker-compose.yml. When the proxy runs on the host rather than in a container, publish the port on the loopback address only, with -p 127.0.0.1:8080:8080.
  7. Restart the container to apply the new Tomcat configuration.
  8. Browse the wiki through the address of the proxy and verify that the generated links and the redirects carry the public scheme, host name and port, and that the access log of the proxy shows the real client addresses.

FAQ

Does the valve cause any harm when no reverse proxy is in front?

No. A RemoteIpValve rewrites a request only when that request carries the X-Forwarded-* headers and comes from a trusted proxy, and its default list of trusted proxies is the private IP ranges, which cover the usual Docker, Docker Compose and Kubernetes networks. A request that reaches Tomcat directly carries no such headers, so nothing is rewritten and the valve can be left in place permanently.

Why declare the valve in context.xml rather than in server.xml?

Both work, but context.xml is a short file that only adds the valve, whereas server.xml has to be copied out of the image and kept in step with the version of Tomcat that the image bundles, which differs from one XWiki cycle to the next. Configure Tomcat to Find Proxy Headers describes the server.xml route, for a Tomcat installed outside of Docker.

Is the valve only useful when the proxy terminates TLS?

No. A plain HTTP proxy also hides the real client address and the public host name and port from Tomcat, so the valve is what restores them, both for the logs and for the URLs that XWiki generates.

Related

Get Connected