Skip to content

Instantly share code, notes, and snippets.

@msiebuhr
Created April 8, 2013 11:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msiebuhr/5336229 to your computer and use it in GitHub Desktop.
Save msiebuhr/5336229 to your computer and use it in GitHub Desktop.

Debianizing Node.js programs

date

2011-03-31

category

Programming

tags

Ubuntu, Debian, Node.js

Note

The bundle-command, on which this guide relies heavily has been removed in the 1.0 version of NPM. It seems to have been superseded by npm install, as it does now install packages in node_modules - but I haven't gotten around to test it thoroughly.

Getting Node.js and NPM up and running on Ubuntu isn't hard. Writing working code is a bit harder (I'm a Python convertee), but not that hard.

But persuading the system administrators to actually run your software is something entirely different:

Me:

I have written the best software in the world! And I hereby grant you the honor of running it on your servers. Oh, by the way: it's in JavaScript.

Sysadmin:

JavaScript... Server... WTF!?

Me:

Explains why Node.js is great

Sysadmin:

If you say so. Gimme' a Debian package then, and you're good to go.

Me:

Ehhh. Can I get back to you?

While Debian has packaging policies for Java, Perl and Python, there is no such thing for Node.js. (As to Node.js itself, there's Bug 611698, which basically states that the binary name node has already been used by a different program, why they package Node.js' binary as nodejs. We have a plan to get around that; I'll post on that once we get there.)

So. I needed to come up with some way to package Node.js programs in Debian. But how?

What to package?

Well. I had time, but I didn't really fancy packaging every single Node.js module as individual Debian packages. They're very different beasts, each having their own quirks. The sheer number of dependencies isn't appealing either. And not least, there is a lot of them (1514 at time of writing).

NPM and Node.js to the rescue!

Update 1/4 2011: This is explained way better in Global vs Local installation on the Node.js blog. Read that and skip the next three paragraphs...

It turns out that Node.js version 0.4 and later, gives special treatment to folders called node_modules. Namely it looks in such folders, when you're importing modules in your code, thus making local versions of packages, among other things, a breeze. The documentation explains this nicely.

NPM uses this feature to power it's bundle-command. If you install your program by issuing npm bundle install (instead of the regular npm install), it'll put your program's dependencies in ./node_modules, instead of wherever it usually puts them. This gives you a nicely compartmentalized environment that works fairly transparently from within node. (The placement of bundled binaries is a bit odd, but that's a minor detail).

In all, npm bundle fetches all the program's dependencies to a known, self-contained and location. We can then trow all of that into a single deployable package, that will contain everything needed, except the Node.js binary itself.

The Recipe

First, you should have a package.json file describing your program. NPM uses this to keep track of dependencies and all the other housekeeping stuff:

{
    "name": "foo",
    "description": "some text",
    "dependencies": {
        "underscore": "*",
        "vows": "*"
    }
}

If you haven't got such a file, use npm init to get started.

Then we need to set up the basic Debian setup going. You can use the program dh-make to get a basic "debianized package" in no time:

dh_make -e YOUR@EMAIL.TLD -s -n -p YOUR-PACKAGE-NAME_0.0.1

Last thing needed is to create/edit a Makefile, which install target does some Debian-related magic. (The package-building scripts expect make install DESTDIR=some/temp/dir to do something sensible):

install:
    # Create parent directories
    install -d $(DESTDIR)/usr/share/YOUR-PACKAGE-NAME/

    # Create and copy over node_modules, so node will find it later.
    @npm bundle install
    cp -r node_modules $(DESTDIR)/usr/share/YOUR-PACKAGE-NAME/

    # Copy your own program...
    cp -r lib $(DESTDIR)/usr/share/YOUR-PACKAGE-NAME/
    install some_binary.js $(DESTDIR)/usr/share/YOUR-PACKAGE-NAME/

If you want to customize how things happen, debian/rules is the place to hack.

Then you can use dpkg-buildpackage to build your package. The -uc and -us parameters indicates that you're not signing the resulting souce and binary packages:

dpkg-buildpackage -uc -us

After tonnes of output, there should be a fresh .deb-file in the parent directory, which you can try to install it:

``dpkg -i ../YOUR-PROJECT-NAME_0.0.1_i386.deb``.

For further tinkering with the debian/*-files, the Debian New Maintainers' Guide is the place to look. In particular, debian/control and debian/changelog is where the fun stuff happens.

Further work

I am neither a Debian nor Node.js, nor NPM guru at any level, so your milage may vary. I'm also quite sure I have missed several corner-cases (it just can't be this simple!).

If you have any suggestions or improvements - or make up something better altogether, please drop me a note, and I'll incorporate it here, post a link or whatever.

@itwars
Copy link

itwars commented Apr 8, 2013

Hello,

Interesting thoughts, anyway that the way I use to make my Node.js debian package for ARM processors : https://github.com/itwars/nodejs-ARM and I use an awesome ruby tool call fpm to make it (see my vagrant script https://github.com/itwars/Nodejs-ARM-builder). fpm is also made to make npm -> deb packages !

As I mention on my Node.js site there's another tool call npm2debian : http://www.nodejs-news.com/nodejs-tech/nodejs-debian/

I hope this could help you.

Bests,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment