<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Teknologist's Blog]]></title><description><![CDATA[Systems & software design,  platforms architectures,  experiences / experiments shared with the masses. 
100% OpenSource. 

GNU is not Unix. ]]></description><link>https://blog.teknologism.com/</link><generator>Ghost 0.11</generator><lastBuildDate>Thu, 09 Apr 2026 06:41:19 GMT</lastBuildDate><atom:link href="https://blog.teknologism.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[eXo Platform Docker Composed]]></title><description><![CDATA[exo platform with mysql and docker data containers using docker-compose]]></description><link>https://blog.teknologism.com/exo-platform-docker-composed/</link><guid isPermaLink="false">a63d24de-34be-48cd-b54a-5133d4623228</guid><category><![CDATA[exo]]></category><category><![CDATA[docker]]></category><category><![CDATA[compose]]></category><category><![CDATA[mysql]]></category><dc:creator><![CDATA[Eric]]></dc:creator><pubDate>Mon, 08 Jun 2015 12:56:04 GMT</pubDate><media:content url="https://blog.teknologism.com/content/images/2015/06/exoCompose-title-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.teknologism.com/content/images/2015/06/exoCompose-title-1.png" alt="eXo Platform Docker Composed"><p><img src="https://blog.teknologism.com/content/images/2015/06/exoCompose-title.png" alt="eXo Platform Docker Composed"></p>

<p><strong>UPDATED 06/09/2015:</strong> Added support for MYSQL_ environment variables in exoplf image allowing for a fully custom exo+mysql setup (i.e.: change mysql password, database name etc.)</p>

<h2 id="1introduction">1. Introduction</h2>

<p>This post's goal is to explain how to build a dockerized eXo Platform following Docker's core principle of  <strong>"one task, one container"</strong>.</p>

<p>In this example eXo platform will be using MySql as the database making it more production ready.</p>

<p>Also eXo's JCR data as well as MySql data will be stored in separate and dedicated <strong>Docker Data containers</strong>. <br>
To link all this containers together we will be using the newly released <strong>docker-compose</strong> tool.</p>

<p>The final docker composition will look like this:</p>

<p><img src="https://blog.teknologism.com/content/images/2015/06/eXoCompose.png" alt="eXo Platform Docker Composed"></p>

<h2 id="2containersdescriptions">2. Containers Descriptions</h2>

<p>We will need 4 containers:</p>

<ul>
<li><strong>mysql</strong>
<ul><li>using the official mysql/mysql-server:latest image</li></ul></li>
<li><strong>mysqldata</strong>
<ul><li>will expose volume /var/lib/mysql</li></ul></li>
<li><strong>exoplf</strong>
<ul><li>using a tweaked exo platform image, supporting server.xml customization and custom jcr data volume</li></ul></li>
<li><strong>exodata</strong>
<ul><li>will expose volume      /srv/exo where eXo's JCR data will be stored</li></ul></li>
</ul>

<p><br>  </p>

<h2 id="3containersdockerfiles">3. Containers Docker Files</h2>

<p><br> <br>
Lets describe these containers.  </p>

<h4 id="mysql">Mysql</h4>

<p>We will pull the official mysql/mysql-server:latest available on DockerHub Registry here:</p>

<p><a href="https://registry.hub.docker.com/_/mysql/">https://registry.hub.docker.com/_/mysql/</a></p>

<p>It supports the initial creation of the database and user through Environment variables.</p>

<pre><code> MYSQL_DATABASE: exo
 MYSQL_USER: exo
 MYSQL_PASSWORD: changeme
 MYSQL_ROOT_PASSWORD: changeme
</code></pre>

<p>You can change any of these but note you will need to adjust the server.xml file in the exo-plf container (described later on)</p>

<p>This container will mount /var/lib/mysql from the mysql-data container</p>

<h4 id="mysqldata">Mysql Data</h4>

<p>This is the container that will store the Mysql data directory. <br>
It is very simple. <br>
It's Dockerfile looks like this:</p>

<pre><code>FROM busybox:latest  
MAINTAINER Eric Taïeb Walch &lt;teknologist@gmail.com&gt;  
RUN mkdir -p /var/lib/mysql &amp;&amp; chmod -R 777 /var/lib/mysql  
VOLUME /var/lib/mysql  
</code></pre>

<p>The important line here is:  </p>

<pre><code>VOLUME /var/lib/mysql  
</code></pre>

<p>It makes the /var/lib/mysql directory mountable by other containers.</p>

<p>DockerHub image is <em>teknologist/mysql-docker-data</em> available at the DockerHub Registry here: </p>

<p><a href="https://registry.hub.docker.com/u/teknologist/mysql-docker-data/">https://registry.hub.docker.com/u/teknologist/mysql-docker-data/</a></p>

<p>GitHub repo: <a href="https://github.com/teknologist/mysql-docker-data">https://github.com/teknologist/mysql-docker-data</a></p>

<h4 id="exodata">eXo Data</h4>

<p>Same as above, this image will be used to spawn a container that holds /srv/exo directory. <br>
This directory contains all the persistent data for eXo's JCR files.</p>

<p>Again it is very simple. <br>
It's Dockerfile looks like this:</p>

<pre><code>FROM busybox:latest  
MAINTAINER Eric Taïeb Walch &lt;teknologist@gmail.com&gt;  
RUN mkdir -p /srv/exo  
RUN chmod 777 -R /srv/exo  
VOLUME /srv/exo  
</code></pre>

<p>DockerHub image is <em>teknologist/exo-data</em></p>

<p>Available at the DockerHub Registry:</p>

<p><a href="https://registry.hub.docker.com/u/teknologist/exo-data/">https://registry.hub.docker.com/u/teknologist/exo-data/</a></p>

<p>GitHub repo: <a href="https://github.com/teknologist/docker-data">https://github.com/teknologist/docker-data</a></p>

<h4 id="exoplatform">eXo Platform</h4>

<p>This image is a fork of eXo's original image.</p>

<p>Changes are:</p>

<ul>
<li>Upgraded to PLF 4.2.0-RC1</li>
<li>Added MySQL JDBC Connector to lib/ directory</li>
<li>Added server.xml to switch default HSQL database to MySQL</li>
<li>Added environment variables to setup mysql connection properties</li>
</ul>

<p>The github repo for this Docker image is available here: <br>
<a href="https://github.com/teknologist/ubuntu-jdk7-exo">https://github.com/teknologist/ubuntu-jdk7-exo</a></p>

<p>As you can see the server.xml refers to a mysql database host named <strong>mysql</strong>. <br>
This is important as this is how containers are linked using docker-compose.</p>

<p>Short story: <br>
If you name a container mysql and link it in the docker-compose.yml file, then docker-compose will set an entry in the hosts file named mysql pointing at the IP of the container. <br>
This makes linking container trivial.</p>

<p>The Docker image is teknologist/ubuntu-jdk7-exo-mysql available at the DockerHub Registry here:</p>

<p><a href="https://registry.hub.docker.com/u/teknologist/ubuntu-jdk7-exo-mysql/">https://registry.hub.docker.com/u/teknologist/ubuntu-jdk7-exo-mysql/</a></p>

<h2 id="4dockercomposingallthesecontainerstogether">4. Docker composing all these containers together</h2>

<p>This is where the magic happens. By writing a simple 25 lines docker-compose.ym we will spawn an entire eXo Platform infrastructure in minutes.</p>

<p>First of all you need to have a recent docker version installed (1.3 or higher) for docker-compose to work. <br>
As of this writing I am using Docker version 1.6.2, build 7c8fca2. <br>
You can find how to install docker here: <a href="https://docs.docker.com/installation/">https://docs.docker.com/installation/</a></p>

<p>Next step is installing docker-compose. <br>
On supported platforms (GNU/Linux, OSX, etc.) this is as simple as entering the following commands:</p>

