Oct 11, 2014

npm without sudo

So you’ve got awesome deploy script for your website which runs on some webhook from git. It does really everything just as you need. But then, you also want to install npm dependencies and for example compile some js or css files.

The problem is, that it will run most probably as www-data user…

why is life so hard

There are already many tutorials, and I of course tried many of them, but none of them really worked.

Sorry, I was working on that few days ago, so I already forgot some things…

Imagine the situation, you’ve got GitLab and also GiLab CI, which sends request to some URL which will just run your deploy script (only if tests passed, if branch is develop, etc…)

Then I had this code in my deploy script:

$ echo "Installing npm dependencies"
$ cd www/front
$ npm install .
$ cd ../..

$ echo "Compile front assets"
$ cd www/front
$ npm run compile
$ cd ../..

Well this will not work of course. The first problem is with npm install ..

npm will create some folders and files in your home directory and since home directory for www-data user is /var/www, than this user needs to be owner (logically). And because I changed it long time ago, I had to set it back.

$ sudo chown www-data:www-data /var/www

Now www-data user will be able to create for example .npm directory.

But even then for some reason it just didn’t work. So I end up with using sudo :-(

You know, every time I see this “sudoers or visudo” as solution to some problem on StackOverflow, I automatically close this page and begin to look for some other solution. I really don’t like that. So this is the first time, I used that.

Do not forget to use visudo and not some other editor!!!

$ sudo visudo

Now you just need to paste this code at the bottom of opened file:

www-data	ALL=NOPASSWD: /usr/bin/npm

Great, now www-data user can run sudo npm install . command without password prompt.

Of course, if it run with sudo, setting owner to /var/www directory is quite useless, but still, it’s www-data’s home directory.

And now guess what, our deploy script still doesn’t work, because of npm run compile.

Here is our package.json:

{
	"name": "xxxxxx",
	"version": "1.0.0",
	"author": {
		"name": "David Kudera",
		"email": "[email protected]"
	},
	"dependencies": {},
	"devDependencies": {
		"gulp": "~3.7.0"
	},
	"scripts": {
		"compile-js": "gulp compile-js",
		"compile-templates": "gulp compile-templates",
		"compile-css": "gulp compile-css",
		"compile": "gulp compile"
	}
}

As you can see, the compile script just runs gulp compile which should be “translated” to node ./node_modules/gulp/bin/gulp.js compile. Well, it is not (at least not for www-data user).

After about 2 hours I tried to replace npm run compile in deploy script with node ./node_modules/gulp/bin/gulp.js compile and now finally it works :-)

$ echo "Installing npm dependencies"
$ cd www/front
$ sudo npm install .
$ cd ../..

$ echo "Compile front assets"
$ cd www/front
$ node ./node_modules/gulp/bin/gulp.js compile
$ cd ../..

Maybe I should try exporting PATH environment variable….