2008/11/29

Nexus on debian

Nexus is very cool Maven Repository Manager, and debian is as cool server OS platform. I tried to match them. There was some pain, however finally I succeeded :).

Nexus is bundled as war now, thus the description is about installing it on tomcat.

In case of using debian etch (current stable), you may consider installing jdk 1.6 from backports. With jdk 1.6 you have to specify new JAVA_HOME=/usr/lib/jvm/java-6-sun in /etc/default/tomcat5.5.

Debian's tomcat has security manager turned on by default. Of course it could be easily disabled in /etc/default/tomcat5.5, however I feel safer when it is turned on :). Establishing security policy is not easy. My solution to the problem is based on work described in Mark Petrovic's article. I tweaked it a bit not to generate redundant rules. In case of nexus the resulting file looks as follows:

grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/WEB-INF/classes/logging.properties", "read";
};

grant codeBase "file:${catalina.base}/webapps/nexus/WEB-INF/lib/-" {
    permission java.util.PropertyPermission "*", "read,write";
    permission java.io.FilePermission "/", "read";
    permission java.io.FilePermission "${catalina.base}/logs", "read";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/localhost/nexus/WEB-INF/plexus.properties", "read";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/localhost/nexus/WEB-INF/plexus.xml", "read";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/WEB-INF/log4j.properties", "read";
    permission java.io.FilePermission "${catalina.base}/temp", "read,write";
    permission java.io.FilePermission "${catalina.base}/temp/-", "read,write,delete";
    permission java.lang.RuntimePermission "defineClassInPackage.java.lang", "";
    permission java.lang.RuntimePermission "createClassLoader", "";
    permission java.lang.RuntimePermission "setContextClassLoader", "";
    permission java.lang.RuntimePermission "accessDeclaredMembers", "";
    permission java.lang.RuntimePermission "getenv.*", "";
    permission java.lang.RuntimePermission "accessClassInPackage.sun.misc", "";
    permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect", "";
    permission java.lang.RuntimePermission "reflectionFactoryAccess", "";
    permission java.lang.RuntimePermission "getClassLoader", "";
    permission java.lang.RuntimePermission "modifyThread", "";
    permission java.io.FilePermission "${catalina.home}/sonatype-work", "read,write";
    permission java.io.FilePermission "${catalina.home}/sonatype-work/-", "read,write,delete";
    permission java.net.SocketPermission "*", "connect,resolve";
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks", "";
    permission java.util.logging.LoggingPermission "control", "";
};

grant codeBase "file:${catalina.base}/webapps/nexus/WEB-INF/classes/-" {
    permission java.util.PropertyPermission "*", "read,write";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/localhost/nexus/WEB-INF/plexus.properties", "read";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/localhost/nexus/WEB-INF/plexus.xml", "read";
    permission java.io.FilePermission "${catalina.base}/webapps/nexus/WEB-INF/log4j.properties", "read";
    permission java.io.FilePermission "${catalina.home}/sonatype-work", "read,write";
    permission java.io.FilePermission "${catalina.home}/sonatype-work/-", "read,write,delete";
    permission java.lang.RuntimePermission "getenv.*", "";
    permission java.lang.RuntimePermission "defineClassInPackage.java.lang", "";
    permission java.lang.RuntimePermission "createClassLoader", "";
    permission java.lang.RuntimePermission "setContextClassLoader", "";
    permission java.lang.RuntimePermission "accessDeclaredMembers", "";
    permission java.lang.RuntimePermission "modifyThread", "";
    permission java.util.logging.LoggingPermission "control", "";
};

Copy these rules into 60nexus.policy file and place it in /etc/default/tomcat5.5. Restart of JVM is required to make these rules effective.

The line:

permission java.io.FilePermission "/", "read";

is redundant with other rules. The need of reading the whole filesystem seems to be a security flaw. I hope it will be eliminated in future nexus releases. I will fill the bug for this.

These security rules should work ok not only on debian, but also on any other system where tomcat is deployed. There are two system properties in use: catalina.home and catalina.base. This seems to be debian specific. In case of other systems catalina.home should be enough.

Nexus would create sonatype-work directory in user.home which is /usr/share/tomcat5.5 in case of debian. However with security manager we have to create it by ourselves.

host# mkdir /var/opt/sonatype-work
host# chown tomcat55:adm /var/opt/sonatype-work
host# ln -s /var/opt/sonatype-work /usr/share/tomcat5.5

The /var/opt/sonatype-work will become storage which should be backed up carefully when nexus is used not only as proxy, but also as local maven repository.

Now we can download the latest nexus from http://nexus.sonatype.org/using/download.html

Create logging.properties file with the following contents:

org.apache.juli.FileHandler.level = WARNING
java.util.logging.ConsoleHandler.level = WARNING

and put it into WEB-INF/classes inside the war.

Without this modification nexus would log every single HTTP request on console which would be redirected to catalina.out log file. To much verbose default logging seems to be another nexus bug.

Strip the version number from war file, stop tomcat with:

host# /etc/init.d/tomcat5.5 stop

Put nexus.war in /var/lib/tomcat5.5/webapps.

host# /etc/init.d/tomcat5.5 start

Nexus should be visible at http://debianhost:8180/nexus/

Upgradges should be as easy as putting new nexus war in webapps.

1 comment:

  1. Anonymous4/3/09 20:58

    Great post, I found it very useful. Thanks.

    ReplyDelete