perlbundleofflinecpanm

How to bundle modules for an offline server with cpanm


I would like to do cpanm SomeModule to install SomeModule together with about 10 dependencies, but the target server has no internet access. I do have a very similar development machine (same Perl environment, same Perl version) where cpanm is able to download its source modules.

After studying the man page of cpanm, I have the feeling that I can create a tarball on the development machine, transfer that to the server, and use it to install the modules in one go.

Unfortunately, I do not seem to find which exact combination it is. Especially, as on the dev machine the modules are already installed, I need to force it to still add all the dependencies to the tarball (excluding core modules of course).

Can someone give the commands for the dev machine and the target machine?

EDIT: this is specifically about cpanm. Of course, if you can say with authority that it is definitely not possible with cpanm, that would be a valid answer as well...

EDIT: The comments and answers so far suggest using pinto or minicpan to create a bundle of CPAN module sources. This works well (especially pinto is quite trivial to use for this). I used pinto now to solve my current problem, but still, Pinto itself has a lot of prerequisite modules (>100 compared to Perl-Core). My hope with this question was that cpanm, which is a standalone, installation-less script, can do it itself (it has extensive options that kind of sound like they could go into that direction). That would be nice for bootstrapping Perl installations without large overheads.


Solution

  • You can use Carton to bundle the dependencies locally (on your machine with internet access) and then use either Carton itself to install the bundled distributions, or use cpanm and specify the bundle location.

    You'll need carton 1.0.32 (to generate the package index) and cpanm 1.7016 (for the --from option) for this to work.

    In the root of your distribution, you can do

    $ carton install # will install the dependencies in `local`
    $ carton bundle  # will cache the dependencies in `vendor`
    $ tree vendor/
    vendor/
    └── cache
        ├── authors
        │   └── id
        │       └── F
        │           └── FO
        │               └── FOOBAR
        │                   ├── Some-Dist-1.337.tar.gz
        │                   └── Another-Dist-0.001001.tar.gz
        └── modules
            └── 02packages.details.txt.gz
    

    Later, after transferring the vendor directory to your other airgapped machine, you can either use carton:

    $ carton install --cached
    $ carton exec scripts/your-script.pl
    

    or install with cpanm directly

    # To emulate carton:
    $ cpanm -L local --from "$PWD/vendor/cache" --installdeps --notest --quiet .
    # Or to install globally:
    $ cpanm --from "$PWD/vendor/cache" .