Using the Encap Package Management System to Manage Non-System Packages

by Keith T. Garner

What Is Encap?

Encap is a simple light weight package management system. It is not intended to replace the package management system that is part of your operating system or distribution, but to make it easy for you to manage applications that you hand compile.

Encap makes it trivial to remove, replace, and upgrade applications you hand compile by placing them in their own directory. However, instead of having to add a lot of directories to your PATH, among other environmental variables, an Encap application helps you add these files to normal system PATHs in /usr/local via symbolic links. These links make Encap completely transparent to the end user. Also, once you have a working Encap package, you can tar it up and put it on other systems, or export it via NFS to client machines.

Brief History of Encap

Encap was first created as a perl script, encap.pl, by Jason Wessel around 1995. The perl version made managing systems a lot easier; however, it was a bit slow for various reasons. It was reimplemented in C as encapper.c by Brian Swetland who added the concept of working only on a single package. The current popular implementation is called epkg and is maintained by Mark Roth from the University of Illinois at Urbana-Champaign. Including all the features of previous versions, epkg advances the Encap system by introducing standards how packages should be structured and has added other helpful features.

The concept of installing and removing packages in this way is not unique. There are other packages such as GNU STOW or djb/package that do approximately the same thing. I've been using Encap since before either of those packages existed and continue to use it today. As always, I recommend that before you jump into using any of these systems, read up on them and choose the one that works best for you.

How Encap Works

Encap fits will with the unix philosophy in that its very simple and works with existing system utilities. Typically, When you compile an application to be encapped you would install it into /usr/local/encap/package-name-package-version. Running the Encap application on that package creates symbolic links from where the package is installed to the property location in /usr/local.

For example, let's say we have a package called example. Example has a binary file called foo and a man page file foo.1. The directory structure would look like the following:

/usr/local/encap/example-1.0
    + bin/
    | + foo
    + man/
      + man1/
        + foo.1

The following symbolic links would be created when your Encap application is run:

/usr/local/bin/foo ->
              /usr/local/encap/example-1.0/bin/foo
    /usr/local/man/man1/foo.1 -> 
              /usr/local/encap/example-1.0/man/man1/foo.1

Compiling and Installing epkg

Epkg can be found on the web at http://www.encap.org/epkg/. The current version is 2.3.6.

On its own, epkg will fit most basic needs. However, when compiled against some other optional libraries additional functionality is included. libtar (also written by Mark Roth) will give epkg the ability to automatically untar and install Encap packages that are packed up in tar. zlib will allow for ungzipping of those packages. fget and cURL allow epkg to retrieve packages with FTP and HTTP, respectively. These must be installed before you compile epkg for epkg to use them. epkg may be able to do some of these actions by calling out to the system , however, it's more efficient to compile against the libraries.

The typical "./configure ; make ; make install" will work perfectly here. Epkg will default to installing itself in /usr/local/encap/epkg-version. For almost all cases, this will be where you want epkg to install itself.

There are some people who have used epkg to build a whole distribution. Those people would install epkg into /usr/encap/epkg-version. I don't recommend that until you become more familiar with Encap.

Compiling and Installing an Encapped Package

Compiling a package to use Encap is typically pretty easy. This is especially true of packages that use the popular autoconf/automake facilities. In most cases, all you need to do is pass the --prefix command to configure. A simple example would be:

 #./configure --prefix=/usr/local/encap/example-1.0

A more complex example, from compiling mutt is:

#./configure --prefix=/usr/local/encap/mutt-1.4.1 \
              --enable-imap --enable-pop \
              --with-ssl --with-slang \
              --with-homespool=Maildir

In some cases you may want to set the --sysconfdir so you can have a shared configuration directory for the multiple versions of an encapped package. A good example of this would be with openssh. With openssh it's helpful to have certain configuration information persistent between versions such as the host keys. You would want to run configure similar to this:

#./configure --prefix=/usr/local/encap/openssh-3.6p1 \
              --with-pam --sysconfdir=/etc/ssh

