Rolling Out Clojure

At Box UK we try, where practical, to be technology agnostic and pick the best tool for the job. Over the next few years I see Clojure (and possibly other JVM languages like Scala) becoming more and more important in solving the problems that both we and our clients encounter.

Internally I’ve been trialling small Clojure applications and libraries for some time, but if we’re going to be rolling these out to production environments then we’re going to need a stable way to do it.

Build Problems

In our current deployment process, using RPMs for all our applications has become standard. But doing some casual Googling on how to get started building these for Clojure projects turned up very few results…There’s a plugin for Leiningen, but we use a slightly more custom process with Mock to create a clean chroot’d build environment, and I couldn’t see how this was going to work for us.

Another problem (before even being able to consider the previous plugin) is Leiningen itself. This is the de facto standard tool for managing Clojure projects, but unfortunately the packaged version is way out of date. This causes problems as our build servers need to be managed in the same way as all our other boxes: packaged software only please.

None of this is too challenging though, so I’ll go over what we put in place to effectively package Clojure applications.

Packaging Leiningen

The first step is packaging Leiningen. With the most recent version I could find being 1.7-something, we needed to roll our own, which we’ve packaged under the name boxuk-leiningen to avoid naming conflicts should an official package appear. Here’s the interesting bit:

%define _prefix /usr/share
%define _lein_version 2.1.3
%define _lein_jar leiningen-%{_lein_version}-standalone.jar
%define _lein_downloads
%define _lein_repo
curl -o %{_lein_jar} 
curl %{_lein_repo}/%{_lein_version}/bin/lein 
     | sed 's#LEIN_JAR=".*"#LEIN_JAR="%{_prefix}/%{name}/lib/%{_lein_jar}"#' 
     > lein

We’re pulling down a specific version to install globally, and tweaking the shell script to reference it:

mkdir -p $RPM_BUILD_ROOT%{_prefix}/%{name}/bin
mkdir -p $RPM_BUILD_ROOT%{_prefix}/%{name}/lib
cp lein $RPM_BUILD_ROOT%{_prefix}/%{name}/bin
cp %{_lein_jar} $RPM_BUILD_ROOT%{_prefix}/%{name}/lib
mkdir -p $RPM_BUILD_ROOT/etc/profile.d
cat <<EOF >$RPM_BUILD_ROOT/etc/profile.d/%{name}.sh
export PATH

If someone tries to self-install they’ll probably get some unexpected behaviour…but at the moment we’re mainly just pulling this in for our RPM builds so it doesn’t matter too much.


With Leiningen now available the second part is packaging individual applications. The setup we’ve started rolling with is far from perfect, but it’s a work in progress and something we will improve. The project is available on Github, so go check it out if you’re interested. Again, while it’s tailored slightly to our specific process, it should be a good starting point if this is your first attempt at doing this kind of thing.

First the spec file:

BuildRequires: java-1.6.0-openjdk-devel, boxuk-leiningen
lein bin

As you can see, we pull in our custom Leiningen RPM as a build dependency. Rather than embedding web applications within a container like Tomcat we’re using the lein-bin plugin to create standalone ‘binaries’ for each application. This then packages all the dependencies and just requires Java on the servers being deployed to. It also lets the application decide which kind of web server it uses (if any of course).

The rest of the file is standard RPM stuff; setting the application up using chkconfig with an init script to manage it:

mkdir -p $RPM_BUILD_ROOT%{_prefix}/%{name}/bin
cp target/%{name} $RPM_BUILD_ROOT%{_prefix}/%{name}/bin/
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d/
cp %{_sourcedir}/chkconfig.conf $RPM_BUILD_ROOT%{_sysconfdir}/init.d/%{name}
chmod 755 $RPM_BUILD_ROOT%{_sysconfdir}/init.d/%{name}
if [ "$1" = "1" ]; then
       chkconfig --add %{name}
exit 0
%attr(0755, root, root) /etc/init.d/%{name}
%attr(0744, root, root) %{_prefix}/%{name}/bin/%{name}
if [ -f %{_prefix}/%{name}/bin/%{name} ]; then
       service %{name} stop
       chkconfig %{name} off

This then allows us to easily install and manage the application with the usual service start/stop/restart commands.


It’s a pretty simple thing, but this solution allows us to start rolling out internal Clojure apps and pilot projects where it makes sense.

The code is on Github:

And hopefully if you’re looking to do the same then this will be a helpful starting point – let me know in the comments.

About the author

Box UK

Box UK

Box UK's team of simply brilliant thinkers, consultants and application developers mastermind simply brilliant solutions to the world's toughest, performance-critical web and software assignments.

Related content

We're hiring. Let's talk. View available roles