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?
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.
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 [email protected] -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.
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.
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,