Deploying a web app with RPM

It’s just a tarball.  You unzip it and put it in a public folder.  Or you just copy a war and let tomcat / jboss unzip it.

Why would you want to go through the effort of creating an RPM (or other package) to install your app if it’s so simple.

There are several reasons you might want to:

  1. Using RPM helps you keep track of versions
  2. Using RPM allows your package manager to tell you if the app is installed
  3. Using RPM allows you to keep multiple deployments in sync
  4. Using RPM helps you to specify and install dependencies

Also, there are some things that you might forget:

  1. You might also have to edit a config file to specify
  2. Which means you might need to restart the server
  3. And you might want to clean up some files (such as logs) that are outside the deployment
  4. And you might forget to do one or more of these things

You could use a custom script or a tool like Capybara to handle this for you, or you could use an OS standard tool.

But I’m not really interested in arguing why.

Like Tennyson said, sometimes “Ours is not to reason why…

Here’s how you can do it:

Like many, I was intimidated by creating an RPM spec, but it’s not that hard.

An RPM is defined by a .spec file and built using the tool rpmbuild.

If you’re on a RedHat based system and you type vi example.spec it will generate  RPM spec template.

You can start by filling in the preamble which describes your project:

Name: 
Version: 
Release: 1%{?dist}
Summary: 
Group: 
License: 
URL: 
Source0: 
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) 
BuildRequires: 
Requires:

%description

%prep
%setup -q

%build
%configure
make %{?_smp_mflags}

%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%doc

Name, Version, and Summary are self explanatory.

Release is 1 by default but if dist is defined, it will be included (i.e. ‘fc’ for fedora core).

Group helps determine where it will install in menus.  It’s not really important unless you care about that.

License can be GPL or whatever you want.  © 2012 One Shore Inc for instance

URL is an optional link with more info about your RPM

Source0 is the first source for the tarball.  You can just use Source if there is only 1 source.

BuildRoot is where it builds.  It is optional and can also be specified from the command line with –buildroot DIRECTORY

BuildRequires means a dependency that is needed to build your RPM.  If you’re not building from source, you don’t need this.

Requires specifies other RPMs needed before you can use this one.  I specified httpd but that’s not necessary.  You can specify a version http = 2.2.14 or range http >= 2  if you need to.

Some fields – notably Release and BuildRoot are filled in for you with macros.  You can just leave these unless you care.

Some other fields you can add include:

Target could should be noarch if it doesn’t matter.  It might be i386.  Target replaces the older BuildArch.   It be specified on the rpmbuild command line with the flag –target

Vendor can optionally specify the RPM vendor

%description  is an optional field that can include more details about your project

Now we move on to the RPM implementation details.

%prep contains steps to prepare.  You can cleanup, create directories, etc.

%setup If you have a tarball, the %setup macro will handle it without any options. -q means quiet.    Normally all you need is

%prep
%setup -q

%build  is where you compile your RPM.  If you don’t need to compile you can leave this section blank.  Typically, even if you do, all you have is something like:

./configure
make

%install is where you tell it how to deploy.  If you have a makefile you can just do

make install

If you want to copy files to /var/www you can use normal shell commands:

rm -rf $RPM_BUILD_ROOT
mkdir $RPM_BUILD_ROOT
mkdir -p -m0755 $RPM_BUILD_ROOT%/var/
mkdir -p -m0755 $RPM_BUILD_ROOT%/var/www/
mkdir -p -m0755 $RPM_BUILD_ROOT%/var/www/%{name}
cp -rp * $RPM_BUILD_ROOT

$RPM_BUILD_ROOT is an environment variable.  It’s where your RPM will be built.  We’re just cleaning it up  and then making sure our folders are in place inside the build root.

%{name} is a macro that prints the Name defined in the preamble

Then we copy the content of our unzipped tarball into the expected file structure

%clean is like make clean for your RPM build.  Typically just

rm -rf $RPM_BUILD_ROOT

%post is done after install.  You could bounce the webserver here for instance

service httpd restart

%preun is what needs done before uninstall

%files is a list of files that is included in the package.  If you want to install everything you can run this script in your install section:

find . -type f |sed -e 's/^\.//' > $RPM_BUILD_DIR/file.list.%{name}
find . -type l | sed -e 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name}

And then refer to it in the files section:

%files -f ../file.list.%{name}
%defattr(-,root,root,-)


This will simply concatenate a list of files (and links) in the your project folder under BUILDS into a file named file.list.myproject.  And then print them out under the %files section.

%defattr is the default file attributes.  file mode (e.g  755) and dir mode can be just a – if no changes are needed. It’s in the format:   

(<file mode>, <user>, <group>, <dir mode>)

More about the files list is here http://www.rpm.org/max-rpm-snapshot/s1-rpm-specref-files-list-directives.html

More information on the RPM spec file can be found at http://www.rpm.org/max-rpm/s1-rpm-build-creating-spec-file.html

Once you have an RPM .spec file in place, you can then build your RPM with rpmbuild:

rpmbuild myproject.spec

More information on the rpmbuild command can be found at http://www.rpm.org/max-rpm-snapshot/rpmbuild.8.html

This intro has gotten quite a bit longer than expected.  In the next post, I’ll show how to build an RPM using ant and a template spec file rpm.spec.in

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s