7

I can clone a project as follows:

$ git clone [email protected]:root/myproject.git ~/bla

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

$ git clone [email protected]:root/myproject.git ~/var/www

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

$ sudo git clone [email protected]:root/myproject.git ~/var/www
Cloning into 'www'...
[email protected]'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?

2
  • 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, 2017 at 17:01
  • @thrig Thanks, but fortunately it isn't. Nov 21, 2017 at 3:11

2 Answers 2

7

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 "$@"
}
5
  • 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, 2017 at 18:40
  • Thanks Stephane, Appreciate your solution, but kind of surprised there is not a more intuitive one. Nov 21, 2017 at 3:15
  • @NgOon-Ee, see edit. Nov 21, 2017 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, 2017 at 10:16
  • I ran into some problems with using git over https with git lfs (it wants to put in the password for every single file downloaded), so I tried swapping to an ssh connection but couldn't sudo clone in my production environment. All I needed was that sudo -E. Now it's working like a dream with my ssh key. Aug 19, 2020 at 18:04
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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .