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.
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!