1.3. Adjustments (optional)

1.3.1. Enable SSL/HTTPS

Enabling SSL is highly recommended on live systems, as it protects sensitive information, like passwords, to be sent plain over the Internet, making it readable by eavesdroppers. If the Tomcat server is directly used from the Internet, to enable SSL / HTTPS you first have to enable (un-comment) the https connector in the file <tomcat_home>/conf/server.xml

<Connector port="443" maxHttpHeaderSize="8192"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" disableUploadTimeout="true"
    acceptCount="100" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS" />

Generate a key with the keytool from Java:

$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA -keystore /path/to/my/keystore

After executing this command, you will first be prompted for the keystore password. Passwords are *case sensitive*. You will also need to specify the custom password in the server.xml configuration file, as described later. Next, you will be prompted for general information about this Certificate, such as company, contact name, and so on. This information will be displayed to users who attempt to access a secure page in your application, so make sure that the information provided here matches what they will expect. Finally, you will be prompted for the key password, which is the password specifically for this Certificate (as opposed to any other Certificates stored in the same keystore file). You MUST use the same password here as was used for the keystore password itself. (Currently, the keytool prompt will tell you that pressing the ENTER key does this for you automatically). If everything was successful, you now have a keystore file with a Certificate that can be used by your server.

1.3.2. Adjust Tomcat/Java memory

The default memory heap size of Tomcat is very low. You can augment this in the following way:

Windows

