Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

If I have a server A into which I can login with my ssh key and I have the ability to "sudo su - otheruser", I lose key forwarding, because the env variables are removed and the socket is only readable by my original user. Is there a way I can bridge the key forwarding through the "sudo su - otheruser", so I can do stuff on a server B with my forwarded key (git clone and rsync in my case)?

The only way I can think of is adding my key to authorized_keys of otheruser and "ssh otheruser@localhost", but that's cumbersome to do for every user and server combination I may have.

In short:

$ sudo -HE ssh user@host
$ sudo -HE -u otheruser ssh user@host
Permission denied (publickey). 
share|improve this question

10 Answers 10

As you mentioned, the environment variables are removed by sudo, for security reasons.

But fortunately sudo is quite configurable: you can tell it precisely which environment variables you want to keep thanks to the env_keep configuration option in /etc/sudoers.

For agent forwarding, you need to keep the SSH_AUTH_SOCK environment variable. To do so, simply edit your /etc/sudoers configuration file (always using visudo) and set the env_keep option to the appropriate users. If you want this option to be set for all users, use the Defaults line like this:

Defaults    env_keep+=SSH_AUTH_SOCK

man sudoers for more details.

You should now be able to do something like this (provided user1's public key is present in ~/.ssh/authorized_keys in user1@serverA and user2@serverB, and serverA's /etc/sudoers file is setup as indicated above):

user1@mymachine> eval `ssh-agent`  # starts ssh-agent
user1@mymachine> ssh-add           # add user1's key to agent (requires pwd)
user1@mymachine> ssh -A serverA    # no pwd required + agent forwarding activated
user1@serverA> sudo su - user2     # sudo keeps agent forwarding active :-)
user2@serverA> ssh serverB         # goto user2@serverB w/o typing pwd again...
user2@serverB>                     # ...because forwarding still works
share|improve this answer
This is the correct answer, should be marked. – Xealot Jan 2 '11 at 15:33
This only works, if user2 above is root! Otherwise, user2 will have SSH_AUTH_SOCK set up correctly, but the user2 won't be able to access e.g. /tmp/ssh-GjglIJ9337/. root does have that access. So this may solve part of the problem, but not the OPs: "and the socket is only readable by my original user" – Peter V. Mørch Nov 4 '11 at 21:00
Defaults>root env_keep+=SSH_AUTH_SOCK Should make sure it only forwards when sudoing to root. You don't want to do that anyways to other users for security reasons. Better run a separate ssh-agent for otherother, and add the appropriate keys. – Paul Schyska Aug 24 '14 at 10:32
sudo su - doesn't work for me, presumably it can't preserve environment because it's not sudo at shell startup time. sudo su seems to work. – dadooda May 19 at 11:25
sudo -E -s
  • -E will preserve the environment
  • -s runs a command, defaults to a shell

This will give you a root shell with the original keys still loaded

share|improve this answer

Allow otheruser to access $SSH_AUTH_SOCK file and it's directory, for example by correct ACL, before switching to them. The example assumes Defaults:user env_keep += SSH_AUTH_SOCK in /etc/sudoers on host machine:

$ ssh -A user@host
user@host$ setfacl -m otheruser:x   $(dirname "$SSH_AUTH_SOCK")
user@host$ setfacl -m otheruser:rwx "$SSH_AUTH_SOCK"
user@host$ sudo su - otheruser
otheruser@host$ ssh server

More secure and works for non-root users as well ;-)

share|improve this answer
Remember when using this method, other people logged in as the otheruser can also use your ssh authentication. – rednaw Nov 27 '13 at 14:49
This works for me except I had to change "sudo su - otheruser" to "sudo su otheruser" (removing the -). – Charles Finkel Mar 17 '14 at 18:09
Why rwx and not rw (or r at all)? – anatoly techtonik Oct 21 '14 at 21:21

I have found that this also works.

sudo su -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"

As others have noted, this won't work if the user you are switching to doesn't have read permissions on $SSH_AUTH_SOCK (which is pretty much any user besides root). You can get around this by setting $SSH_AUTH_SOCK and the directory it is in to have the permissions 777.

chmod 777 -R `dirname $SSH_AUTH_SOCK`
sudo su otheruser -l -c "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK; bash"

This is pretty risky though. You are basically giving every other user on the system permission to use your SSH Agent (until you log out). You may also be able to set the group and change the permissions to 770, which could be more secure. However, when I tried changing the group, I got "Operation not permitted".

