Centralizing Certificate Management of LetsEncrypt with a Raspberry PI

Lets Encrypt is a new Certificate Authority (CA), run for the public’s benefit by the Internet Security Research Group (ISRG). At the time of writing it’s currently in Beta and is due to go public in December 2015.

Update: Lets Encrypt went into public -beta on December 3 2015. I have updated this article with the minor change needed to work with the live servers.

Now in the default mode, the standard Lets Encrypt client (it’s not the only one) can manage this automatically – however it’s not ideal if you have more than one server.

What I describe here is how to centralize managing certificate registration (& later renewal) on a central machine. When a certificate is then registered or renewed we can then copy the certs to the remote servers.

Continue reading “Centralizing Certificate Management of LetsEncrypt with a Raspberry PI”

Java 8 running out of file handles on Linux

When I checked one of my websites this morning I discovered it had stopped responding. All it did was sit there then time out with a standard Tomcat error page. So I logged in to check the logs and found that tomcat was complaining about “Too many open files”. Now a few days earlier I had released a new version of the site which moved the serving of static content from Apache to Tomcat so that was my initial though of where the problem was.

This turns out to be true. Where I was reading a text file I was using the new Java 8 Files.line() method which returns a Stream consisting of each line in a file. Now this was nice as instead of writing a block of code to read a file into a string we could reduce it down to:

String page = Files.line( f.getPath() ).
    collect( Collectors.joining( "\n" ) ) );

The problem here is that although nice and concise, it never closes the file. So after a while the Operating System complains that too many files are open and tomcat grinds to a halt.

Now hidden away in the javadocs you’ll find tha Stream actually implements AutoClosable & the reason why is that you can close the stream once you have done with it. Now in 99% of all Streams you don’t need to do anything but if a Stream is operating against some external resource like a File then you are supposed to be closing the stream afterwards.

Now this is where I went wrong, and I suspect a lot of others would also fall foul of this as every example of using Java 8 streams do not show closing them – so who would know that they need to?

So, the correct way of reading a file using streams is this:

try( Stream lines = Files.line( path ) ) {
    // do something with the stream
}

For example, in my case it ended up looking something like this:

String page;
try( Stream lines = Files.line( f.getPath() ) ) {
    page = lines.collect( Collectors.joining( "\n" ) ) );
}

So the lesson here is make certain when using an external resource within a Stream then ensure you close it afterwards.

Installing Java 7 on Debian Squeeze

For all of my servers I use Debian, however that distribution has a few problems, mainly the packages can be a bit behind the cutting edge.

Now this is usually a good thing if you are looking for stability – cutting edge software can have issues, especially from new features etc, so for a live environment you want something thats stable.

However, there does come a time when this can bite back. You either need a feature thats not in the standard repositories or in this case the version is now unsupported.

In Debian Squeeze it has Java 6 – but that was EOL’d a couple of months ago so is no longer supported by Oracle. The current version is Java 7 update 17.

So how do we get Java 7 installed?

Well it’s pretty easy to do, we just need to add another repository into apt and install it.

First the repository:

sudo su -
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886
apt-get update
exit

What that does is to install the ubuntu ppa repository into apt, setup the public keys and then load the package lists.

Next we need to install it:

sudo apt-get install oracle-java7-installer

This will now download Oracle Java 7 and present you with a couple of screens about licensing. Just ok and accept it and it will now install.

That’s it. You now have Java 7 installed – but it’s not the default JDK (if you already had Java 6 installed). If you want it to be the default then there’s just one more thing to do:

sudo apt-get install oracle-java7-set-default

That’s a dummy package but it will make Java 7 the default on that machine. If you want to check then you can check:

peter@titan ~ $ java -version
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

Writing Servlets the J2EE 6 / Servlet 3.0 way

In the past whenever you wrote a Servlet you had a lot of work to do. First you wrote your servlet, then you had to add configuration for that servlet into web.xml so that your application would use it.

For simple applications this was fine but the more servlets you wrote the harder it became as web.xml started to become large and unwieldy.

Now with J2EE 6 you got the ability to add annotations to your servlets. No more do you need to add anything to web.xml as the container scans the classpath for any servlet that’s annotated with @WebServlet getting the required configuration from there.

This also has the benefit that you can write libraries of servlets. Those servlets get deployed automatically and you don’t have to worry about duplicating the config.

Both Tomcat 7 and TomEE 1.5.1 support the J2EE 6 Web Profile as standard. I’m not certain of other containers as I’ve only tested this on those two.

Continue reading “Writing Servlets the J2EE 6 / Servlet 3.0 way”

The problem of mixing library versions

Usually you wouldn’t mix versions. Build environments like Maven should handle this for you – although even maven can get things wrong.

