Server

HTTP and HTTPS Reverse-Proxy Configuration

Updated: December 17, 2024

The Nuxeo webapp can be virtually hosted behind a HTTP/HTTPS reverse proxy, like Apache, NGINX, IIS, etc.

The Nuxeo Platform provides a content repository for document management, digital asset management and case management business applications.

Motivations for Virtual Hosting

Virtual hosting provides several advantages:

  • Support for HTTPS:
    HTTPS support in Apache is easy and flexible to setup. Apache can also be used to handle certificate authentication.

  • URL filtering:
    You can use Apache filtering tools to limit the URLs that can be accessed via the reverse proxy.

  • Handle HTTP cache for static resources:
    The Nuxeo Platform generates standard HTTP cache headers for all static resources (images, JavaScript...). These resources are by default cached on the client side (in the browser cache). For performance reasons, it can be useful to host these resources in the reverse proxy cache.

This page focuses on the Apache Configuration.

Bandwidth and Transactions Optimizations

Using a reverse proxy can also be a way to optimize uploads and downloads.

When clients access the Nuxeo server via a WAN with low bandwidth, upload and download can take time: this is bad for the server since it consumes resources such as:

  • HTTP socket and HTTP thread
  • Memory
  • Transaction and associated JDBC resources

A reverse proxy can be used to buffer uploads and downloads so that uploads and downloads from the Nuxeo server's point of view are always done at a high speed.

Virtual Hosting Configuration for Apache 2.x

Reverse Proxy with mod_proxy

For this configuration, you will need to load and enable the mod_proxy and mod_proxy_http modules.

ProxyPass /nuxeo/ http://NuxeoServerInternalIp:8080/nuxeo/ nocanon
ProxyPassReverse /nuxeo/ http://NuxeoServerInternalIp:8080/nuxeo/
ProxyPreserveHost On

The nocanon keyword for ProxyPass is required to prevent URL canonicalization on Apache, since it decodes certain characters (such as ";") before passing them on to the Nuxeo server. In the absence of nocanon, some URLs won't be parsed correctly.

You can also use rewrite rules to achieve the same result:

ProxyVia On
ProxyRequests Off
RewriteEngine On
RewriteRule /nuxeo(.*) http://NuxeoServerInternalIp:8080/nuxeo$1 [P,L]

This configuration will allow you to access the Nuxeo Platform webapp via http://ApacheServer/nuxeo/.

The Nuxeo webapp will generate the URLs after reading the HTTP header x-forwarded-host.

Unfortunately, this header does not specify the protocol used. So if your Apache is responding to HTTPS, you will need to send the Nuxeo Platform a specific header to indicate the base URL that the webapp must use when generating links.

RequestHeader append nuxeo-virtual-host "https://myDomainName/"

This will require you to load and activate the mod_headers module.

When it is not possible to add this header at the reverse-proxy level, you can use the nuxeo.virtual.host parameter in nuxeo.conf instead. This restricts the URLs through which your Nuxeo instance can be accessed though, so use of the header if preferred when possible.

And if you have a "client denied by server configuration" error, you must check the access control directives of mod_proxy:

<Proxy *>
  Order Deny,Allow
  Deny from all
  Allow from 192.168
</Proxy>

Reverse Proxy a WebEngine Site to a myexample.com/mysite URL

You need the same configuration from the first section. It is advised to first get it to work before exclusively proxying a WebEngine site.

A site request queries both from its own URL (/nuxeo/site/mysite) but also acquires static resources from the root (/nuxeo/nxthemes ...). A rewrite configuration for mysite would look like:

RewriteRule ^/nuxeo$   /nuxeo/  [P,L]
RewriteRule ^/mysite$   /mysite/  [P,L]

RewriteCond %{REQUEST_URI}  ^/mysite/skin/mysite/.*
RewriteRule ^/mysite/skin/mysite/(.*) http://NuxeoServerInternalIp:8080/nuxeo/site/skin/mysite/$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/mysite/skin/.*
RewriteRule ^/mysite/skin/(.*) http://NuxeoServerInternalIp:8080/nuxeo/site/skin/mysite/$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/mysite/nxthemes-(lib|css)/.*
RewriteRule ^/mysite/(.*) http://NuxeoServerInternalIp:8080/nuxeo/$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/mysite/nxthemes-webwidgets/.*
RewriteRule ^/mysite/(.*) http://NuxeoServerInternalIp:8080/nuxeo/site/$1 [P,L]

RewriteRule ^/mysite/(.*) http://NuxeoServerInternalIp:8080/nuxeo/site/mysite/$1 [P,L]

WebEngine also needs to know the base of the site, in this case, an empty string instead of /nuxeo/site. This information is passed using the mod_headers:

RequestHeader append nuxeo-webengine-base-path ""

You can also fetch the static resources from a different path. To do so add a properties to the nuxeo.properties file:

org.nuxeo.ecm.webengine.skinPathPrefix=/skin/

Reverse Proxy with mod_jk