share|improve this answer
This is extremely risky. Giving every other user permission to use your SSH agent is equivalent to giving them all your credentials (and if you ever use sudo or su, giving them root power over all other users on system, as well as all other systems you ssh to!). This must NEVER EVER be done! – Matija Nalis Mar 6 '14 at 18:11
I disagree with the statement that "This must NEVER EVER be done!" There are many cases where this risk is acceptable. For example, a small team where everyone has the same permissions and you trust all the other users. It should never be done without understanding the risks it involves. But once those risks are understood, there are times that risk is acceptable. – phylae Mar 7 '14 at 22:52

If you are authorized to sudo su - $USER, then you would probably have a good argument for being permitted to do a ssh -AY $USER@localhost instead, with your valid public key in $USER's home directory. Then your authentication forwarding would be carried through with you.

share|improve this answer
He mentioned that at the bottom of his question, and said it would be hard to do. – fahadsadah Jan 28 '10 at 16:46
This is probably the best solution but it gets hairy if $USER is a Real Person(tm) -- they might delete the SA's key from authorized_keys or change their password... – voretaq7 Jan 28 '10 at 16:48
You can remove their write access to authorized_keys (though if they really are set on denying Florian access, they can delete and recreate it, it being in a directory they own) – fahadsadah Jan 28 '10 at 16:52

Don't use sudo su - USER, but rather sudo -i -u USER. Works for me!

share|improve this answer
What version of sudo do you have? Mine (1.6.7p5, CentOS 4.8) doesn't have -i in its man page. – David Mackintosh Jan 28 '10 at 20:58
Sudo version 1.6.9p17 running on Debian Lenny. Try sudo -s? – fahadsadah Jan 30 '10 at 7:48
Doesn't work for me. – Florian Schulze Feb 1 '10 at 12:31
On Ubuntu, using Sudo 1.8.9p5, neither sudo -s nor sudo -i work for me... – Jon L. Dec 29 '14 at 16:12

Unfortunately when you su to another user (or even use sudo) you'll lose the ability to use your forwarded keys. This is a security feature: You don't want random users connecting to your ssh-agent and using your keys :)

The "ssh -Ay ${USER}@localhost" method is a little cumbersome (and as noted in my comment on David's answer prone to breakage), but it's probably the best you can do.

share|improve this answer
Hmm, but if I do this with ssh, then my agent is accessible by that user anyway, or am I wrong? – Florian Schulze Feb 1 '10 at 12:34
If you SSH into the target user with agent forwarding your agent requests will bounce up the chain to wherever the "real" agent is. When you su or sudo away from the original user your SSH agent socket won't (or shouldn't) be accessible -- The directory it lives in is mode 700 & owned by the original user. (Obvious Caveat: If you're switching to root & reset the SSH_AUTH_SOCK environment it might work, but I wouldn't rely on it) – voretaq7 Feb 1 '10 at 16:14
On my server (Ubuntu 12.04, ssh version OpenSSH_5.9p1 Debian-5ubuntu1.1, OpenSSL 1.0.1 14 Mar 2012), ssh has -a and -A arguments. -a does the exact opposite of what's intended, it disables agent forwarding! So, under recent (and possibly all) version of Ubuntu, use -A to enable agent forwarding. – knite Jun 26 '13 at 2:25
@knite You are correct - that's a (3 year old!) typo in my answer. Fixed now :-) – voretaq7 Jun 26 '13 at 17:13

You can always just ssh to localhost with agent forwarding instead of using sudo:

ssh -A otheruser@localhost

Disadvantage is that you need to log in again, but if you're using it in a screen/tmux tab, that's only a one time effort, however, if you disconnect from the server, the socket will (of course) be broken again. So it's not ideal if you can't keep your screen/tmux session open at all times (however, you could manually update your SSH_AUTH_SOCK env var if you're cool).

Also note that when using ssh forwarding, root can always access your socket and use your ssh authentication (as long as you're logged in with ssh forwarding). So make sure you can trust root.

share|improve this answer

Combining information from the other answers I came up with this:

setfacl -m $user:x $(dirname "$SSH_AUTH_SOCK")
setfacl -m $user:rwx "$SSH_AUTH_SOCK"
sudo SSH_AUTH_SOCK="$SSH_AUTH_SOCK" -u $user -i

I like this because I don't need to edit sudoers file.

Tested on Ubuntu 14.04 (had to install acl package).

share|improve this answer

I think there is a problem with the - (dash) option after su in your command:

sudo su - otheruser

If you read the man page of su, you may find that the option -, -l, --login starts the shell environment as login shell. This will the environment for otheruser regardless of the env variables where you run su.

Simply put, the dash will undermine anything you passed from sudo.

Instead, you should try this command:

sudo -E su otheruser

As @joao-costa pointed out, -E will preserve all variables in the environment where you ran sudo. Then without the dash, su will use that environment directly.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.