Usually, you're done after you do a "make install" from the package. However, when using Encap, you have to create the symbolic links from the normal system areas into where the package is installed. This is accomplished by running the command "epkg package-name"

Other Packages

If the package you want to compile doesn't use autoconf, things can be more difficult. Most sane packages have BINDIR, MANDIR, and the like in their Makefile that you can edit. Sometimes they even have a PREFIX to define. If you're not sure where a package is going to put the files the best course of action is to run "make -n install" and watch closely where the Makefile will put the files. Unfortunately, there's so many build systems out there that its difficult to give a general rule of thumb. The lesson here is to be aware of what you or the install script is doing at package install time.

Perl Modules

There are two ways you can encap perl modules. The first is to pass PREFIX to Makefile.PL.

perl Makefile.PL \
    PREFIX=/usr/local/encap/perl-package

This works pretty well, however, you can't use nice tools like cpan to grab the package; you need to manually download the package. Instead of running "perl Makefile.PL", you can use an optional package called cpanencap. cpanencap is a helper script to make the process of encapping a perl module easier. cpanencap calls "perl Makefile.PL" on your behalf with the proper arguments passed along.

If you enjoy using CPAN.pm to download and install perl modules, you can still use cpanencap. The man page for cpanencap says this method has some rough spots, but it will work well for most people. All you need to do is configure CPAN.pm with these configuration settings:

conf makepl_arg "`/usr/local/bin/cpanencap -A -M \
    '-a "exclude $(INSTALLARCHLIB)/perllocal.pod"'`"
 conf make_install_arg "&& epkg -f \
    `/usr/local/bin/cpanencap -P`"

The other thing to worry about with encapping perl modules is your PERL5LIB. For example, the default perl install from RedHat 7.x does not include any /usr/local paths in its INC/PERL5LIB. If you use the default Encap location of /usr/local perl will not see any modules you install via Encap unless you set the PERL5LIB environmental variable or recompile perl to include these paths.

Basics of Using epkg

Once you've installed a package into the Encap repository, it's really easy to link the files into their standard locations. Simply run the epkg command with the name of the package you'd like to install.

#epkg yase
  epkg: installing package yase...
    > reading Encap source directory...
    > installing package yase-0.9.9
      > installation successful

If anything should go wrong, logging information is recorded into /usr/local/encap/epkg.log. epkg.log can also be used as an audit trail in the case of multiple admins working on the same Encap repository.

After doing the install of yase, the following is found in the log:

Mar 25 2003 18:18 /usr/local yase-0.9.9 install success

Upgrading A Package

Upgrading to a new version of a package is as easy as installing one the first time. Compile and install the upgrade into the correct Encap directory, then run the epkg command.

#sudo epkg mutt
 epkg: installing package mutt...
   > reading Encap source directory...
   > removing package mutt-1.4
     > removal successful
   > installing package mutt-1.4.1
     > installation successful

If you're upgrading a package that contains a daemon, you'll want to shut down the daemon first. Also, if you didn't specify a sysconfdir when you ran ./configure and your configuration files were copied into /usr/local/encap/package/etc, you'll want to also either copy your configuration files over or edit the newly installed configuration files. This is one of those things that needs to be looked at on a case by case basis.

Removing A Package

The first step in removing a package is removing the symbolic links that point from the system directories into the Encap area. This is accomplished using the -r flag of epkg.

#epkg -r mutt
 epkg: removing package mutt...
   > reading Encap source directory...
   > removing package mutt-1.4
     > removal successful

In some cases, you may want to keep the application around if you need it again. If not, just use rm to get rid of it.

 # rm -rf /usr/local/encap/mutt-1.4

Downgrading One Version

As is often the case, the new package, especially if bleeding edge, might have a show stopping bug. For example, this happened to me recently in going from SpamAssassin 2.50 to 2.51. SA 2.51, for various reasons, was causing havoc with the machines load as well as severely delaying mail delivery. Without using Encap, I would have been in a bit of trouble.

Luckily, the developer of epkg has seen this as a common occurrence and has added a shortcut argument to help you back down gracefully. This is the -1 argument.