Yesterday I was playing with Apache TomEE looking at migrating some webapp’s away from Apache Tomcat 7. The impetus for this was to get Rest services working and one of the TomEE profiles supports JAX-RS rest services. Tomcat only supports JAX-WS as thats in Java EE6 Web profile.

Anyhow, with the theory that the webapp’s should just run with minor config changes to the container (declaring datasources, that sort of thing) I installed TomEE and got Netbeans to deploy to it.

Bang!

None of the apps would deploy. They all complained about slf4j missing a method:

java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/Object;Ljava/lang/Throwable;)V
    at org.apache.commons.logging.impl.SLF4JLocationAwareLog.debug(SLF4JLocationAwareLog.java:133)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:221)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)

Now if you ever see this, it’s down to having mixed versions of slf4j in your classpath – and unlike Tomcat, TomEE uses the most recent version of slf4j.

The solution

Many hours later I find this article where someone had a similar problem last year: SLF4J Dependencies and LocationAwareLogger.log Method Not Found Exception.

Now my webapps also use the latest standalone tiles library for layout so after getting maven to show me the dependency tree (mvn dependency:tree) on the webapp it showed that I was pulling in an old slf4j version into the webapp.

So, with a minor change to the pom telling maven to exclude slf4j it finally worked.

Here’s the changes I ended up making to the pom:

<dependency>
  <groupId>org.apache.tiles</groupId>
  <artifactId>tiles-extras</artifactId>
  <!-- needed to exclude slf4j which causes incompatibilities -->
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <scope>provided</scope>
</dependency>

The first dependency is for tiles. The <version/> element is missing as I declare that in the project’s root pom and ensures all webapps use the same version.

The important bit is the <exclusions/> element, here we tell maven to exclude those artifacts from the war. There’s one or more <exclusion/> elements which contain just the <groupId/> and <artifactId/> elements – no <version/> here.

The second dependency is for slf4j. It’s here to allow any code provided by the war to have access to it. Again <version/> is missing as its in the root pom but we provide a <scope/> of provided. This tells maven it can use it for compiling but does not include it in the war.

Finally in the project’s other modules I just make sure that any pom with a reference to slf4j is also declared as provided so they don’t cause maven to include it either.

That’s about it. It only took me about 4 hours of hunting around to find the underlying cause. In the Windows world this is known as DLL Hell – well it can happen to any OS/Environment & it is hell when it strikes.

Notes:

  • If you use another logging library within your webapp then that shouldn’t be affected. log4j should just work, this problem appears just to be for slf4j.
  • If you use apache commons logging then you can declare that as provided if you wanted. This is because TomEE provides it at the container level as well as slf4j.

Formatting xml in emacs

I had this problem of debugging some xml but when reading the output of some log4j it was almost impossible to read so I needed some way of prettifying the xml quickly.

For this example I have the following xml:

<?xml version="1.0"?><xml><iq xmlns="jabber:component:accept" from="test1@temp.retep.org/client" id="iq_257" to="service.retep.org" type="get"><query xmlns="some:namespace"/></iq></xml>

So how do we pretify this in emacs?

Well the first thing to do is to write an extension function & place it into your ~/.emacs file. Placing it here means that when you open emacs the extension is available:

(defun xml-format ()
  (interactive)
  (save-excursion
    (shell-command-on-region (mark) (point) "xmllint --format -" (buffer-name) t)
  )
)

Now this works by passing the buffer to the xmllint utility and replaces it with the output – in this case nicely formatted xml.

Now we need to install xmllint:

pi@lindesfarne: ~$ sudo apt-get install libxml2-utils

Ok so now open emacs and open the xml. To format first select the xml you want to format then Press Escape then x followed by xml-format & press return. You should then get the xml nicely formatted:

<?xml version="1.0"?>
<xml>
  <iq xmlns="jabber:component:accept" from="test1@temp.retep.org/client" id="iq_257" to="service.retep.org" type="get">
    <query xmlns="some:namespace"/>
  </iq>
</xml>

Compiling a Kernel on the Raspberry PI

The reason I had to do this was because I needed video4linux to get a webcam working for a forcoming series of posts connecting a telescope to the pi. Although the connection to the telescope wasn’t a problem, the customized webcam I have needed it.

Here I compile the kernel on a more powerful linux box to save time then transfer the kernel over to the PI.

Also this article is mainly my personal notes on compiling a new kernel rather than a tutorial on how to do it. Writing it here makes sense to keep things together & maybe it’s useful for anyone else.

These instructions are based on the RPI Kernel Compilation available at elinux.org.
Continue reading “Compiling a Kernel on the Raspberry PI”