1

I have a CentOS 6 server set up with git, gitosis, nginx, and php-fpm.

With our setup, nginx executes php scripts via php-fpm, which is configured on a per-site basis to run as a specific user for security purposes (i.e. not all under nginx:nginx) since we don't want the situation where if one site is compromised, all sites are compromised.

Our environment works great, but, when git is involved, php-fpm creates a fundamental issue.

Upon successfully running the following command locally:

$ git push origin

My post-receive hook is run:

#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.com/httpdocs git checkout -f

Normally, this would copy the contents of the repo into the httpdocs folder, however since php-fpm is installed and the directory+files are owned by a specific user, gitosis (or any other non-root user) can not write to the directory. This is made evident by the following error:

remote: error: git checkout-index: unable to create file index.php (Permission denied)

It makes sense, and that is what I would expect. However, I am wondering if there is a way to get around this issue in this specific case? Is there a way I can modify the post-receive hook to run as root (it is currently run by the gitosis user) or in some other fashion in order for it to succeed?

Just to be clear: there are no other problems with the setup, git works fine, nginx/php-fpm work fine, but this is a permissions issue which I am not quite sure how to get around.

Brendan
  • 4,565
  • 1
  • 24
  • 39

1 Answers1

1

You could use sudo to get the hook to run as user1, user2, user3, or whatever your system needs. You would need to consider the security implications of having the gitosis user able to masquerade as your web users, even if to a limited extent.

Example recipe

Given that the post-receive hook runs as user gitorious and assuming your web users are called user1, user2, user3 etc...

Move your current post-receive hook into /usr/local/sbin/update-user1.sh, or some other suitable place, and make sure it's executable.

Add something like these lines to /etc/sudoers:

gitosis    localhost = (user1) NOPASSWD: /usr/local/sbin/update-user1.sh
gitosis    localhost = (user2) NOPASSWD: /usr/local/sbin/update-user2.sh
gitosis    localhost = (user3) NOPASSWD: /usr/local/sbin/update-user3.sh
... etc ...

And then your post-receive hook for user1 could become something like:

#!/bin/sh
sudo -u user1 /usr/local/sbin/update-user1.sh

Similarly for other users.

Untested, so please test before implementing!

clstrfsck
  • 14,715
  • 4
  • 44
  • 59
  • The problem with this is that I would have to add gitosis to every website's user group. That would in turn negate the reason for having every user isolated from eachother on a permissions standpoint. I'm starting to think this isn't possible without compromising the integrity of the system we've set up. – Brendan Mar 05 '12 at 21:04
  • I don't see why you would have to add `gitosis` to each website's user group using this technique? `sudo` would run the checkout script as `www-data` (or whatever the actual web user is). You would need a separate checkout script with a matching entry in `/etc/sudoers` for each user, but it would be possible to parameterize this if really needed. – clstrfsck Mar 06 '12 at 09:59
  • There is no single web user, so www-data does not apply. Our server has been setup with fairly strict security in mind-- every website has its own user. These users do not belong to any group but their own, and thus cannot modify eachothers files, which is important when running php with php-fpm (since php runs as the user). – Brendan Mar 06 '12 at 16:45
  • I've updated the text -- hopefully this should make it clearer how to apply to multiple users. – clstrfsck Mar 07 '12 at 01:38
  • Thanks I'm going to test this out and try to simulate a worst-case scenario. – Brendan Mar 07 '12 at 15:58