#epkg -1 mutt
 epkg: installing package mutt...
   > reading Encap source directory...
   > removing package mutt-1.4.1
     > removal successful
   > installing package mutt-1.4
     > installation successful

Changing To An Arbitrary Version

If you give a full package name including version to epkg it will jump back to the version you've specified.

#epkg SpamAssassin-2.51
  epkg: installing package SpamAssassin-2.51...
    > reading Encap source directory...
    > removing package SpamAssassin-2.50
    > removing package SpamAssassin-2.52
    > removing package SpamAssassin-2.53
      > removal successful
    > installing package SpamAssassin-2.51
      > installation successful

Ignoring Version Information

The -S flag tells epkg to ignore the version information contained in the directory name and work on the specific package name you give it. This is used in the situation where epkg doesn't understand the package name as being of the form package-version.

#epkg -S mutt-1.4                                   ~
  epkg: installing package mutt-1.4...
    > installing package mutt-1.4
      > installation successful

The encapinfo File

Along with the creation of epkg came the creation of the Encap Specification. 2.1 is the current version and contains only minor changes or clarifications to 2.0. A key element added by Encap 2.0 is the encapinfo file.

The encapinfo file contains a number of optional fields that describe the configuration data for a package. This file allows you to specify what systems an encapped package should run on. It also specifies ways to link certain files and directories or even ignore files and directories. All encapinfo files must start with "encap version". The current version is 2.1, so you'll want to say "encap 2.1"

encap 2.1
  contact "Joe Admin" joe@admin.example
  require var
  exclude var/openldap-data
  linkdir

The require field allows you to state file or directory dependencies before this encapped package can be installed. In the case of a file, the file must exist before the package can be installed. In the case of a directory, the directory must already exist or epkg must be able to successfully create the directory. An example of why you would want epkg to make the required directory would be in the case of a package that needs a scratch directory to work in.

The exclude field allows you to specify files or directory trees that should be excluded from the linking process. You could use this to protect non-public configuration directories or to prevent linking of data directories that are only needed by the running application. Another use would be to block the installation of binaries that are not needed to be in a user's path.

As the name implies, the linkdir field tells epkg to create a symbolic link to this directory instead of creating a new target directory in the system area with links to the original directory's files inside it. This is useful for large directories that are specific to and only used by one package. Any directory used with this field is required to have unique name within its target directory.

(pre|post)(install|remove) Scripts

Acknowledging the fact that an admin might need to do some setup before or cleanup after installing a package, epkg honors 4 optional scripts: preinstall, postinstall, preremove, and postremove. These scripts must be at the top level of the package directory and will not be linked by epkg.

The pre scripts should return 0 upon successful completion. If a pre script returns an error code, epkg will halt the install or remove immediately and consider the operation as a failed operation. Besides setup another use for pre scripts, as documented in the encap man page, is to do more complex checking for dependencies or other necessary conditions.

The post scripts should also return 0 upon successful completion. Unlike the pre scripts, if a post script does not successfully complete only the failure is reported. It doesn't halt the operation on the package. post scripts are commonly used for manipulating areas outside of the Encap arena. For example, for a daemon package, the post install script could copy the init script to the init.d/ directory. However, this script should not make any changes that could effect how the machine boots, such as creating the links from the rc directories to the script in init.d. This behavior for scripts, as well as some others, is documented in the Encap specifications.

Going Farther

At this point, you can use the epkg version of Encap and fit almost all of your needs. However, there are some things not covered in this article that larger shops might find useful. Chief among these are the use of Encap spec files and the mkencap utility. Information on those can be found in the epkg distribution or at encap.org. Also at encap.org you'll find links to precompiled encap packages for a variety of platforms.

Keith Garner is a Strategic Architect for the National Association of REALTORS(R). He's been using Linux personally since 1994 and professionally since 1997. While coding and system administration are his first loves, he tries to stay sharp doing presentations and writing articles. He lives in Bartlett, IL with his wife Sarah.

Load Disqus comments