Hosting GeoServer behind a Reverse Proxy and CDN


I thought it would be fun to serve geo-tagged photos and GPX track data over a WMS/WFS interface with GeoServer. This turned out to be quite challenging to run GeoServer behind a reverse proxy, and with a context path (e.g. /api/geoserver/).

After a lot of trial and error, the configuration documented below ultimately worked for me 🙂


My goal was for GeoServer to be accessible from I was hoping to run the service in a Docker container, and add a CDN and Apache reverse proxy in-front to help with caching.

Eventual solution for running GeoServer behind a CDN and Reverse Proxy


I faced several challenges configuring the base and context URLs inside GeoServer, as well as some general issues with the Admin interface.

Setting the Base URL and Context Path

GeoServer needs to know where it is running so that the URLs and redirects it generates are valid. For example, redirecting to an internal URL like http://192.168.1.x/api/geoserver would break the application for the end user.

In my case, the base URL was, and the context path was /api/geoserver.

Depending on how you’re hosting GeoServer, configuring these URLs in multiple places may be required. For example, the Global “Proxy Base URL” setting will set the URL for OGC output, but user login redirects for the admin interface may need to be configured in Tomcat XML configuration files.

Recommendation: use the kartoza/docker-geoserver Docker image, which makes it simple to configure the base URL and context path as part of the docker run command, for example:

docker run -p 8881:8080 
  --env GEOSERVER_CONTEXT_ROOT=api#geoserver 
  --env HTTP_PROXY_NAME="" 
  --env HTTP_PROXY_PORT=443 
  --env HTTP_SCHEME=https 

Admin UI CORS Errors

The GeoServer Admin interface employs CSRF security checks during form POSTs, which were breaking for me during certain operations like Adding a new Layer. Recommendations online were to disable to CSRF checks, or provide a domain whitelist.

Oddly I also found the admin interface was much more stable when running in an incognito window.

Configuring the CDN

Fortunately the CDN configuration was straight-forward and mostly a matter of configuring when to pass along headers/cookies/query string parameters.

  1. /api/geoserver/*/wms – WMS calls – trying to cache these requests, I only passed the Host, Origin, and Referer headers back, along with all query strings (used by OGC calls)
  2. /api/geoserver/*/ogc – WFS calls – same configuration as #1.
  3. /api/geoserver/* – GeoSever Admin Interface – I disabled all caching on this behavior, and passed all headers/cookies/query string parameters back to the origin server.

Important: make sure the rules #1 and #2 are evaluated by the CDN before #3, otherwise the requests will not be cached. In CloudFront, this is done by making sure #1 and #2 appear in the list above #3.

Configuring the Apache Reverse Proxy

The reverse proxy configuration was minimal, and forwarded incoming requests back to the Docker container, which was listening on port 8881.

# configure reverse proxy to geoserver docker container
ProxyPass /api/geoserver
ProxyPassReverse /api/geoserver

# optional for CORS support
<LocationMatch /api/geoserver>
  Header set Access-Control-Allow-Origin "*"

Running the GeoServer Docker Container

As mentioned above, I used the kartoza/docker-geoserver image. It was extremely flexible and allowed for the specific URL configuration that I needed.

docker run -e GEOSERVER_ADMIN_USER=admin -e GEOSERVER_ADMIN_PASSWORD=geoserver --name geoserver 
  --mount type=bind,src=/local/os/path/geoserver/data,target=/opt/geoserver/data_dir -p 8881:8080 
  --env GEOSERVER_CONTEXT_ROOT=api#geoserver 
  --env HTTP_PROXY_NAME="" 
  --env HTTP_PROXY_PORT=443 
  --env HTTP_SCHEME=https 

Next Steps

Now that my GeoServer instance is available, I will begin to load it with data and publish layers. I am excited to experiment with updating data via WFS Transactions.

In addition to the fun stuff, I should better secure the GeoServer instance by changing the default user/password, and configuring the instance so that it is only accessing from certain machines via an IP allow-list.

Subscribe by Email

Enter your email address below to be notified about updates and new posts.


Loading comments..

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *