I have an www-data running with php which is controlling a git server. The www-data user creates Unix users (having given it sudo adduser), and those users are supposed to control their own private git directory, where each user can house his/hers repositories.

I've followed this guide at least ten times, in addition to which, I'm also following this guide in order to create the git server.

  • Apache adds a unix user bar, with a home in /var/www/git/bar and the user has no password (--disable-password)

  • The user bar is part of group gitusers which allows +rwx to the group members, and has his shell set to /usr/bin/git-shell.

  • This is done so that www-data can access his home directory and populate it with repositories and ssh keys.

  • The skeleton home directory is also populated with git-shell-commands and the user www-data creates an /var/www/git/bar/.ssh/authorized_keys where it appends my test user's foo public key.

When www-data adds a new user and then a new repository it does:

sudo adduser --disabled password\
             --home /var/www/git/bar\
             --conf /var/www/conf/adduser.conf\
             --ingroup gitusers\

The above ^^ is done via php. The .ssh and authorized_keys are owned by www-data.

Then www-data proceeds to create a new directory and initialize it:

  • mkdir /var/www/git/bar/test.git
  • cd /var/www/git/bar/test
  • git --bare init

My test user foo can read it from ssh (it just clones an empty repository). Once I try to push an initial commit:

git clone ssh://foo@localhost:/var/www/git/bar/test.git
cd test
touch readme
vim readme
git add .
git commit -m "init"
git push origin master
foo@'s password:
Counting objects: 6, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 411 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
remote: error: insufficient permission for adding an object to repository database ./objects
remote: fatal: failed to write object
error: unpack failed: unpack-objects abnormal exit
To ssh://foo@localhost:/var/www/git/bar/random.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'ssh://foo@localhost:/var/www/git/bar/random.git'

I am asked for foo user's password (which is the user with the public key).

This is NOT the Unix user who owns the home directory, that is user bar who has a disabled password.

  1. why am I being asked for an ssh password? shouldn't they ssh key take care of that?
  2. If I create a bar with a password, then I can use that git repository, replacing foo@localhost:/var/www/git/bar with bar@localhost:/var/www/git/bar
  3. When I don't use ssh:// at all, I am still able to clone but get the same error when pushing asfoo but not as bar provided I enable the password.

What am I doing wrong?

Is it because the permissions of .ssh and authorized_keys are too open or not owned by bar?

Even when I go (as sudo) into the bar homedir and make everything owned by him, I still get the same error.

Finally, I have set my .ssh/config for test user foo so that:

Host localhost
     IdentityFile ~/.ssh/foo
     User foo
duancheng6500 虽然这不是你问题的答案,但我认为你以错误的方式攻击它。看看gitolite,如果那个(也不是gitlab)不符合你的需求,看看他们如何实现让用户拥有私有存储库。对于所有用户来说,拥有一个git用户是一个更容易的解决方案。许多unix用户很难以一种好的方式取得成功。
4 年多之前 回复


It turns out it was indeed the permissions. tailing the /var/log/auth.log provided the insight:

Authentication refused: bad ownership or modes for directory /var/www/git/bar

Googling this I figured out the problem was that the entire home directory was accessible by the group.

So back to square one, allowing www-data to be part of the group with +rwx is not a possibility, since it breaks ssh.


The comment from iveqy was very wise, using unix users for this sort of operation is an overkill and opens potential security holes, since it requires that you escalate user www-data to a superuser.

I've ended up using gitolite-admin the following way (I am adding it for future reference on how www-data the apache user under Debian/Ubuntu can control gitolite).


The webserver apache2 runs as www-data on the system. All php scripts are executed as www-data. This requires that we enable this user to administrate our git server automatically.

For gitolite to work, it requires that the administrator provides an ssh key. This in turn requires that user www-data (apache2) has a pair of ssh keys. The key pair must be protected else ssh won't work:

  • create a new user git with home directory in: /var/www/git
  • sudo adduser git --home /var/www/git
  • cd into /var/dir/git and remove all skeleton files (.bashrc, .profile, .bash_logout)
  • log locally as user git: su - git and use the password you created earlier
  • make sure permissions of git user home dir are set to 755 (g+rx)
  • create the .ssh dir: mkdir .ssh and then make it private: chmod 700 -R .ssh

Now as www-data create your ssh key (exit from git user):

  • go into /var/www/ and create an ./ssh owned by www-data and with 700 mask.
  • sudo -u www-data ssh-keygen -t rsa

If everything went accordingly, copy your /var/www/.ssh/ into /var/www/git/.ssh/

  • give ownership of key to user git: sudo chown git.git .ssh/
  • log back in as git: su - git
  • make the pub key private: chmod 600 .ssh/

Time to install gitolite:

  • git clone git://
  • mkdir -p $HOME/bin
  • gitolite/install -to $HOME/bin

Setup the www-data public rsa key to be used as the administrator of gitolite:

  • $HOME/bin/gitolite setup -pk .ssh/

You should get:

Initialised empty Git repository in /var/www/git/repositories/gitolite-admin.git/ Initialised empty Git repository in /var/www/git/repositories/testing.git/ WARNING: /var/www/git/.ssh/authorized_keys missing; creating a new one (this is normal on a brand new install)

the user git is now setup. logout: exit


We will clone it locally, and control it from there. Clone it as user www-data:

  • first create the local copy owned by www-data: sudo mkdir gitolite-admin && chown -R www-data.www-data gitolite-admin/
  • then execute as user www-data the command: sudo -u www-data git clone git@localhost:gitolite-admin gitolite-admin/

This clones the gitolite-admin in /var/www/gitolite-admin from which you control the gitolite server.

For instructions on how to control the gitolite-server, see:

From now on, any gitolite command you execute, execute it as user www-data. Any command run as root or with sudo will break the server!

PS: I accept no responsibility if this breaks your apache configuration. I hope it helps anyone coming here for the same reason I did: creating a git server. I'm open to suggestions and better ideas or improvements.

Csdn user default icon