The AJP connector may lock threads if you're not using the APR implementation. Please read the native Tomcat documentation for activating the APR implementation on your system. On Linux you just have to install the package libtcnative-1.

mod_jk allows you to communicate between Apache and Tomcat via the ajp1.3 protocol.

JkWorkersFile /etc/apache2/jk/workers.properties
JkLogFile     /var/log/mod_jk.log
JkLogLevel    info
JkMount /nuxeo ajp13
JkMount /nuxeo/* ajp13

The workers.properties file will contain the list of Nuxeo Platform Tomcat servers. The AJP13 Tomcat listener should be enabled by default on port 8009.

worker.list=ajp13
worker.ajp13.port=8009
worker.ajp13.host=NuxeoServerInternalIp
worker.ajp13.type=ajp13
worker.ajp13.socket_keepalive=1
worker.ajp13.connection_pool_size=50

Once again, if you use HTTPS, you will need to set the Nuxeo-specific header to tell the webapp how to generate URLs:

RequestHeader append nuxeo-virtual-host "https://myDomainName/"

This will require you to load and activate the mod_headers module.

Secure Headers with Tomcat behind HTTPS Apache

The only need to secure headers (like the SESSIONID) in this type of configuration is to add to the Tomcat web.xml of Nuxeo the following lines:

<session-config>
        <session-timeout>30</session-timeout>
        <cookie-config>
          <http-only>true</http-only>
          <secure>true</secure>
        </cookie-config>
    </session-config>

 

Secure Headers with mod_headers.so

Without having HttpOnly and Secure flags in HTTP response header, it is possible to steal or manipulate web application session and cookies.

  1. Enable mod_headers.soin Apache instance
  2. Add following entry in httpd.conf or apache2.conf:

    Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure (>= apache 2.2.4)
    or
    Header set Set-Cookie HttpOnly;Secure (< apache 2.2.4)
    
  3. Restart Apache instance

Configuring HTTP Cache

The Simple cache filter is deprecated, we recommend using the filterConfig extension point of RequestControllerService .

RequestControllerService's Filter Extension Point

This extension point lets you contribute customized filter for a given pattern URL.

Example of a filterConfig Registration

 <extension target="org.nuxeo.ecm.platform.web.common.requestcontroller.service.RequestControllerService"
  point="filterConfig">

   <filterConfig name="filterName" transactional="true" synchonize="true"
     cached="true" private="true" cachetime="3600">
   <pattern>/nuxeo/urlPattern/.*</pattern>
   </filterConfig>
 </extension>

This contribution will ensure that every pattern matching URL will go through NuxeoRequestControllerFilter. The header of the corresponding request will be modified according to the extension point configuration. Here is a list of the possible options:

  • filterConfig

    • name: name of the Filter.
    • transactional: use transaction.
    • synchonize: is synchronized.
    • cached: if true, adds cache-control to the header.
    • cacheTime: cache duration.
    • private: if true, cache is private, public if false.
  • pattern: URL pattern to match

Using Simple Cache Filter

The Nuxeo webapp includes a servlet filter that will automatically add header cache to some resources returned by the server.

By using the deployment-fragment.xml you can also put some specific resources behind this filter:

<extension target="web#FILTER">
  <filter-mapping>
    <filter-name>simpleCacheFilter</filter-name>
    <url-pattern>/MyURLsToCache/*</url-pattern>
  </filter-mapping>
</extension>

When the Nuxeo Platform is virtual hosted with apache you can use mod_cache to use the reverse-proxy as cache server.

You can also use Squid or any other caching system that is compliant with the standard HTTP caching policy.

Configuration Between AWS Elastic Load Balancing (ELB) and Apache

When using Apache as a backend server for ELB, it is really important to pay attention to the configuration of both, otherwise you may encounter several performance issues. The ELB is creating connections on the Apache and putting them in idle, but if Apache has a much shorter timeout, it will close them before they are actually used. We recommend using a slightly higher value for the Apache keep alive timeout than the idle timeout configured on the ELB.

Here is an example of a configuration on Apache (apache2.conf file) and on ELB:

Apache configuration

KeepAlive On    
KeepAliveTimeout 300
MaxKeepAliveRequests 100
AcceptFilter http none

Nuxeo Tomcat HTTPS Configuration

Configuring Tomcat in HTTPS is not recommended. Please follow instructions above to configure Apache server. 

If you need to configure your Nuxeo Tomcat in HTTPS, the platform provides an HTTPS configuration template for this purpose:

Add https to the nuxeo.templates property then edit the related properties.

Sample configuration of properties related to the "https" template

nuxeo.server.https.port=8443
nuxeo.server.https.keystoreFile=/path/to/keystore
nuxeo.server.https.keystorePass=password

To create your keystore using Java
keytool -genkey -alias tomcat -keyalg RSA

Ngnix Issue

Due to a Nginx headers filtering, you must disable the check on invalid headers:

ignore_invalid_headers off

Affected headers in the Nuxeo Platform are:

  • enrichers.document
  • fetch.document

Otherwise, features like the Permissions tab will not work.