<pre><code>curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` &gt; /usr/local/bin/docker-compose  
chmod +x /usr/local/bin/docker-compose  
</code></pre>

<p>See <a href="https://docs.docker.com/compose/install/">https://docs.docker.com/compose/install/</a> for more information.</p>

<p>Once your docker + docker-compose environment is ready, create a directory, exo-compose for example. In that directory create a file called docker-compose.yml with the following content:</p>

<pre><code>exodata:  
  restart: on-failure:5
  image: teknologist/exo-data
mysqldata:  
  restart: on-failure:5
  image: teknologist/mysql-docker-data
mysql:  
  restart: on-failure:5
  image: mysql/mysql-server:latest
  environment:
    MYSQL_DATABASE: exo
    MYSQL_USER: exo
    MYSQL_PASSWORD: changeme
    MYSQL_ROOT_PASSWORD: changeme
  volumes_from:
  - mysqldata
exoplf:  
  restart: on-failure:5
  ports:
  - 8080:8080/tcp
  image: teknologist/ubuntu-jdk7-exo-mysql
  environment:
    MYSQL_DATABASE: exo
    MYSQL_USER: exo
    MYSQL_PASSWORD: changeme
  links:
  - mysql
  volumes_from:
  - exodata
</code></pre>

<p><strong>UPDATED 09/16/2015 to include MYSQL_ environment variables to the <em>exoplf</em> service.</strong></p>

<p>Beware this a yaml file so indentation is of the utmost importance. Gist available <a href="https://gist.githubusercontent.com/teknologist/aec363604a952bfc2ef4/raw/acbf30bc8efc58ba64d0cfead21c7d186b0af2f1/docker-compose.yml">here</a>.</p>

<p>As you can see 3 things are important here and let you link everything together:</p>

<pre><code>volumes_from  
</code></pre>

<p>This directive instructs each container to mount the volumes from the respective data container.</p>

<pre><code>links:  
 - mysql
</code></pre>

<p>This is the main compose directive that links exo platform to mysql. With this directive, docker-compose:</p>

<ul>
<li>creates a network connection between the exo and mysql containers</li>
<li>creates an entry named <em>mysql</em> in eXo container's /etc/hosts file pointing to the mysql container IP</li>
</ul>

<p>If you look back at the server.xml file, this is how the <em>mysql</em> host in the jdbc connection string gets resolved. </p>

<p>You can find docker-compose full documentation here: <br>
<a href="https://docs.docker.com/compose/">https://docs.docker.com/compose/</a></p>

<p>Last but not least, both mysql and exoplf services' MYSQL_ environment variables:</p>

<pre><code>    MYSQL_DATABASE: exo
    MYSQL_USER: exo
    MYSQL_PASSWORD: changeme
    MYSQL_ROOT_PASSWORD: changeme
</code></pre>

<p><strong>NOTE:</strong> <code>MYSQL_ROOT_PASSWORD</code> is only needed in mysql service</p>

<p><strong>NOTE:</strong> You may want (highly recommended) change mysql exo user password. In order to do that <del>you need to pull my ubuntu-jdk7-exo-mysql image and modify the server.xml. I recommend setting it up as an environment variable in the docker-compose.yml <em>exoplf</em> section, then changing the server.xml to use that environment variable. I may update the images later to reflect this.</del> <strong>UPDATE: I have updated the <em>exoplf</em> image to support MYSQL_ environment variables. It is know trivial to setup custom MySQL connection details. Just set the MYSQL_ environment variables correctly on both <em>exoplf</em> and <em>mysql</em> services in docker-compose.yml - Content has been updated in this post to reflect this.</strong> </p>

<p>Now you are ready to spawn the infrastructure. In the directory where you created the docker-compose.yml file, just launch: <em>docker-compose up</em></p>

<pre><code>eric@morpheus:~/exo-compose$ docker-compose up  
Creating exocompose_mysqldata_1...  
Creating exocompose_exodata_1...  
Creating exocompose_mysql_1...  
Creating exocompose_exoplf_1...  
Attaching to exocompose_mysql_1, exocompose_exoplf_1  
mysql_1  | Running mysql_install_db  
mysql_1  | 2015-06-08 12:07:00 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).  
mysql_1  | 2015-06-08 12:07:00 0 [Note] /usr/sbin/mysqld (mysqld 5.6.25) starting as process 22 ...  
exoplf_1 | 2015-06-08 12:07:01,891 | INFO  | The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib [o.a.catalina.core.AprLifecycleListener&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:07:02,334 | INFO  | Initializing ProtocolHandler ["http-nio-0.0.0.0-8080"] [o.apache.coyote.http11.Http11NioProtocol&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:07:02,384 | INFO  | Using a shared selector for servlet write/read [o.apache.tomcat.util.net.NioSelectorPool&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:07:02,386 | INFO  | Initializing ProtocolHandler ["ajp-bio-0.0.0.0-8009"] [org.apache.coyote.ajp.AjpProtocol&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:07:02,405 | INFO  | Initialization processed in 1216 ms [org.apache.catalina.startup.Catalina&lt;main&gt;]  
</code></pre>

<p>NOTE: If you want to run your services in the background, you can pass the -d flag (for daemon mode) to docker-compose up and then use docker-compose ps to see what is currently running. Of course, each docker container supports classic docker commands, so you could check <em>exoplf's</em> logs via a <em>docker logs</em> commands.</p>

<p>I like to start the first time without -d so I can see what is going on in the initial containers setup.</p>

<p><strong>NOTE:</strong> Now the thing is that docker-compose starts containers fast and the initial startup of mysql creates the database and user so at immediate startup exo's container will show an error connecting to the database. You can ignore that because while exo continues its startup process the database will become available. This only happens the first time as the databases need to be created.</p>

<p>Depending on your docker's host performance after some time you'll see:  </p>

<pre><code>exoplf_1 | 2015-06-08 12:09:11,830 | INFO  | Starting ProtocolHandler ["http-nio-0.0.0.0-8080"] [o.apache.coyote.http11.Http11NioProtocol&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:09:11,835 | INFO  | Starting ProtocolHandler ["ajp-bio-0.0.0.0-8009"] [org.apache.coyote.ajp.AjpProtocol&lt;main&gt;]  
exoplf_1 | 2015-06-08 12:09:11,838 | INFO  | Server startup in 129433 ms [org.apache.catalina.startup.Catalina&lt;main&gt;]  
</code></pre>

<p>And you can connect to your docker's host port 8080 (provided you didn't change it in the docker-compose ports directive) and you'll be greeted with the initial eXo setup page:</p>

<p><img src="https://blog.teknologism.com/content/images/2015/06/exo-setup-1.PNG" alt="eXo Platform Docker Composed"></p>

<p>Complete the rest of the setup wizard and you are set.</p>

<h2 id="5operatingyourexomysqldockercomposition">5. Operating your eXo/Mysql Docker composition</h2>

<p>You can stop and start your infrastructure as you wish. Persistence data is kept in the data containers so no loss of data/configuration.</p>

<h4 id="stoppingyourexistinginfrastructure">Stopping your existing infrastructure</h4>

<p>If you started in foreground , just hit [CTRL]-C. <br>
If you started in background, just enter: <em>docker-compose stop</em>  </p>

<pre><code>eric@morpheus:~/exo-compose$ docker-compose stop  
Stopping exocompose_exoplf_1...  
Stopping exocompose_mysql_1...  
</code></pre>

<p>Note you don't see anything related to the data containers as they don't really run, they just provide volumes.</p>

<h4 id="startingyourexistinginfrastructure">Starting your existing infrastructure</h4>

<p>Again, just enter: <em>docker-compose start</em>  </p>

<pre><code>eric@morpheus:~/exo-compose$ docker-compose start  
Starting exocompose_mysqldata_1...  
Starting exocompose_exodata_1...  
Starting exocompose_mysql_1...  
Starting exocompose_exoplf_1...  
</code></pre>

<h4 id="toseewhatiscurrentlyrunninginyourcomposeinfrastructure">To see what is currently running in your compose infrastructure</h4>

<p>Just enter: <em>docker-compose ps</em></p>

<pre><code>eric@morpheus:~/exo-compose$ docker-compose ps  
         Name                       Command               State            Ports
-----------------------------------------------------------------------------------------
exocompose_exodata_1     /bin/sh                          Exit 0  
exocompose_exoplf_1      /bin/sh -c ${EXO_APP_DIR}/ ...   Up       0.0.0.0:8080-&gt;8080/tcp  
exocompose_mysql_1       /entrypoint.sh mysqld            Up       3306/tcp  
exocompose_mysqldata_1   /bin/sh                          Exit 0  
</code></pre>

<p>Again, you see the data containers are not in running state and that is normal. <br>
Also note mysql port 3306 is not exposed outside the container. docker-compose does all the tunnelling for you.</p>

<h4 id="toseeyourcontainerslogs">To see your container's logs</h4>

<p>If you want to tail <em>exoplf's</em> log just type: <em>docker logs exocompose_exoplf_1</em>  </p>

<pre><code>eric@morpheus:~/exo-compose$ docker logs exocompose_exoplf_1  
2015-06-08 12:22:12,758 | INFO  | The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib [o.a.catalina.core.AprLifecycleListener&lt;main&gt;]  
2015-06-08 12:22:13,129 | INFO  | Initializing ProtocolHandler ["http-nio-0.0.0.0-8080"] [o.apache.coyote.http11.Http11NioProtocol&lt;main&gt;]  
2015-06-08 12:22:13,177 | INFO  | Using a shared selector for servlet write/read [o.apache.tomcat.util.net.NioSelectorPool&lt;main&gt;]  
2015-06-08 12:22:13,179 | INFO  | Initializing ProtocolHandler ["ajp-bio-0.0.0.0-8009"] [org.apache.coyote.ajp.AjpProtocol&lt;main&gt;]  
2015-06-08 12:22:13,198 | INFO  | Initialization processed in 1274 ms [org.apache.catalina.startup.Catalina&lt;main&gt;]  
2015-06-08 12:22:13,517 | INFO  | Starting service Catalina [org.apache.catalina.core.StandardService&lt;main&gt;]  
2015-06-08 12:22:13,517 | INFO  | Starting Servlet Engine: Apache Tomcat/7.0.55 [org.apache.catalina.core.StandardEngine&lt;main&gt;]  
2015-06-08 12:22:13,543 | INFO  | Deploying web application archive /opt/exo/platform-community-4.2.0-RC1/webapps/forum-gadgets.war [org.apache.catalina.startup.HostConfig&lt;localhost-startStop-5&gt;]  
2015-06-08 12:22:13,543 | INFO  | Deploying web application archive /opt/exo/platform-community-4.2.0-RC1/webapps/wiki.war [org.apache.catalina.startup.HostConfig&lt;localhost-startStop-9&gt;]  
2015-06-08 12:22:13,543 | INFO  | Deploying web application archive /opt/exo/platform-community-4.2.0-RC1/webapps/eXoPlatformResources.war [org.apache.catalina.startup.HostConfig&lt;localhost-startStop-10&gt;]  
</code></pre>

<p>Again, each of this containers supports all docker commands.</p>

<h2 id="6finalthoughts">6. Final thoughts</h2>

<p>As you can see docker-compose makes building docker based infrastructures very easy.</p>

<p>Other tools such as <a href="http://kubernetes.io">Google's Kubernetes</a> are very promising too. They not only let you compose but also scale (through minions, yes I didn't invent that).</p>

<p>Another very promising tool I have used to explore docker composition on <a href="https://coreos.com">CoreOS</a> is <a href="http://rancher.com">Rancher</a></p>

<p>It looks like we are moving more and more from VM based cloud infrastructure to highly dense container based ones. Think lower overhead (if not zero), think also green!</p>

<p><strong>Thanks for reading, sharing, commenting, +1 ing etc...</strong></p>]]></content:encoded></item><item><title><![CDATA[Creating a Codenvy Factory  for eXo extensions development using Docker]]></title><description><![CDATA[Codenvy cloud ide development factories for eXo Platform 4.1]]></description><link>https://blog.teknologism.com/codenvy-factory-docker-for-exo/</link><guid isPermaLink="false">1a3a9b5e-f0ed-4f7c-9883-a8755b33cad6</guid><category><![CDATA[Getting Started]]></category><category><![CDATA[exo platform]]></category><category><![CDATA[exo]]></category><category><![CDATA[codenvy]]></category><category><![CDATA[factories]]></category><category><![CDATA[cloud]]></category><category><![CDATA[infrastructure]]></category><category><![CDATA[docker]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Eric]]></dc:creator><pubDate>Wed, 26 Nov 2014 11:23:35 GMT</pubDate><media:content url="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-57-38.PNG" medium="image"/><content:encoded><![CDATA[<img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-57-38.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"><p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-57-38-1.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker">
<br></p>

<p>This tutorial aims to explain how to create a Codenvy Factory to provide a cloud based development and testing environment for developing an eXo extension based on Docker containers. <br>
<br></p>

<p>A Codenvy Factory can be used for:</p>

<ul>
<li>Creating a pre configured environment for a platform add ons (extension, skins etc.) development</li>
<li>Providing a development environment for modifying an existing software and testing it out of the box</li>
<li>Many more... Use your imagination
<br> <br>
<br>  </li>
</ul>

<h2 id="contents">Contents</h2>

<ul>
<li>Introduction</li>
<li>Getting Started: Requirements</li>
<li>Preliminary steps: Installing Codenvy CLI</li>
<li>Anatomy of a Codenvy Factory: Brief overview of the configuration file</li>
<li>Preparing the Codenvy Custom Runner Dockerfile: How the Codenvy custom runners and the Docker images work</li>
<li>Publishing the Codenvy custom runner Dockerfile</li>
<li>Assembling the Factory file: factory.json</li>
<li>Create the Factory using the factory.json file</li>
<li>Use or share your Factory</li>
</ul>

<p><br> <br>
<br></p>

<h2 id="introduction">Introduction</h2>

<p><br></p>

<p>About a month ago I had the chance to be invited to play with Codenvy's new platform and more specifically Factories. </p>

<p>I was asked to try to build factories to help eXo developers speed up/automate the setup of a development environment ready to code, test and deploy their extensions in an eXo platform automatically provisioned runtime, all running inside codenvy platform in the cloud.</p>

<p>I was amazed by Codenvy's overall value proposition. The platform is very impresive and I said twitted early on, in my opinion this signals clearly the dawn of a new generation of IDEs. </p>

<p>As a result of this work, I produced 2 factories for eXo. Both are available on eXo platform's add on catalog. One which allows to extend and code on the chat application extension and server. The other being an empty extension skeleton project. This tutorial is based on the latter.</p>

<p><br></p>

<p>In Codenvy, there are three types of Codenvy factories:</p>

<ul>
<li>Hack Factories</li>
<li>Tracked Factories (require a special account)</li>
<li>Branded Factories (require a special account)</li>
</ul>

<p><br> <br>
More on Codenvy Factory types here: <a href="http://bit.ly/120MP6O" target="_blank" title="Codenvy Factories For Sales &amp; Support">Codenvy Factories For Sales &amp; Support</a> </p>

<p>Basically, Tracked and Branded Factories allow more customization (ie: custom Welcome screens, etc.) and provide powerful analytics features.</p>

<p><b>NOTE: Creating a Tracked Factory requires a special account while Hack Factories are free and available to everyone. If you wish to use Tracked Factories, contact Codenvy using the link above for more information.</b></p>

<p><br></p>

<p>In this example we will address Hack Factories (we'll call them normal factories) and Tracked Factories. We will use the eXo platform 4.1RC1 and an empty eXo add-on maven project skeleton to create a factory which allows jumpstarting the development of an extension for the eXo Platform.</p>

<p>More information on this great enterprise social portal platform here:</p>

<p><br></p>

<p><a href="http://bit.ly/1zvyXwe" target="_blank" title="eXo Platform website" style="color:black;font-weight:bold;">eXo Platform website</a></p>

<p><br></p>

<p>We will show you how to create a custom runner that spawns a Docker container with eXo Platform 4.1RC1, builds your maven based project and deploys it to the eXo Platform 4.1RC1 runtime using eXo's add-on manager, then starts the eXo runtime in order to see the results.</p>

<p><br></p>

<p><b>NOTE:</b> In a future codenvy release you might be able to build all kinds of maven projects in the IDE. At the time of this writing it is difficult to succesfully retrieve multiple build artifacts for multi modules maven projects successfully.</p>

<p>Therefore, in order to be as flexible and as universally useable as possible, we do the build inside the custom runner using maven.</p>

<p>For example, eXo add-ons are maven multi modules projects which produce variuous artifacts, one of them being a zip file that we will provide to eXo's add-on manager in order to have it installed. This is the case for eXo empty add-on project we use in this tutorial.</p>

<p><br></p>

<h2 id="gettingstarted">Getting Started</h2>

<p><br></p>

<p><strong>Requirements:</strong></p>

<ul>
<li>Basic knowledge of GNU/Linux</li>
<li>A Codenvy account</li>
<li>Codenvy CLI installed on your local machine (see <a href="http://docs.codenvy.com/cli/" target="_blank" title="Codenvy Docs">Codenvy CLI Docs</a>)</li>
<li>Basic Docker knowledge (particularly: <a href="https://docs.docker.com/articles/dockerfile_best-practices/" target="_blank" title="Docker Best Practices">Docker Best Practices</a>)</li>
<li>Space to server html files and Dockerfile recipes (ie: webserver etc.)</li>
<li>Github account</li>
<li>DockerHub account linked to your GitHub account. See: <a href="https://hub.docker.com/" target="_blank" title="Docker Hub">Docker Hub</a> and <a href="https://docs.docker.com/docker-hub/" target="_blank" title="Docker Hub Documentation">Docker Hub Documentation</a></li>
</ul>

<p>For the sake of simplicity, in this tutorial, we will use a Dropbox account to host the html files (Only for tracked factories).</p>

<p><br></p>

<h2 id="preliminarysteps">Preliminary steps</h2>

<p><br> <br>
<strong>Installing required components: Codenvy CLI</strong></p>

<ul>  
<li>If you don't have a codenvy account, create one by navigating to <a href="https://codenvy.com/site/create-account" target="_blank" title="Create a Codenvy account">Create a Codenvy account</a>  in your favorite modern browser.</li>

<li>Install the Codenvy CLI on your local machine following these steps: <a href="http://docs.codenvy.com/cli/" target="_blank" title="Codenvy Docs">Codenvy CLI Docs</a></li>


<li>Verify you can login by opening a terminal and trying:</li></ul>

<pre><code>    # codenvy login
    Username: yourusername
    Password for yourusername:**********
</code></pre>

<p>If everything is OK you should see this message:</p>

<pre><code>      Login success on default remote 'default' [https://codenvy.com]
</code></pre>

<p>NOTE: Make sure you are using <b>bash</b> as your shell. I have found issues using other shells such as fish. Also make sure you have correctly setup your PATH so codenvy binary is in your PATH.</p>

<p><br></p>

<h2 id="anatomyofacodenvyfactory">Anatomy of a Codenvy Factory</h2>

<p><br></p>

<p>Codenvy official documentation for custom runners is available here: <a href="http://docs.codenvy.com/user/creating-custom-builder-runner-environments/#custom-overview" target="_blank" title="Codenvy Custom Runners Documentation">Codenvy Custom Runners Documentation</a></p>

<p>Long story short, we will be writing a JSON file (we will name it exo-extension-factory.json) describing the factory. Then we will create the factory using the codenvy cli and passing that json file.</p>

<p>That JSON file will among other have:</p>

<ul>
<li>a reference to a custom runner Dockerfile recipe</li>
<li>a reference to an html resource to be used as Welcome screen (Tracked Factories only)</li>
</ul>

<p><br></p>

<p>To build the Custom runner Docker image recipe we will use intermediate images. All Docker images will be built and pushed to the DockerHub public repository, except for the last one which will always be built by Codenvy at runtime in order to deploy the newly compiled add-on (see Docker Inheritance diagrams in the next section for more information).</p>

<p>In this next section I will show you how to create such a Dockerfile.</p>

<p><br></p>

<h2 id="preparingthecodenvycustomrunnerdockerfile">Preparing the Codenvy Custom Runner Dockerfile</h2>

<p><br></p>

<p>In codenvy a runner is the term to describe an execution runtime. In order to deploy custom runners, Codenvy uses Docker recipes. In this example our custom runner will be an eXo Platform distribution Docker image. </p>

<p>For the sake of simplicity we will write a Dockerfile recipe based on an already prepared image which has:</p>

<ul>
<li>Ubuntu minimal</li>
<li>Java JDK 7</li>
<li>Apache Maven including all eXo maven dependencies pre installed in .m2/repository (speeds up build time)</li>
<li>eXo Platform 4.1RC1 with first time wizard completed (this speeds up dramatically the runner startup time)</li>
</ul>

<p><br></p>

<p>This image is hosted on the DockerHub at this address: <a href="https://registry.hub.docker.com/u/teknologist/exo-maven-setup-done/" target="_blank" title="DockerHub base image">https://registry.hub.docker.com/u/teknologist/exo-maven-setup-done/</a></p>

<p>You can play with it your docker installation by pulling the image:</p>

<pre><code>docker pull teknologist/exo-maven-setup-done
</code></pre>

<p>The base image for this pre-setup image is available here <a href="https://registry.hub.docker.com/u/teknologist/exo-maven/" target="_blank">https://registry.hub.docker.com/u/teknologist/exo-maven/</a>: <br>
It is strictly the same except for the fact that the eXo platform is already setup through the first time wizard. <br>
The source for this docker image is available here: <a href="https://github.com/teknologist/exo-maven-docker" target="_blank">https://github.com/teknologist/exo-maven-docker</a></p>

<p><br></p>

<p>In order to install an eXo add-on using the bundled add-on manager script we need to provide a local.json file in EXO PLATFORM directory. This file describes the add-on, its availability, compatibility, license etc.</p>

<p>A sample file local.json file:</p>

<pre><code>[
    {
        id: "exo-custom-addon",
        version: "1.0.0",
        unstable: true,
        name: "Custom Add-on",
        description: "eXo custom extension",
        releaseDate: "2014-11-12T22:00:00.000Z",
        sourceUrl: "https://github.com/teknologist/exo-empty-extension",
        downloadUrl: "file:///home/exo/.m2/repository/org/exoplatform/archetype/empty-extension-packaging-addon/1.0.0-SNAPSHOT/empty-extension-packaging-addon-1.0.0-SNAPSHOT.zip",
        vendor: "eXo",
        license: "LGPLv3",
        licenseUrl: "https://www.gnu.org/licenses/lgpl-3.0.txt",
        mustAcceptLicense: false,
        supportedDistributions: "community,enterprise",
        supportedApplicationServers: "tomcat",
        compatibility: "[4.1.0-RC1,)"
    }
]
</code></pre>

<p>As you see we include the full path to the built maven artifact:</p>

<pre><code>/home/exo/.m2/repository/org/exoplatform/archetype/empty-extension-packaging-addon/1.0.0-SNAPSHOT/empty-extension-packaging-addon-1.0.0-SNAPSHOT.zip
</code></pre>

<p>as 'maven install' command will compile, assemble and install the artifact to exo's user maven repository in the codenvy custom runner Docker conrtainer.</p>

<p>You have 2 choices now:</p>

<ul>
<li>include the local.json file in your source code repository</li>
<li>include it in your docker recipe repository</li>
</ul>

<p>Basically, choose the first option if you have control over the source code repository (ie: you own the repository, or you are ok with forking it), choose the second option if you don't have control over the source code repository and you don't want to fork it.</p>

<p>Docker Images' names are in Bold, except for the ephemeral image built by Codenvy at runtime which is unpublished and therefore doesn't have a name.</p>

<p>One of the main reasons we choose to put most of the content on pre built Docker images (i.e.: images we then pull from the DockerHub repository) as opposed to delegating it to the Codenvy custom runner DockerFile, is to speed up startup times for the custom runner.</p>

<p>As the Codenvy custom runner Docker image is built every time you start the runner, we save a substantial amout of  startup time by having most of its contents pre built at the Dockerhub repository. This is especially true for a large platform such as eXo or platforms which require lots of additional components downloaded and installed (i.e.: MongoDb, Databases etc.).</p>

<p>Find below diagram for option 1: <br>
<img src="https://blog.teknologism.com/content/images/2014/11/eXoDockersOption1-5.png" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>The second option is a bit more difficult as you will have to build an intermediate Dockerfile repository to include the local.json file.</p>

<p>Find below diagram shown earlier, modified for option 2:</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/eXoDockersOption2-3.png" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p><b>NOTE: I highly recommend using the first option. Only use the second option as a last resort, as it adds another docker intermediate image.</b></p>

<p><br></p>

<h4 id="firstoptionincludethelocaljsonfileinyoursourcecoderepository">First option: include the local.json file in your source code repository</h4>

<p>We will assume the local.json file is at the root of your source code repository.</p>

<p>In this example, for an empty eXo extension the Dockerfile will have this content:</p>

<pre><code>FROM teknologist/exo-maven-setup-done

ENV EXOADDON_SRC_DIR /home/${EXO_USER}/src 

USER exo
RUN mkdir -p ${EXOADDON_SRC_DIR}

#Get app src from Codenvy Project
ADD $app_src$ ${EXOADDON_SRC_DIR}/app_src.zip

#ADDON: Unpack, build and install with addon manager
RUN cd ${EXOADDON_SRC_DIR} &amp;&amp; unzip -q app_src.zip &amp;&amp; \
cd ${EXOADDON_SRC_DIR} &amp;&amp; ${M2_HOME}/bin/mvn clean install -q -Dmaven.test.skip --batch-mode  &amp;&amp; \
cp ${EXOADDON_SRC_DIR}/local.json ${EXO_APP_DIR}/current/addons/
cd ${EXO_APP_DIR}/current/ &amp;&amp; \
 ./addon install exo-custom-addon:1.0.0 --offline --snapshots --unstable
</code></pre>

<p>There are 3 important instructions here:</p>

<p>This is a codenvy specific which copies your source code tree to your docker based custom runner:</p>

<pre><code>    ADD $app_src$ ${EXOADDON_SRC_DIR}/app_src.zip
</code></pre>

<p>This one adds the local.json (eXo add-on desciption) to your eXo installation:</p>

<pre><code>    cp ${EXOADDON_SRC_DIR}/local.json ${EXO_APP_DIR}/current/addons/
</code></pre>

<p>The last one installs your referenced add-on using eXo bundled addon manager:</p>

<pre><code> ./addon install exo-custom-addon:1.0.0 --offline --snapshots --unstable
</code></pre>

<p><br></p>

<h4 id="secondoptionincludelocaljsoninyourdockerreciperepository">Second option: include local.json in your docker recipe repository</h4>

<p>In this case you are going to create an intermediate docker image.</p>

<p>First create a repository on github to hold your Docker recipe files. <br>
We will assume the local.json file is at the root of your source code repository.</p>

<p>You will have 3 files:</p>

<ul>
<li>Dockerfile</li>
<li>local.json</li>
<li>README.MD (optional)</li>
</ul>

<p>The Dockerfile is super simple:</p>

<pre><code>FROM teknologist/exo-maven-setup-done
ENV EXOADDON_SRC_DIR /home/${EXO_USER}/src

USER exo  
RUN mkdir -p ${EXOADDON_SRC_DIR}
ADD local.json ${EXO_APP_DIR}/current/addons/
</code></pre>

<p>This Docker recipe simply adds the local.json to the eXo installation from the base exo-maven-setup-done Docker image.</p>

<p>Now head up to your DockerHub account and create an automated build based on the Github repository you just created.</p>

<p>You should now have a new docker image automatically built and available.</p>

<p>You can find a fully working githuib docker recipe repository example here: <a href="https://github.com/teknologist/exo-empty-addon-docker" target="_blank">https://github.com/teknologist/exo-empty-addon-docker</a></p>

<p>The corresponding DockerHub automatically built image is available here: <a href="https://registry.hub.docker.com/u/teknologist/exo-empty-addon-docker/" target="_blank">https://registry.hub.docker.com/u/teknologist/exo-empty-addon-docker/</a> </p>

<p>It's named <b>teknologist/exo-empty-addon-docker</b>.</p>

<p>Therefore the codenvy custom runner's Dockerfile, which will inherit <b>teknologist/exo-empty-addon-docker</b> image,  will have this content:</p>

<pre><code>FROM teknologist/exo-empty-addon-docker

EXPOSE 8080
ENV CODENVY_APP_PORT_8080_HTTP 8080
ENV EXOADDON_SRC_DIR /home/${EXO_USER}/src 

USER exo
RUN mkdir -p ${EXOADDON_SRC_DIR}

#Get app src from Codenvy Project
ADD $app_src$ ${EXOADDON_SRC_DIR}/app_src.zip

#ADDON: Unpack, build and install with addon manager
RUN cd ${EXOADDON_SRC_DIR} &amp;&amp; unzip -q app_src.zip &amp;&amp; \
cd ${EXOADDON_SRC_DIR} &amp;&amp; ${M2_HOME}/bin/mvn clean install -q -Dmaven.test.skip --batch-mode  &amp;&amp; \
cd ${EXO_APP_DIR}/current/ &amp;&amp; \
 ./addon install exo-custom-addon:1.0.0 --offline --snapshots --unstable
</code></pre>

<p>There are 2 important instructions here:</p>

<p>This is a codenvy specific which copies your source code tree to your docker based custom runner:</p>

<pre><code>    ADD $app_src$ ${EXOADDON_SRC_DIR}/app_src.zip
</code></pre>

<p>The last one installs your referenced add-on using eXo bundled addon manager:</p>

<pre><code> ./addon install exo-custom-addon:1.0.0 --offline --snapshots --unstable
</code></pre>

<p><b>NOTE:</b> We don't have to deal with the local.json file anymore as it is already included in the intermediate image.</p>

<p><br></p>

<h2 id="publishingthecodenvycustomrunnerdockerfile">Publishing the Codenvy custom runner Dockerfile</h2>

<p><br></p>

<p>For the rest of the tutorial we will use Option 1. </p>

<p>Therefore our custom runner Dockerfile looks like this:</p>

<pre><code>FROM teknologist/exo-empty-addon-docker

EXPOSE 8080
ENV CODENVY_APP_PORT_8080_HTTP 8080
ENV EXOADDON_SRC_DIR /home/${EXO_USER}/src 

USER exo
RUN mkdir -p ${EXOADDON_SRC_DIR}

#Get app src from Codenvy Project
ADD $app_src$ ${EXOADDON_SRC_DIR}/app_src.zip

#ADDON: Unpack, build and install with addon manager
RUN cd ${EXOADDON_SRC_DIR} &amp;&amp; unzip -q app_src.zip &amp;&amp; \
cd ${EXOADDON_SRC_DIR} &amp;&amp; ${M2_HOME}/bin/mvn clean install -q -Dmaven.test.skip --batch-mode  &amp;&amp; \
cp ${EXOADDON_SRC_DIR}/local.json ${EXO_APP_DIR}/current/addons/ &amp;&amp; \
cd ${EXO_APP_DIR}/current/ &amp;&amp; \
 ./addon install exo-custom-addon:1.0.0 --offline --snapshots --unstable
</code></pre>

<p>We need to publish this as an http available resource. We will choose a Github Gist as it is flexible, lets you maintain revisions and doesn't need any infrastructure management on your side.</p>

<p>I have published this Dockerfile as Gist on my account. It is available here: <a href="https://gist.github.com/teknologist/ff5ae3149acbe0dab1b7" target="_blank" title="Dockerfile Gist">Dockerfile Gist</a>  </p>

<p>And the raw Gist URL needed by the factory.json file is: <a href="https://gist.githubusercontent.com/teknologist/3b4efacda5cedaf37128/raw/da75fb43f306bfa2a0940d2fc185c2cfcf81d6a8/Dockerfile" target="_blank" title="Dockerfile Raw Gist for factory.json URL referencing">Dockerfile Gist for factory.json</a></p>

<p><br></p>

<h2 id="assemblingthefactoryfilefactoryjson">Assembling the Factory file: factory.json</h2>

<p><br></p>

<p>The factory.json configuration file looks like this:</p>

<pre><code>{
    "project": {
        "name": "eXoEmptyExtensionAddOn",
        "visibility": "public",
        "type": "maven",
         "builders":{
         "default":"maven"
      },
        "runners":{
            "configs":{
                "project:/docker/exo-empty-extension":{
                    "ram":4096,
                    "variables":{

                    },
                    "options":{

                    }
                }
            },
            "default":"project:/docker/exo-empty-extension"
        },
        "description":"eXo Platform 4.1 with an empty addon skeleton.",
        "attributes": {}
    },
    "source": {
        "project": {
            "location": "https://github.com/teknologist/exo-empty-extension.git",
            "type": "git",
            "parameters": {
                "commitId": "1c8d67612df4c2d388f82c18d3f22a0e5d96d5ca"
            }
        },
        "runners": {
            "/docker/exo-empty-extension" : {
                "location" : "https://gist.githubusercontent.com/teknologist/ff5ae3149acbe0dab1b7/raw/2958a761771a4dee5625d07812fa297dd4743514/exo-empty-extension-docker-runner"
            }
        }
    },
    "actions": {

            "findReplace" : [
            {
                "files" : [
                "pom.xml"
                ],
                "entries" : [
                {
                    "find":"&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;",
                    "replace" : "&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt; &lt;repositories&gt;&lt;repository&gt;&lt;id&gt;exo-public-repository-group&lt;/id&gt;&lt;name&gt;eXo Public Maven Repository Group&lt;/name&gt;&lt;url&gt;http://repository.exoplatform.org/public&lt;/url&gt;&lt;layout&gt;default&lt;/layout&gt;&lt;releases&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;updatePolicy&gt;never&lt;/updatePolicy&gt;&lt;/releases&gt;&lt;snapshots&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;updatePolicy&gt;never&lt;/updatePolicy&gt;&lt;/snapshots&gt;&lt;/repository&gt;&lt;/repositories&gt;",
                    "replacemode" : "text_multipass"
                }
                ]

            }

            ]
  },
    "variables": [],
    "v": "2.0"
}
</code></pre>

<p>The important lines here are:</p>

<pre><code>"visibility": "public"
</code></pre>

<p>Obviously makes your Factory publicly visible/shareable.</p>

<pre><code>"type": "maven"
</code></pre>

<p>This example project is of type maven </p>

<pre><code>        "builders":{
            "default":"maven"
        },
</code></pre>

<p>Builder defaults to maven. This is for building the addon in Codenvy's Editor (distinct from the build we execute later on in the custom runner)</p>

<p>Then we define the project source code repository and custom runner we have created earlier in the tutorial.</p>

<p>This is done here:</p>

<pre><code>"source": {
    "project": {
        "location": "https://github.com/teknologist/exo-empty-extension.git",
        "type": "git",
        "parameters": {
            "commitId": "1c8d67612df4c2d388f82c18d3f22a0e5d96d5ca"
        }
    },
    "runners": {
        "/docker/exo-empty-extension" : {
            "location" : "https://gist.githubusercontent.com/teknologist/ff5ae3149acbe0dab1b7/raw/2958a761771a4dee5625d07812fa297dd4743514/exo-empty-extension-docker-runner"
        }
    }
}
</code></pre>

<p>And then set up the default runner here together with its memory resources (other options/variables may be added. See Codenvy Documentation):</p>

<pre><code>"runners":{
            "configs":{
                "project:/docker/exo-empty-extension":{
                    "ram":4096,
                    "variables":{
                    },
                    "options":{
                    }
                }
            },
            "default":"project:/docker/exo-empty-extension"
}
</code></pre>

<p><b>NOTE: We added a find/replace section to add the eXo maven repository to the pom.xml files as eXo dependencies are not in the public maven repository. That is not an issue when the built is executed in the runner as we have included the repository in the maven settings.xml. <br>
Nevertheless, it is currently impossible to customize maven in Codenvy's IDE builder. Therefore we use this trick to be able to build using Codenvy's maven based builtin builder.</b></p>

<p>The final result for a Tracked Factory looks like this:</p>

<pre><code>{
        "project": {
            "name": "eXoEmptyExtensionAddOn",
            "visibility": "public",
            "type": "maven",
             "builders":{
             "default":"maven"
          },
            "runners":{
                "configs":{
                    "project:/docker/exo-empty-extension":{
                        "ram":4096,
                        "variables":{

                        },
                        "options":{

                        }
                    }
                },
                "default":"project:/docker/exo-empty-extension"
            },
            "description":"eXo Platform 4.1 with an empty addon skeleton.",
            "attributes": {}
        },
        "source": {
            "project": {
                "location": "https://github.com/teknologist/exo-empty-extension.git",
                "type": "git",
                "parameters": {
                    "commitId": "1c8d67612df4c2d388f82c18d3f22a0e5d96d5ca"
                }
            },
            "runners": {
                "/docker/exo-empty-extension" : {
                    "location" : "https://gist.githubusercontent.com/teknologist/ff5ae3149acbe0dab1b7/raw/2958a761771a4dee5625d07812fa297dd4743514/exo-empty-extension-docker-runner"
                }
            }
        },
        "creator":{
            "name":"Your name",
            "email":"youremail@yourdomain.com",
            "accountId":"accountxxxxxxxxxxxx"
        },
        "actions": {
              "welcome": {
                   "authenticated": {
                   "title": "Welcome",
                   "contenturl": "https://dl.dropboxusercontent.com/u/663951/codenvy-exo/exo-empty-addon.html"
              },
             "nonauthenticated": {
                "title": "Welcome",
                "contenturl": "https://dl.dropboxusercontent.com/u/663951/codenvy-exo/exo-empty-addon.html"
             }
          },
            "findReplace" : [
                {
                    "files" : [
                    "pom.xml"
                    ],
                    "entries" : [
                    {
                        "find":"&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;",
                        "replace" : "&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt; &lt;repositories&gt;&lt;repository&gt;&lt;id&gt;exo-public-repository-group&lt;/id&gt;&lt;name&gt;eXo Public Maven Repository Group&lt;/name&gt;&lt;url&gt;http://repository.exoplatform.org/public&lt;/url&gt;&lt;layout&gt;default&lt;/layout&gt;&lt;releases&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;updatePolicy&gt;never&lt;/updatePolicy&gt;&lt;/releases&gt;&lt;snapshots&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;updatePolicy&gt;never&lt;/updatePolicy&gt;&lt;/snapshots&gt;&lt;/repository&gt;&lt;/repositories&gt;",
                        "replacemode" : "text_multipass"
                    }
                    ]

                }

                ]
      },
        "variables": [],
        "v": "2.0"
    }
</code></pre>

<p>Complete file available as Github Gist here:  <a href="https://gist.github.com/teknologist/5e5bec3bb2924013ac5f">https://gist.github.com/teknologist/5e5bec3bb2924013ac5f</a> <br>
  <br></p>

<h4 id="optionalmakethisfactoryatrackedfactory">OPTIONAL: Make this factory a Tracked Factory</h4>

<p>A Tracked Factory is a simple Factory where we add a special accountID that allows advanced customization options and enables analytics.</p>

<p>To make this factory a Tracked Factory we add an accountId to the creator snippet</p>

<pre><code>"creator":{
    "name":"Your name",
    "email":"youremail@yourdomain.com",
    "accountId":"accountxxxxxxxxxxxx"
}
</code></pre>

<p>In order to retrieve you accountId:</p>

<p>At this moment, you need to use our rest APIs to get your account ID. </p>

<p>The documentation on Codenvy rest APIs can be found under the API Docs: <a href="http://docs.codenvy.com/api/" target="_blank" title="Codenvy API Docs">Codenvy API Docs</a> <br>
You can easily make a call to the API and get your information.</p>

<p>Using your browser, Login under the server.</p>

<p>Once you see the dashboard, call the /api/account REST endpoint by entering the following URL: <a href="https://codenvy.com/api/account" target="_blank">https://codenvy.com/api/account</a></p>

<p>In the JSON provided in response, you have the following information:</p>

<pre><code>[
  {
    "userId" : "userxxxxxxxxxxxxxxxx",
    "roles" : [
      "account/owner"
    ],
    "accountReference" : {
      "id" : "accountxxxxxxxxxxxx",
      "links" : [
        {
          "method" : "GET",
          "rel" : "get by id",
          "href" : "http://nightly.codenvy-stg.com/api/account/accountxxxxxxxxxxxx",
          "produces" : "application/json",
          "parameters" : []
        }
      ],
      "name" : "yourusername"
    }
    ...
  }
]
</code></pre>

<p>Your Tracked Factory ID, is the value behind “id” key under “accountReference”. (Be careful, this one is different from your userID)</p>

<pre><code>accountxxxxxxxxxxxx
</code></pre>

<p>All the REST Api documentation is available here:<a href="https://codenvy.com/api-docs-ui/" target="_blank" title="Codenvy API Docs - Swagger style">Codenvy API Docs - Swagger style</a></p>

<p>We can also add a Welcome screen when using a Tracked Factory:</p>

<p>You basically create whatever html resource you want and reference it in the factory.json file.</p>

<p>It will then be displayed in the right side pane as shown below: <br>
<img src="https://blog.teknologism.com/content/images/2014/11/sidepane.png" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>For this example, I created the html resource on my DropBox Public folder account. It is available here:</p>

<p><a href="https://dl.dropboxusercontent.com/u/663951/codenvy-exo/exo-empty-addon.html" target="_blank" title="Sample welcome file served from  Dropbox">Sample welcome file served from  Dropbox</a></p>

<p><br></p>

<p>Add the welcome snippet below to the actions section :</p>

<pre><code>    "actions": {
    ...

      "welcome": {
         "authenticated": {
            "title": "Welcome",
            "contenturl": "https://dl.dropboxusercontent.com/u/663951/codenvy-exo/exo-empty-addon.html"
         },
         "nonauthenticated": {
            "title": "Welcome",
            "contenturl": "https://dl.dropboxusercontent.com/u/663951/codenvy-exo/exo-empty-addon.html"
         }
      },

      ...
</code></pre>

<p>Complete file available as Github Gist here:  <a href="https://gist.github.com/teknologist/50192fa7663df9912df7" target="_blank" title="Gist for Tracked Factory Dockerfile">Gist for Tracked Factory Dockerfile</a> <br>
<br> <br>
<br></p>

<h2 id="createthefactoryusingthefactoryjsonfile">Create the Factory using the factory.json file</h2>

<p><br></p>

<p>We now have all resources available via http (Dockefile, html welcome screens, add-on source code git repository).</p>

<p>We also created a factory.json file which describes our factory and references these resources.</p>

<p>Creating the factory is as simple as login in codenvy with the cli and issuing a codenvy create-factory command.</p>

<p>This translates to:</p>

<pre><code># codenvy login
Username: yourusername
Password for yourusername:*************
</code></pre>

<p>If everything is OK you should see this message:</p>

<pre><code>  Login success on default remote 'default' [https://codenvy.com]
</code></pre>

<p>Then issue (suppose you saved factory.json file as /home/user/factory.json):</p>

<pre><code>   codenvy create-factory /home/user/factory.json
</code></pre>

<p>If the command is successful it should output a Factory URL:</p>

<pre><code>   Factory URL: https://codenvy.com/f?id=6r7mhjhjhsd444nlv
</code></pre>

<p><br></p>

<p><b>NOTE: The Factory URL above is obviously invalid. Launching it would yield to invalid factory URL message</b> <br>
<br></p>

<h2 id="useorshareyourfactory">Use or share your Factory</h2>

<p><br></p>

<p>Open the produced URL in a modern browser and you'll have a temporary workspace with your project sources and runner configured.  </p>

<p>In order to build the add'on, hit the [BUILD] button: <br>
<img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-40-37.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>In order to deploy and run, hit the [RUN] button: <br>
<img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-40-41.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>You are done. <br>
You may now share that URL with anyone you want. <br>
It will open in a temporary workspace and the user will have the choice to persist it.</p>

<h4 id="ifyoubuildtheproject">If you BUILD the project:</h4>

<p>Codenvy will use its builtin maven builder to compile and package the project using its pom.xml files. With this eXo sample, this is made possible because we added via the find/replace factory feature the eXo maven repositories.</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-17-06-54.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>Your should see a "BUILD SUCCESS" message.</p>

<h4 id="ifyouruntheproject">If you RUN the project:</h4>

<p>Codenvy will first build your Docker image based Custom runner (This might take some time depending on the docker images cache status and size/complexity of the image):</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-43-40.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>It will then deploy your eXo add-on using eXo's bundled add-on manager:</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-45-04.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>Then it will start eXo Platform:</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-45-24.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>Wait a bit for eXo to finish starting up (around 60s currently on Codenvy) and Click on the URL displayed in blue by Codenvy for the Application :</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-47-57.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>You should be greated with the eXo Login Screen:</p>

<p><img src="https://blog.teknologism.com/content/images/2014/11/Screen-Shot-2014-11-26-at-16-49-06.PNG" alt="Creating a Codenvy Factory  for eXo extensions development using Docker"></p>

<p>As stated in the Docker Image README file for the base image, default credentials are:</p>

<p>Default usernames and password:</p>

<p>Normal user :</p>

<ul>
<li>username: exo</li>
<li>password: password</li>
</ul>

<p>Administrative user:</p>

<ul>
<li>username: root</li>
<li>password: password</li>
</ul>

<p><br></p>

<p><strong>That is all for the now.</strong></p>

<p>More on Codenvy: <a href="http://bit.ly/1ATPXR0" target="_blank" title="Codenvy">Codenvy Homepage</a></p>

<p>I would like to thank <a href="https://twitter.com/stevanlm" target="_blank" title="Stevan Le Meur" style="color:black;">Stevan Le Meur</a>, <a href="https://twitter.com/tylerjewell" target="_blank" title="Tyler Jewell" style="color:black;">Tyler Jewell</a>, <a href="https://twitter.com/benjmestrallet" target="_blank" title="Benjamin Mestrallet" style="color:black;">Benjamin Mestrallet</a>, <a href="https://twitter.com/andrew00x" target="_blank" title="Andrey Parfonov" style="color:black;">Andrey Parfonov</a> and  <a href="https://twitter.com/karlsson82" target="_blank" title="Eugene Ivantsov" style="color:black;">Eugene Ivantsov</a> from Codenvy for their precious help throughout the project.</p>

<p><strong>Thanks for reading, sharing, +1 ing etc...</strong></p>

<p><br></p>]]></content:encoded></item><item><title><![CDATA[Apache 2 or Nginx as a highly secure (PFS) SSL encrypting reverse proxy for eXo Platform 4.0 or any other web application]]></title><description><![CDATA[<p><br> <br>
The goal of this tutorial is to explain, including all the subtleties, how to run eXo Platform 4 behind a reverse Proxy using Apache 2 or Nginx on GNU/Linux (Debian).</p>

<p><br> <br>
The goals of the Reverse Proxy are:</p>

<ul>
<li>Securing the eXo platform by hiding it behind the proxy</li>
<li>Offloading SSL</li></ul>]]></description><link>https://blog.teknologism.com/nginx-apache-exo/</link><guid isPermaLink="false">30d9ceab-1d68-4768-9419-e1760451cef7</guid><category><![CDATA[nginx]]></category><category><![CDATA[apache]]></category><category><![CDATA[exo platform]]></category><category><![CDATA[social]]></category><category><![CDATA[exo]]></category><category><![CDATA[security]]></category><category><![CDATA[ssl]]></category><category><![CDATA[debian]]></category><category><![CDATA[proxy]]></category><category><![CDATA[ubuntu]]></category><dc:creator><![CDATA[Eric]]></dc:creator><pubDate>Tue, 08 Apr 2014 08:00:00 GMT</pubDate><content:encoded><![CDATA[<p><br> <br>
The goal of this tutorial is to explain, including all the subtleties, how to run eXo Platform 4 behind a reverse Proxy using Apache 2 or Nginx on GNU/Linux (Debian).</p>

<p><br> <br>
The goals of the Reverse Proxy are:</p>

<ul>
<li>Securing the eXo platform by hiding it behind the proxy</li>
<li>Offloading SSL encryption to the proxy and supporting Perfect Forward Secrecy</li>
<li>Using advanced modules such as:
<ul><li>caching modules</li>
<li>security modules:
<ul><li>mod_security on apache or naxsi web application firewall on nginx</li></ul></li>
<li>Google's mod pagespeed, etc.</li>
<li>Google SPDY 3.1 (only stable on Nginx at the moment)</li></ul></li>
</ul>

<p><br> <br>
Using advanced modules is beyond the scope of this topic and might be included in a future post. <br>
<br> <br>
All the instructions below are valid for any Web server. For instance it is valid for Hudson/Jenkins install,  the Atlassian webapps such as Jira, Fisheye, Bamboo etc. It should also work with your own webapp running on any platform. It is pure http proxying. </p>

<p>For the sake of simplicity we'll use the eXo platform installed in directory EXO_PLATFORM running on default port 8080. <br>
<br></p>

<p>More information on this great enterprise social portal platform here:</p>

<p><strong><a href="http://www.exoplatform.com">http://www.exoplatform.com</a></strong></p>

<p>At the time of this writing the latest community release is 4.0.5 available in 12 languages. </p>

<p>Let's move on to the main event of the evening! <br>
<br></p>

<h2 id="gettingstarted">Getting Started</h2>

<p><strong>Requirements:</strong></p>

<ul>
<li>Basic knowledge of GNU/Linux (Debian specially as instructions will be given for Debian based distributions but may be easily applicable for RedHat/CentOS using the yum package manager)</li>
<li>Being familiar with Apache or Nginx configuration directives</li>
<li>eXo Platform installed and running on Tomcat (using public platform distribution) listening on port 8080</li>
<li>Debian server(s) installed and running.</li>
</ul>

<h2 id="preliminarysteps">Preliminary steps</h2>

<p><strong>Installing required components/servers</strong></p>

<p>The reverse proxy (Nginx or Apache) can be installed on the same server as eXo or on a separate server. <br>
Nevertheless, it is highly recommended to install the proxy on a dedicated server as it will be more secure. In fact, running the proxy on another server will allow to only expose the proxy ports (80 &amp; 443) to the "outside" world and keep eXo only listening to the internal infrastructure requests. </p>

<ul>
<li>Enough with the words. Let's see what it looks like:</li>
</ul>

<p><br></p>

<p><img src="https://blog.teknologism.com/content/images/2014/Apr/eXoReverseProxy-.png" alt=""></p>

<p><br></p>

<h2 id="installingthereverseproxy">Installing the Reverse Proxy</h2>

<p>First you have to choose between Nginx or Apache 2. I personnally favor Nginx as it has a lot better support for cuttting edge web technologies such as websockets, streaming, SPDY 3 etc. Moreover, it seems it scales very well while keeping a smaller memory footprint.</p>

<ul>
<li>On Debian/Ubuntu install the proxy:</li>
</ul>

<p><strong>For Nginx:</strong></p>

<p>For Debian/Ubuntu, in order to authenticate the nginx repository signature and to eliminate warnings about missing PGP key during installation of the nginx package, it is necessary to add the key used to sign the nginx packages and repository to the apt program keyring. Please download this key from our web site, and add it to the apt program keyring with the following command:</p>

<pre><code>sudo apt-key add nginx_signing.key
</code></pre>

<p>For Debian replace codename with Debian distribution codename (i.e.: wheezy), and append the following to the end of the /etc/apt/sources.list file:</p>

<pre><code>deb http://nginx.org/packages/debian/ codename nginx
deb-src http://nginx.org/packages/debian/ codename nginx
</code></pre>

<p>For Ubuntu replace codename with Ubuntu distribution codename, and append the following to the end of the /etc/apt/sources.list file:</p>

<pre><code>deb http://nginx.org/packages/ubuntu/ codename nginx
deb-src http://nginx.org/packages/ubuntu/ codename nginx
</code></pre>

<p>For Debian/Ubuntu run the following commands:</p>

<pre><code>apt-get update
apt-get install nginx
</code></pre>

<p>NOTE: These instructions come straight from Nginx official documentation: <a href="http://nginx.org/en/linux_packages.html#mainline">http://nginx.org/en/linux_packages.html#mainline</a></p>

<p><strong>For Apache 2:</strong></p>

<pre><code>sudo apt-get install apache2
sudo apt-get install libapache2-mod-proxy-html 
</code></pre>

<p>After successful install you need to activate mod<em>ssl and mod</em>proxy_http and it's dependencies. This is easily done on Debian:</p>

<pre><code>sudo a2enmod proxy_http
sudo a2enmod ssl
</code></pre>

<p><br>  </p>

<h2 id="configuringthevirtualhostforexosfrontend">Configuring the Virtual Host for eXo's frontend</h2>

<p>Let's assume your eXo platform installation is reachable at the following address:</p>

<pre><code>https://exo.mydomain.com
</code></pre>

<p>We'll also assume you have a Certificate and Private key for ssl encryption located at /etc/ssl/certs/exo.mydomain.com.crt and /etc/ssl/private/exo.mydomain.com.key</p>

<p>Last but not least, as shown on the diagram above we'll assume the proxy server's IP address is 192.168.1.1 and the eXo Platform server's IP address is 192.168.1.2.</p>

<p>Please adapt to your infrastructure's hostname (exo.mydomain.com) and IP addresses if need be.</p>

<p><strong>On Nginx:</strong></p>

<p>Create a file called exo.mydomain.com.conf in:</p>

<pre><code>   /etc/nginx/conf.d
</code></pre>

<p>with the following contents:</p>

<pre><code>server {
    listen 443 default ssl;
    keepalive_timeout 70;
    server_name exo.mydomain.com;

# beginning of ssl config

    ssl_certificate  /etc/ssl/certs/exo.mydomain.com.crt;
    ssl_certificate_key  /etc/ssl/private/exo.mydomain.com.key;


# enable session resumption to improve https performance
# http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;

# Diffie-Hellman parameter for DHE ciphersuites,      recommended 2048 bits
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

# enables server-side protection from BEAST attacks
# http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html
ssl_prefer_server_ciphers on;
# disable SSLv3(enabled by default since nginx 0.8.19)     since it's less secure then TLS   http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ciphers chosen for forward secrecy and compatibility
# http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';

# enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner)
# http://blog.mozilla.org/security/2013/07/29/ocsp-   stapling-in-firefox/
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;



# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";   


 #end of ssl config


    root /var/www;

    access_log /var/log/nginx/exo.mydomain.com-access_log;
    error_log  /var/log/nginx/exo.mydomain.com-error_log;


    location / {
        try_files $uri $uri @exo;
    }


    location @exo {
        proxy_pass  http://192.168.1.2:8080;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  Host $http_host;
        proxy_set_header  X-Forwarded-Proto https;

         # By default we dont want redirect it
        proxy_redirect off;

        # Cache
        proxy_buffering off;
        proxy_cache off;

        client_max_body_size 10m;
    }
}
</code></pre>

<p>The directive <strong>try_files</strong> specifies that Nginx will try to locate the requested resource in its document root (/var/www/ in this example), if it fails to find it it will proxy the request to the @exo backend. This is quite useful as it allows you to place static files in /var/www and they will be served.</p>

<p>The directive <strong>client_max_body_size 10m;</strong> sets the maximum HTTP post size (i.e. max file size upload amongst others)</p>

<p>You can also play with caching using the following directive (Refer to NGinx documentation here <a href="http://wiki.nginx.org/ReverseProxyCachingExample">http://wiki.nginx.org/ReverseProxyCachingExample</a>):</p>

<pre><code>proxy_cache
</code></pre>

<p>This is setup is the most secure ssl setups configuration (see Forward Secrecy below) as it avoids the weak ciphers and prefers the best ones (it might be too secure for old browsers surch as Internet Explorer 6, you should not be using Internet Explorer 6 anyways). </p>

<p><strong>CREDITS: <a href="https://gist.github.com/plentz/6737338">https://gist.github.com/plentz/6737338</a></strong></p>

<p>More on Perfect Forward secrecy here: <a href="https://en.wikipedia.org/wiki/Forward_secrecy">https://en.wikipedia.org/wiki/Forward_secrecy</a> </p>

<p>You need to generate a Diffie-Hellman cert with this command (this will take some time depending on the performance of your server, adjust paths if needed):</p>

<pre><code>cd /etc/nginx/ssl
sudo openssl dhparam -out dhparam.pem 2048
</code></pre>

<p>Note: You can also enable Google's SPDY protocol if your Nginx build supports it (the packages installed from sources above have SPDY 3.1,  1.5.12 works perfectly). <br>
You can check by running nginx -V to see the compile time options. If you see spdy, then your nginx build is SPDY enabled.</p>

<p>To enable it in your eXo's virtual host , just add <strong>spdy</strong>  after the ssl directive. The configuration line (2nd line) above should look like this:</p>

<pre><code>listen 443 default ssl spdy;
</code></pre>

<p>Google's SPDY 3.1 protocol speeds considerably pages loading time. More infos here: <br>
<a href="https://code.google.com/p/mod-spdy/">https://code.google.com/p/mod-spdy/</a></p>

<p>This module is bundled in Nginx's latest mainline release (1.5.12 on April 2014). <br>
On Ubuntu you can add the following official Nginx Mainline PPA: <br>
<a href="https://launchpad.net/~nginx/+archive/development">https://launchpad.net/~nginx/+archive/development</a></p>

<p><strong>On Apache:</strong></p>

<p>Create a file called exo.mydomain.com (append .conf to the filename if running Apache version >=2.4) in /etc/apache/sites-available with the following contents</p>

<p>/etc/apache/sites-available/exo.mydomain.com(.conf) :</p>

<pre><code>&lt;VirtualHost *:443&gt;
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/exo.mydomain.com.crt
    SSLCertificateKeyFile /etc/ssl/private/exo.mydomain.com.key

    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder on
    SSLCipherSuite  "EECDH+ECDSA+AESGCM   EECDH+aRSA+AESGCM 
    EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EEDH+aRSA+SHA384
    EECDH+aRSA+SHA256 EECDH+aRSA+RC4 
    EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"

    ServerAdmin admin@mydomain.com
    ServerName exo.mydomain.com
    ProxyPassReverse /  http://192.168.1.2:8080/
    ProxyPass / http://192.168.1.2:8080/
    ProxyPreserveHost on
    ProxyRequests Off
    Header always append Access-Control-Allow-Origin: "mydomain.com"
&lt;/VirtualHost&gt;
</code></pre>

<p><br></p>

<p>Credits: <a href="https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy">https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy</a></p>

<p><br> <br>
<strong>IMPORTANT NOTE: if you host other NAMED BASED virtual hosts (multiple vhosts on one single IP address) it is advised to set eXo's Virtual Host as the default one as non TLS/SNI web clients will only see the default virtual host</strong></p>

<p><br></p>

<p>On Nginx this is supplied by the 'default' keyword in the following line:</p>

<pre><code>    listen 443 default ssl;
</code></pre>

<p>or if you enabled SPDY:</p>

<pre><code>    listen 443 default ssl spdy;
</code></pre>

<p>On Apache 2 you just need to write exo's virtual host as the first one.</p>

<h2 id="activatethevirtualhost">Activate the Virtual Host</h2>

<p><strong>For Nginx:</strong></p>

<p>If you created the config file as described above in /etc/nginx/conf.d/exo.mydomain.com.conf  you don't need to do anything else. </p>

<p><strong>For Apache:</strong></p>

<pre><code> sudo a2ensite exo.mydomain.com
</code></pre>

<p><br>  </p>

<h2 id="configuringexostomcatconnectorforreverseproxyoperations">Configuring eXo's Tomcat connector for Reverse Proxy operations</h2>

<p>Open EXO_PLATFORM/conf/server.xml and modify the port 8080 connector as follows:</p>

<pre><code>&lt;Connector address="0.0.0.0" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           enableLookups="false" 
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
maxHttpHeaderSize="8192"
acceptCount="100" 
           connectionTimeout="20000" disableUploadTimeout="true"
           URIEncoding="UTF-8"
 proxyName="exo.mydomain.com" proxyPort="443"  scheme="https" /&gt;
</code></pre>

<p>The important line is:</p>

<pre><code> proxyName="exo.mydomain.com" proxyPort="443" scheme="https" 
</code></pre>

<p>This tells Tomcat it's running behind an SSL enabled reverse proxy for which the DNS name is exo.mydomain.com and connection scheme is https. <br>
<br></p>

<h2 id="increasingmaxopenfiles">Increasing Max Open Files</h2>

<p>As this configuration is optimized for speed, the SPDY feature can lead to a vast amount of open files on Tomcat 7.</p>

<p>Therefore, depending on your GNU/Linux setup you might need to increase max open files.</p>

<p>On Debian this is done in two steps:</p>

<p>System wide:</p>

<p>Edit /etc/sysctl.conf and add/modify this entry (you may increase/decrease the values):</p>

<pre><code>fs.file-max = 70000
</code></pre>

<p>Then for the user running eXo platform:</p>

<p>Edit /etc/security/limits.conf and add (in the example below user exo is running Tomcat):</p>

<pre><code>exo       soft    nofile  50000
exo       hard    nofile  70000
</code></pre>

<p>Then check /etc/pam.d/su file and make the following line is <strong>not commented</strong>.:</p>

<pre><code>session    required   pam_limits.so
</code></pre>

<p><br></p>

<h2 id="automaticredirectionofplainhttptohttps">Automatic redirection of plain http to https</h2>

<p>Below you will find typical Apache &amp;  Nginx Rewrite rules to redirect http to https.</p>

<p>Warning:  it breaks mobile app on android (haven't tested on iOS).  Developer is aware and answered on Google playstore comment.</p>

<p>Add this on top of your virtual host configuration file:</p>

<p><strong>For Nginx:</strong></p>

<pre><code>server {
    listen 80 default;
    server_name exo.mydomain.com;
      ## redirect http to https ##
      rewrite        ^ https://exo.mydomain.com$request_uri? permanent;
}
</code></pre>

<p><strong>For Apache:</strong></p>

<pre><code>&lt;VirtualHost *:80&gt;
  ServerAdmin admin@mydomain.com
  ServerName exo.mydomain.com
  Redirect permanent / https://exo.mydomain.com/
&lt;/VirtualHost&gt;
</code></pre>

<p><br></p>

<h2 id="cherryonthecakecustomerrorpagestohandleexomaintenance">Cherry on the cake: Custom error pages to handle eXo maintenance</h2>

<p>Both Nginx and Apache can handle custom pages for http errors. Specially a nice placeholder page for error 503 for under maintenance (when the eXo Tomcat server is down or restarting).</p>

<p>This proves particularly useful to handle the scheduled downtimes occurring during offline backups where the eXo server might need to be stopped.</p>

<p>You can also, using the same method, create a custom error page for 404 not found.</p>

<p>First you need to create an html page (50x.html in the example below) and store it (together with its assets) under the document root (defined in your virtual host configuration file,  /var/www in this tutorial).</p>

<p>Than add these directives in the virtual host configuration file.</p>

<p><strong>For Nginx:</strong></p>

<pre><code>    error_page 502 @maintenance;
    error_page 503 @maintenance;
    error_page 504 @maintenance;

    location @maintenance {
          rewrite ^(.*)$ /50x.html break;
    }
</code></pre>

<p><strong>For Apache:</strong></p>

<pre><code>    ErrorDocument 502 /50x.html
    ErrorDocument 503 /50x.html
    ErrorDocument 504 /50x.html
</code></pre>

<p><br></p>

<h2 id="resultqualyssslaudit">Result: Qualys SSL Audit</h2>

<p><strong>For the Nginx configuration above:</strong>
<img src="https://blog.teknologism.com/content/images/2014/Apr/qualys_ssl-1.png" alt=""></p>

<p><a href="https://www.dropbox.com/s/c8fft7zfu4lnuqj/qualySSL_FullAudit.pdf">Full Audit in PDF format available here</a></p>

<p>You can test your installation at: <a href="https://www.ssllabs.com/ssltest/analyze.html">https://www.ssllabs.com/ssltest/analyze.html</a></p>

<p><br></p>

<p><strong>That is all for the now.</strong></p>

<p><strong>Stay tuned for additions to this tutorial and other posts related to JavaEE, Systems, Networks and Software architecture.</strong></p>

<p><strong>Thanks for reading, sharing, +1 ing etc...</strong></p>

<p><br></p>]]></content:encoded></item></channel></rss>