Friday, December 11, 2009

How I manage my Perl modules on Debian

I just started doing this on another server this morning, and I just realized I can't find my notes on the process! Since I like to record things like this, I started typing and decided I'll turn it into a blog post...

Anyhow, I think I've developed a good enough set of rules and steps for managing perl modules on a Debian-based system that I feel comfortable sharing them with the public. If I'm lucky I will get some useful feedback and critique that will help me further improve!

The basic premise of it this: Try as hard as possible to avoid installing modules from CPAN to the system's perl.

I do this by following these rules-of-thumb:
  • only install system-wide modules from debian packages (excepting local::lib)
  • use local::lib as much as possible
  • properly configure CPAN both system-wide and per-user
So, here's how I set up a fresh system to make following these rules as easy as possible...

Assume starting from a fresh, bare-bones installation of Debian Lenny. This should work with previous releases, but YMMV.

Step 1: Install necessary debian packages to make the cpan client happy.
# Stuff to install for a happy CPAN client:
sudo aptitude install \
  ftp \
  tar \
  curl \
  gzip \
  less \
  lynx \
  wget \
  bzip2 \
  gnupg \
  ncftp \
  patch \
  unzip \
  makepatch \
  libwww-perl \
  libyaml-perl \
  libexpect-perl \
  build-essential \
  libyaml-syck-perl \
Step 2: (optional) Throw your favorite default settings into the system's CPAN config file.

cat <<'END_TXT' >/etc/perl/CPAN/
$CPAN::Config = {
    'build_requires_install_policy' => q[ask/yes],
    'check_sigs'           => q[0],
    'build_dir_reuse'      => q[0],
    'prefer_installer'     => q[MB],
    'prerequisites_policy' => q[ask],
    'inactivity_timeout'   => q[300],
    'build_cache'          => q[250],
    'build_dir'         => qq[$ENV{HOME}/.cpan/build],
    'cpan_home'         => qq[$ENV{HOME}/.cpan],
    'histfile'          => qq[$ENV{HOME}/.cpan/histfile],
    'keep_source_where' => qq[$ENV{HOME}/.cpan/sources],
    'prefs_dir'         => qq[$ENV{HOME}/.cpan/prefs],
    'urllist'           => [

Step 3:  Initalize the system CPAN config, just agree to auto-config so it can fill in what's missing.
sudo -H perl -MCPAN -e 'CPAN::Shell->o(qw[conf init])'
Step 4: (optional if you did step 2) Choose and save your default CPAN mirrors.
sudo -H perl -MCPAN -e 'CPAN::Shell->o(qw[conf init urllist]);CPAN::Shell->o(qw[conf commit])';
Step 4:  Install local::lib to the system perl.
sudo -H cpan local::lib
Step 5: (optional) Enable local::lib by default for all users
sudo sh -c 'echo eval \$\(perl -Mlocal::lib\) >> /etc/profile'
Step 6: (optional) Give new users a convenient default config, for example:
cat <<'END_TXT' >/etc/skel/.cpan/CPAN/
$CPAN::Config = {
    'prerequisites_policy' => q[follow],
    'tar_verbosity'        => q[none],
    'build_cache'          => q[100],
    'build_dir'         => qq[$ENV{HOME}/.cpan/build],
    'cpan_home'         => qq[$ENV{HOME}/.cpan],
    'histfile'          => qq[$ENV{HOME}/.cpan/histfile],
    'keep_source_where' => qq[$ENV{HOME}/.cpan/sources],
    'prefs_dir'         => qq[$ENV{HOME}/.cpan/prefs],
    # you may not need these, I think a user's
    # will pick them up from the system CPAN
    'urllist' => [

Anyhow, that's a start for now. It sounds like a lot of work now that I've typed it all out, but I really feel like it saves me time and trouble later!


  1. good point, rob!

    dh-make-perl is an excellent tool for getting cpan modules installed into a Debian system. I should totally use that for installing local::lib.

    The only drawback is the usual folly of attempting to upgrade core modules, or possible subtle issues with compiled modules that require external dependencies (ie GD, ImageMagick, etc...)

    Again, for those I use local::lib if the packages provided by Debian are not sufficient (so far that hasn't been the case, but that's how I think I would fall back)

    One more thing I haven't mentioned - I use multiple local lib dirs, for experimenting and for working on different code-bases, and I've even begin making them into git repos so I can revert if something goes wrong!