4

I can clone a project as follows:

$ git clone git@mysite.com:root/myproject.git ~/bla

But now I wish to clone it to /var/www. So I try

$ git clone git@mysite.com:root/myproject.git ~/var/www

But alas, I do not have permission to write to /var/www. Sudo to the rescue!

$ sudo git clone git@mysite.com:root/myproject.git ~/var/www
Cloning into 'www'...
git@mysite.com's password:

What's this? I am being asked for a password? We shouldn't need no stinking passwords!

I am obviously sending the root user's ssh keys with the request, and as they have not been imported to the git repository, I am being denied. In the past, my solution has been to temporarily change permissions of the folder or first clone it somewhere I have access and then move it using sudo, but would like to learn the right way to do so.

So... How do I use git with my normal user's ssh keys but sudo file permissions?

  • this will be problematical if your user home directory is encrypted or remote mounted such that the user-being-sudo'd-to cannot read the key materials – thrig Nov 20 '17 at 17:01
  • @thrig Thanks, but fortunately it isn't. – user1032531 Nov 21 '17 at 3:11
0

File (or socket) permissions may be complicated if the key files (or socket) cannot be read by the user sudo runs as. This most definitely includes root if the files reside on a network share that root has no permission to, or should the home directory be encrypted which may again deny root access.

Another way on Unix systems that support extended ACLs is to use those, in which case you can grant additional write access on top of the usual base permissions:

$ sudo chown apache:www /var/www/html
$ sudo chmod g+s /var/www/html
$ sudo setfacl -m g:webedit:rwx /var/www/html
$ groups
jdoe webedit
$ ls -ld /var/www/html
drwxrwsr-x+ 4 apache www 25 Nov 21 19:42 /var/www/html
$ 

but the webedit group has permissions thanks to the setfacl

$ git clone ~/repo /var/www/html
Cloning into '/var/www/html'...
done.
$ ls -al /var/www/html
total 0
drwxrwsr-x+ 4 apache www   25 Nov 21 19:42 .
drwxr-xr-x  4 root   root  31 Oct 19 20:39 ..
drwxrwsr-x  3 jdoe   www   14 Nov 21 19:42 a
drwxrwsr-x  8 jdoe   www  152 Nov 21 19:42 .git
$ 

there are however various gotchas around extended ACLs eg check how your backup software handles them, etc

2

If you have a ssh agent running, do:

sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" git clone...

That basically tells the git command started by root (or the ssh command started by that git command) to use your ssh agent (how to connect to it, which root should be able to as it has every right).

If you don't have a ssh agent running, you can start one beforehand with:

eval "$(ssh-agent)"

(and add keys to it as needed with ssh-add).

Alternatively, you can use

sudo -E git clone...

To pass every environment variable across sudo, not just $SSH_AUTH_SOCK.

I would not got with @NgOon-Ee's suggestion in comment to add $SSH_AUTH_SOCK to the env_keep list. In general, you don't want to pollute root's environment, as that's the user you start services as. For instance sudo sshd to start a sshd service would mean all ssh sessions started through that service would inherit your $SSH_AUTH_SOCK, polluting users environment with something they can't and shouldn't use. Even for other target users than root, passing that variable across would not make sense as the target user couldn't make use of that authentication agent.

Now, that only addresses key authentication. If you also wanted root to inherit your settings in your ~/.ssh/config, you could not do that with ssh environment variables, but you could do that with git environment variables. For instance, defining a sugit function as:

sugit() {
  sudo "GIT_SSH_COMMAND=
    exec ssh -o IdentityAgent='$SSH_AUTH_SOCK' \
             -o User=$LOGNAME \
             -F ~$LOGNAME/.ssh/config" git "$@"
}

That is, tell git to use a ssh command that uses your ssh config file and agent and username instead of root's.

Or maybe even better, tell git to run ssh as the original user:

sugit() {
  sudo "GIT_SSH_COMMAND=
    exec sudo -Hu $LOGNAME SSH_AUTH_SOCK='$SSH_AUTH_SOCK' ssh" git "$@"
}
  • This won't help if there's anything in .ssh/config needed (e.g. a ProxyCommand). Also the right way for this solutions would be to use visudo and add SSH_AUTH_SOCK to env_keep – Ng Oon-Ee Nov 20 '17 at 18:40
  • Thanks Stephane, Appreciate your solution, but kind of surprised there is not a more intuitive one. – user1032531 Nov 21 '17 at 3:15
  • @NgOon-Ee, see edit. – Stéphane Chazelas Nov 21 '17 at 10:08
  • Fair point in env_keep, but I would still prefer that in the (IMO most common) single user configuration. Sudo is used fairly rarely in modern Linux, and perhaps shouldn't even be used here (maybe I'll write up that answer as an alternative). – Ng Oon-Ee Nov 21 '17 at 10:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.