Using CPAN with a non-root account

Manual CPAN Configuration | Customize @INC via PERL5LIB | Switching the Install User

Root access is not required to install Perl modules. Perl modules can be installed under a home directory, or into any other location. When possible, use the local::lib module, as this module automates the manual CPAN configuration outlined below. Installing Perl modules without root access presents a walk-through with local::lib. Set the make_install_make_command option to install via sudo or some other method, if necessary.

Caveat

Installs from CPAN may not be reproducible, as the author could upload a new, incompatible module version, or delete the entire module without warning (though old versions of the module may be available on backpan). If this is a concern, be sure to archive the specific module versions required for the software, so that the installation can be properly reproduced on other systems or again in the future.

Multiple perl Installed?

Another important piece of information is the number of perl installed on the system. Ensure that only one version of perl is used consistently for each software project—usually by using the fully qualified path, or by ensuring that all required environment settings are consistent and correct—as otherwise modules may end up installed for the wrong version of perl.

$ type -a perl
perl is /usr/bin/perl
perl is /usr/local/bin/perl
$ whence -a perl
/usr/bin/perl
/usr/local/bin/perl

Some vendors (notably Apple in recent Mac OS X releases) may install multiple versions of perl by default, and may offer a means to switch between these different versions. This might also complicate module installation and usage.

$ ls /usr/bin/perl5*
/usr/bin/perl5.10.0 /usr/bin/perl5.8.9

Clean Slate

Previous build or configuration attempts may have left the system in a messy state. If possible, use a virtual system, so that a build system can easily be rebuilt, or restored to a known clean slate. Another method is to create a new system account, and build software under that, destroying the home directory when done to reset to a clean slate. If this is not possible, reset CPAN to a clean slate by wiping out the ~/.cpan directory. The system-wide CPAN configuration should have no bearing on user-specific build attempts, though for reference can be located by running:

% perl -le 'print grep -f, map $_.$ARGV[0], @INC' /CPAN/Config.pm

When using local::lib with CPAN, accept the defaults during the cpan configuration questions (that is, make no changes to the prompted configuration settings), then bootstrap local::lib.

Manual CPAN Configuration

These (tedious and possibly error-prone) manual steps are not necessary if instead the local::lib module is used. @INC must be configured correctly in either case; see the next section for details on that step.

  1. Download the sample MyConfig.pm, and move it to ~/.cpan/CPAN/MyConfig.pm.
  2. $ mkdir -p ~/.cpan/CPAN
    $ mv MyConfig.pm ~/.cpan/CPAN

  3. Customize the MyConfig.pm file.
     
    1. Change all occurences of HOMEDIRFIX to your home directory, for example /home/username.
       
    2. Review the makepl_arg arguments. For more information on the arguments, see ExtUtils::MakeMaker.
       
    3. Check the paths to various commands (e.g. wget), proxy settings for your environment, the urllist, and the shell.
    4. Be sure to remove the UNINST=1 option on make_install_arg for any non-system-wide configuration as otherwise CPAN will attempt to remove “shadowing” versions of the module installed for the site perl, leading to error messages involving forceunlink.

    5. Test MyConfig.pm for problems.
    6. $ perl -c MyConfig.pm
      MyConfig.pm syntax OK

  4. See below for the required PERL5LIB settings to customize @INC, if installing modules that depend on previously installed modules. Be sure to load the changes into your shell environment before running cpan, or to close and reopen your shell.
     
  5. Test the new configuration.
  6. To ensure Makefile are being generated with the proper paths, make a module from the CPAN shell, then review at the paths set in the resulting Makefile.

    cpan> make Text::Autoformat

    cpan> look Text::Autoformat

    $ grep /home/username Makefile
    SITELIBEXP = /home/username/lib/perl5
    PREFIX = /home/username/
    INSTALLPRIVLIB = /home/username/lib/perl5
    INSTALLSITELIB = /home/username/lib/perl5
    INSTALLVENDORLIB = /home/username/lib/perl5
    INSTALLARCHLIB = /home/username/lib/perl5/darwin-thread-multi-2level
    INSTALLSITEARCH = /home/username/lib/perl5/darwin-thread-multi-2level
    INSTALLVENDORARCH = /home/username/lib/perl5/darwin-thread-multi-2level
    INSTALLMAN1DIR = /home/username/share/man/man1
    INSTALLSITEMAN1DIR = /home/username/share/man/man1
    INSTALLMAN3DIR = /home/username/share/man/man3
    INSTALLSITEMAN3DIR = /home/username/share/man/man3
    $ less Makefile

    $ exit

    If the Makefile has the wrong path set for any variables, update the makepl_arg arguments in MyConfig.pm to set these variables to install to the proper custom location.

