Installation and Administration

Deploying Nuxeo on CloudFoundry

Updated: July 17, 2023

Before you start reading this documentation page you may want to have a look at the Nuxeo Requirements page.

Building a WAR

The following is a recipe to build a WAR of Nuxeo CoreServer. We need a WAR because normally Nuxeo runs as an exploded hierarchy with a customized loader that knows about the Nuxeo structure. Building a simple WAR turns this into a static configuration that can be used in any servlet container.

Getting Nuxeo

Download the latest nuxeo-coreserver from http://qa.nuxeo.org/jenkins/view/Depl/job/IT-nuxeo-master-build/lastSuccessfulBuild/artifact/archives/ , for instance in these examples: nuxeo-coreserver-8.1-I20151208_0124-tomcat.zip

For this recipe we'll put it into /opt.

Preparing Nuxeo

Nuxeo is currently packaged with a Tomcat 7 instance (version 7.0.64). The following explains how to prepare it.

  1. First unzip Nuxeo in /opt:

    cd /opt
    unzip nuxeo-coreserver-8.1-I20151208_0124-tomcat.zip
    mv coreserver-8.1-SNAPSHOT-tomcat nuxeo-coreserver-8.1-SNAPSHOT-tomcat
    
  2. Then edit some permission:

    chmod +x /opt/nuxeo-coreserver-8.1-SNAPSHOT-tomcat/bin/*.sh
    
  3. In /opt/nuxeo-coreserver-8.1-SNAPSHOT-tomcat/bin/nuxeo.conf , remove or comment nuxeo.wizard.done=false

Building the Tomcat+WAR

This builds a ZIP containing a WAR and a few additional files, designed to be unpacked at the root of a Tomcat instance. It cannot be used directly as a pure WAR.

cd /opt/nuxeo-coreserver-8.1-SNAPSHOT-tomcat
bin/nuxeoctl pack /opt/nuxeotomcatwar.zip 

The resulting ZIP is all that's needed for the rest of the instructions.

Preparing a full Tomcat 7 with Nuxeo WAR

  1. Download and set up a new Tomcat 7 from scratch with the WAR that was just built.

    cd /opt
    unzip apache-tomcat-7.0.65.zip
    mv apache-tomcat-7.0.65 tomcat-7.0.65
    cd tomcat-7.0.65
    chmod +x bin/*.sh
    unzip /opt/nuxeotomcatwar.zip
    
  2. Now update the WAR to work in a Tomcat 7 instance without references to the toplevel >lib/ directory:

    mv lib/commons-*.jar lib/h2-*.jar lib/lucene-*.jar lib/nuxeo-*.jar webapps/nuxeo/WEB-INF/lib/
    rm lib/derby-*.jar
    
  3. Finally we must set up the Nuxeo datasources inside the WAR (instead of from the toplevel server.xml in a standard Nuxeo setup, which is more convenient when possible).

    Edit the file webapps/nuxeo/META-INF/context.xml. In this file the <Resource> elements that point to a global configuration in server.xml must be replaced by explicit resources:

      <Resource name="jdbc/NuxeoDS" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxsqldirectory" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxrelations-default-jena" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/comment-relations" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxaudit-logs" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxjbpm" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/placeful_service_ds" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxwebwidgets" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
      <Resource name="jdbc/nxuidsequencer" accessToUnderlyingConnectionAllowed="true" auth="Container" driverClassName="org.h2.Driver" maxActive="100" maxIdle="30" maxWait="10000" password="" type="javax.sql.DataSource" url="jdbc:h2:nuxeo" username="sa" validationQuery=""/>
    

    In the above we use an embedded H2 database. Configuration for an external database server would need to use a different JDBC URL.

  4. The above exploded WAR can now be packed into a zipped WAR:

    cd /opt/tomcat-7.0.65/webapps/nuxeo
    zip -r /opt/nuxeo.war .
    

    The resulting /opt/nuxeo.war is now compatible with any modern application server.

Deploying to CloudFoundry

Patching the WAR

If you try to deploy the above WAR on CloudFoundry you'll get an error: Too many open files

This is due to the fact that CloudFoundry has a limit of 256 file descriptors open, and Nuxeo uses more.

In fact, it's the Tomcat classloader that uses a lot of file descriptors, because for performance reasons it keeps one open file descriptor per JAR in the WEB-INF/lib directory. To work around this problem, the non-Nuxeo JARs present in WEB-INF/lib can be merged into one big JAR, which solves the problem.

cd webapps/nuxeo/WEB-INF/lib
mkdir tmp
mkdir bigjar
mv *.jar tmp/
mv tmp/nuxeo-*.jar .
cd bigjar
for i in ../tmp/*.jar; do unzip $i; done
rm META-INF/*.SF META-INF/*.DSA
zip -r ../bigjar.jar .
cd ..
rm -rf tmp/ bigjar/

Deploying Tomcat 7 + Nuxeo

Before the above Tomcat 7 instance can be set up as a full “standalone” application in CloudFoundry, it needs to be modified to take configuration information (like TCP ports) from the CloudFoundry PaaS framework. (These are standard instructions for using a stock Tomcat in CloudFoundry, you'll find them elsewhere.)

  1. The following is added to bin/catalina.sh :

    # USE VCAP PORT IF IT EXISTS, OTHERWISE DEFAULT TO 8080
    if [ -z ${VCAP_APP_PORT} ]; then
      export VCAP_APP_PORT=8080
    fi
    export JAVA_OPTS="-Dport.http.nonssl=$VCAP_APP_PORT $JAVA_OPTS"
    
  2. The bin/startup.sh is changed to not run in the background ( run instead of start):

    exec "$PRGDIR"/"$EXECUTABLE" run "$@"
    
  3. Finally the non-useful ports in conf/server.xml are commented out:

    • Replace 8005 with -1 to deactivate the Tomcat SHUTDOWN port.
    • Comment out the AJP connector on port 8009.
    • Replace 8080 with the expression ${port.http.nonssl} to use the PaaS configuration.
  4. The Tomcat 7 application including the Nuxeo WAR is now ready to be pushed to CloudFoundry as a “Standalone Application”. For this, standard CloudFoundry mechanisms are used, don't forget to specify the Java 8 runtime:

    vmc push --runtime=java8 myapp
    

    The following CloudFoundry YML manifest corresponds to a full setup (myapp should be replaced by your namespace):

    ---
    applications:
      .:
        mem: 1G
        instances: 1
        url: myapp.cloudfoundry.com
        framework:
          info:
            mem: 64M
            exec:
            description: Standalone Application
          name: standalone
        command: bin/startup.sh
        name: myapp
        runtime: java8
    

Testing Nuxeo CMIS

Once deployed and started, Nuxeo CoreServer does not provide a web-accessible graphical user interface (because the CoreServer version doesn't have those), but it can be addressed through a CMIS client like the Apache CMIS Workbench available at http://chemistry.apache.org/java/developing/tools/dev-tools-workbench.html.

It must point to Nuxeo, whose CMIS address is described by the Nuxeo startup page, usually it is of the form http://NUXEO_SERVER/nuxeo/atom/cmis. The default Nuxeo user/password is Administrator/Administrator.