In the bin directory of Tomcat create (if it doesn't exist) a file called setenv.bat, edit this file and add the following line:

set JAVA_OPTS=-Xms128m -Xmx512m -XX:MaxPermSize=128M

Linux

In the bin directory of Tomcat create (if it doesn't exist) a file called setenv.sh, edit this file and add the following line:

JAVA_OPTS="-Xms128m -Xmx512m -XX:MaxPermSize=128M"

1.3.3. Clustering

Clustering is useful both for scaling (serving more requests) and for high availability (if a server crashes, the application continues to run). The main reason for configuring a cluster in Tomcat is to replicate HTTP sessions. Cyclos, however, doesn't use Tomcat sessions, but handles them internally. This way, there is no special Tomcat configuration to support a Cyclos cluster.

The Cyclos application, however, needs some small configurations to enable clustering. Cyclos uses Hazelcast to synchronize aspects (such as caches) between cluster servers. To enable clustering, find in cyclos.properties the line containing cyclos.clusterHandler, and set it to hazelcast.

Some extra configuration can be performed in the WEB-INF/classes/hazelcast.xml file. Basically, if the local network runs more than a single Cyclos instance, the group needs to be configured. Configure all files belonging to the same group with the same group name and password. It is also possible to change the default multicast to TCP/IP communication. Just comment the <multicast> tag and uncomment the <tcp-ip> tag, setting up the hosts / ports which will be part of the cluster. For a TCP/IP cluster, Hazelcast needs the host name / port of at least one node already in a cluster (it is not necessary to set all other nodes on each node).

To setup high-availability at database (Postgresql) level, please, refer to this document.

1.3.4. Use Apache as frontend for Tomcat

You can use apache as a front-end / load balancer for the tomcat. This is very usefull when you have several domains configured on the server. There are several documentations and examples available on the internet, in our example we will use the mod_jk library for apache.

sudo apt-get install apache2 libapache2-mod-jk

The configuration is done on the file /etc/libapache2-mod-jk/workers.properties. By default this is configured to use the AJP port 8009, this is the default ajp port for tomcat, if you are using a different port you need to configure here.

On tomcat we need to enable the ajp connector. Edit the file tomcat/conf/server.xml and uncomment the AJP connector:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Now on apache we need to configure the virtualhost to use the ajp connector. On the virtualhost of your domain add the following lines:

        <IfModule mod_jk.c>
            JkMount /* ajp13_worker
            JkMount / ajp13_worker      
        </IfModule>            
        

This example uses the cyclos as ROOT application on tomcat. If you want to use something like http://www.yourdomain.com/cyclos we need to deploy cyclos on the webapps/cyclos directory and configure apache like this:

        <IfModule mod_jk.c>
            JkMount /cyclos/* ajp13_worker
            JkMount /cyclos ajp13_worker    
        </IfModule>            
        

Now restart both apache and tomcat and check if it works.

1.3.5. Enable SSL on apache

Enabling SSL is highly recommended on live systems, as it protects sensitive information, like passwords, to be sent plain over the Internet, making it readable by eavesdroppers. If you are using apache as a front-end for the tomcat first you need to enable the ssl module.

sudo a2enmod ssl

After enable the module we need to configure the virtualhost to use the ssl. On the virtualhost of your domain add the following lines:

NameVirtualhost www.yourdomain.org:443
<VirtualHost www.yourdomain.org:443>
ServerAdmin youremail@yourdomain.org
ServerName www.yourdomain.org
DocumentRoot /var/www/

<Directory />
        Options FollowSymLinks
        AllowOverride All
</Directory>
<Directory /var/www/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
</Directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
</Directory>

ErrorLog /var/log/apache2/domain_error.log
LogLevel warn
CustomLog /var/log/apache2/domain_access.log combined

<IfModule mod_ssl.c>
       SSLEngine on
       SSLProtocol ALL -SSLv2 -SSLv3
       SSLHonorCipherOrder On
       SSLCipherSuite ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH
       ServerSignature Off
       BrowserMatch ".*MSIE.*" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
       SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
       SSLCertificateFile /etc/ssl/certs/yourcertificate.crt
       SSLCertificateKeyFile /etc/ssl/private/yourkey.key        
</IfModule>
</VirtualHost>            
        

Now we need to generate the certificate, in this example we will use a self-signed certificate, normally used to test your new SSL implementation

Generate a Private Key

The utility "openssl" is used to generate the key and CSR. This utility comes with the OpenSSL package and is usually installed under /usr/local/ssl/bin. If the utility was installed elsewhere, these instructions will need to be adjusted accordingly.

Type the following command at the prompt:

        openssl genrsa -des3 -out yourkey.key 2048

Generate a CSR (Certificate Signing Request)

Once the private key is generated a Certificate Signing Request can be generated. The CSR is then used in one of two ways. Ideally, the CSR will be sent to a Certificate Authority, such as Thawte or Verisign who will verify the identity of the requestor and issue a signed certificate. The second option is to self-sign the CSR, which will be demonstrated in the next section.

During the generation of the CSR, you will be prompted for several pieces of information. These are the X.509 attributes of the certificate. One of the prompts will be for "Common Name (e.g., YOUR name)". It is important that this field be filled in with the fully qualified domain name of the server to be protected by SSL. If the website to be protected will be https://public.akadia.com, then enter public.akadia.com at this prompt. The command to generate the CSR is as follows:

            openssl req -new -key yourkey.key -out yourcertificate.csr
        
            Country Name (2 letter code) [GB]:CH
            State or Province Name (full name) [Berkshire]:Bern
            Locality Name (eg, city) [Newbury]:Oberdiessbach
            Organization Name (eg, company) [My Company Ltd]:Akadia AG
            Organizational Unit Name (eg, section) []:Information Technology
            Common Name (eg, your name or your server hostname) []:public.akadia.com
            Email Address []:martin dot zahn at akadia dot ch
            Please enter the following extra attributes
            to be sent with your certificate request
            A challenge password []:
            An optional company name []:
       

Remove Passphrase from Key

One unfortunate side-effect of the pass-phrased private key is that Apache will ask for the pass-phrase each time the web server is started. Obviously this is not necessarily convenient as someone will not always be around to type in the pass-phrase, such as after a reboot or crash. mod_ssl includes the ability to use an external program in place of the built-in pass-phrase dialog, however, this is not necessarily the most secure option either. It is possible to remove the Triple-DES encryption from the key, thereby no longer needing to type in a pass-phrase. If the private key is no longer encrypted, it is critical that this file only be readable by the root user! If your system is ever compromised and a third party obtains your unencrypted private key, the corresponding certificate will need to be revoked. With that being said, use the following command to remove the pass-phrase from the key:

    cp yourkey.key yourkey.key.org
    openssl rsa -in yourkey.key.org -out yourkey.key
    

The newly created yourkey.key file has no more passphrase in it.

Generating a Self-Signed Certificate

At this point you will need to generate a self-signed certificate because you either don't plan on having your certificate signed by a CA, or you wish to test your new SSL implementation while the CA is signing your certificate. This temporary certificate will generate an error in the client browser to the effect that the signing certificate authority is unknown and not trusted.

To generate a temporary certificate which is good for 365 days, issue the following command:

    openssl x509 -req -days 365 -in yourcertificate.csr -signkey yourkey.key \
    -out yourcertificate.crt
    

Installing the Private Key and Certificate

When Apache with mod_ssl is installed, it creates several directories in the Apache config directory. The location of this directory will differ depending on how Apache was compiled.

    cp yourcertificate.crt /etc/ssl/certs/yourcertificate.crt
    cp yourkey.key /etc/ssl/private/yourkey.key
    

Now restart apache and check if it works.

1.3.6. Configuring Cyclos to work behind a proxy / load balancer

When using some other proxy / load balancer in front of Tomcat other than Apache, where the AJP protocol is not available (for example, NGNIX or Amazon's Elastic Load Balancing - ELB), additional parameters in cyclos.properties are needed. The proxy will receive the first request (probably handling the SSL certificate), then create a NEW request to Tomcat. That means the client IP address received by Cyclos, as well as the request URI are different than the original request performed by the client. However, the proxy will add some extra headers, with information about the original request. Cyclos then needs to be configured to read both the IP address and the request URI (used to match configurations) from those headers, instead of reading them directly from the HTTP request. As such, the following settings in cyclos.properties are needed:

  • cyclos.header.remoteAddress: Specifies the name of the header which contains the original client's IP address. The name of this header is usually X-Forwarded-For.
  • cyclos.header.uri: Specifies the name of the header which contains the original client's requested URI. The name of this header is usually X-Forwarded-URI.

Sometimes the load balancer does periodic health check requests to Cyclos. In this case, the X-Forwarded-* headers are not sent. When Cyclos detects those headers don't have a valid value, it responds with a message, but the request has the response status 200 (OK), so the load balancer can know the service is online.

1.3.7. External content storage

1.3.7.1. Storage types

Starting with Cyclos 4.5 you have the possibility to configure the storage type to be used for images, documents and imported files.

Cyclos comes with three implementations out of the box:

  • Database: the content is stored in conjunction with all data in the database. This is the default implementation.
  • File system: the content is stored outside the database in a specific path.
  • Amazon S3: Amazon Simple Storage Service, the content is stored outside the database in a specific bucket.

Besides the built-in implementations you can create your own custom implementation. To do that you must create a Java class implementing org.cyclos.impl.storage.StoredFileContentManager

The followins are the properties you need to configure in the cyclos.properties

Storage type property

Database storage specific properties

There are no additional properties to be configured.

File system storage specific properties

  • cyclos.storedFileContentManager.rootDir: the root directory where the contents will be stored.
  • cyclos.storedFileContentManager.maxSubDirs: tha maximum count of diretories to be created below the root directory where the content will be stored.

Amazon S3 storage specific properties

  • cyclos.storedFileContentManager.bucketName: the name of the bucket to be created.
  • cyclos.storedFileContentManager.accessKeyId: the AWS access key.
  • cyclos.storedFileContentManager.secretAccessKey: the AWS secret access key.

1.3.7.2. Storage migrator utility class

If you already have a running Cyclos instance and want to change the storage type to use then there is an utility class that will allow to migrate the contents from the current storage to a new one. To use it you must have Java configured in your path then go to the <TOMCAT_DIR>/webapps/<cyclos_dir> directory and execute:

java -cp "WEB-INF/classes:../../lib/*:WEB-INF/lib/*" \
             org.cyclos.impl.storage.utils.StoredFileContentMigrator

and just follow the instructions shown in the usage help.