Customize @INC via PERL5LIB

Testing PERL5LIB | Shell Configuration for PERL5LIB

If using local::lib, consult its documentation. Otherwise, if manually configuring CPAN as shown above, Perl must be made aware of the custom /home/username/lib/perl5 library directory. Perl uses the @INC variable to hold library directories, though this array must not be edited directly. For more information on @INC, consult perlvar (overview of Perl variables), perlrun (command line arguments and environment variables: see Perl One Liners for more information on these), or lib (regarding the use lib pragma).

Testing PERL5LIB

For Perl 5, under a Bourne shell, set the PERL5LIB environment variable, and test whether perl can find and use a module verified to be installed under the custom install path:

# Confirm nothing else has set PERL5LIB first
$ echo $PERL5LIB
$ export PERL5LIB=~/lib/perl5

# Check that the shell and perl are aware of the new setting
$ echo $PERL5LIB
/home/username/lib/perl5
$ perl -V | grep $PERL5LIB
PERL5LIB="/home/username/lib/perl5"
/home/username/lib/perl5/darwin-thread-multi-2level
/home/username/lib/perl5

# Find a Perl module to test with (if none, install something!)
$ find ~/lib/perl5 -type f -name "*.pm" | head -1
/home/username/lib/perl5/Bundle/LWP.pm

# See if the module can load, and if so, from where
$ perl -MBundle::LWP -le 'print $INC{"Bundle/LWP.pm"}'
/home/username/lib/perl5/Bundle/LWP.pm

The final command confirms that Bundle::LWP is actually being read from under /home/username/lib/perl5 by perl, and not some other directory in @INC. Note how module names are converted to filesystem paths by replacing all the :: with / on Unix, plus a suffix of .pm. If a module cannot be used as expected, causes would include permissions problems, or perhaps other environment variables and settings altering the results. Unix Debugging Tips covers how to delve through Unix systems, and the various external documents referenced above detail other environment variables and settings that also influence @INC. Additional points:

Shell Configuration for PERL5LIB

The custom PERL5LIB should be made permanent, for example by adding the lines:

PERL5LIB=$HOME/lib/perl5
export PERL5LIB

MANPATH=$HOME/share/man
export MANPATH

To the ~/.profile shell startup file (or as appropriate for the shell in question). Then, create a new shell and echo $PERL5LIB to confirm that the setting is available. Consult the shell documentation (for example STARTUP/SHUTDOWN FILES under zsh(1)), or learn from a book such as Learning the BASH Shell to understand the various startup files and when they are evaluated by the shell. One method to cleanly replace the currently running shell is to simply exec the shell, which replaces the current shell process with a newly launched instance:

% echo $SHELL
/bin/zsh
% exec $SHELL

Note that under cron(8), the environment may be different than set in the shell. Ensure that the crontab(5) file sets appropriate environment variables to find any required perl modules.

Perl code running under Taint mode may require the use lib statement: see perlsec for details. Certain programs may require custom configuration to set PERL5LIB. Consult the documentation to see whether any options to adjust environment variables are offered, or experiment to see whether the program will inherit them from the parent process. Apache, for example, offers the SetEnv configuration option under mod_env:

SetEnv PERL5LIB /home/username/lib/perl5:/some/other/perl/lib

Some programs, such as sudo, may strip environment variables. This may delete PERL5LIB or other necessary settings. Workaround programs that do this via a wrapper script that then sets all the necessary variables, then runs the original program:

#!/bin/sh
export PERL5LIB=…
exec /path/to/the/real_program "$@"

Switching the Install User

Use the make_install_make_command option to build as one user, but install as a different user, for example via sudo:

cpan> o conf make_install_make_command 'sudo /usr/bin/make'
cpan> o conf commit

And then build and test as a non-root account:

$ cpan -i File::AtomicWrite

If the install has previously failed, CPAN may cache this result. In the cpan shell, try clean Module::Name, or otherwise cleanup the ~/.cpan/build directory to start anew.