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

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
| improve this answer | |
  • 1
    This is the correct answer, should be marked. – Xealot Jan 2 '11 at 15:33
  • 50
    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
  • 6
    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
  • 5
    I've never understood why people use sudo su anyway. If you need a root shell, that's what sudo -s or sudo -i is for. – eaj Nov 16 '16 at 14:46
  • 2
    @eaj historical reasons. The sudo -i didn't exist originally, it was added later. So a lot of people got into the habit of sudo su, and lots of docs were written with the old way. Though it has available for ~15 years now. – Zoredache Oct 9 '19 at 21:20
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.

| improve this answer | |
  • 3
    As with the comment above, this only addresses the question if you're becoming root, because in that case root is able to get around the usual access permissions on the $SSH_AUTH_SOCK. – doshea Aug 13 '16 at 8:29
  • 6
    You can also specify to preserve only the SSH_AUTH_SOCK environment variable instead of preserving all environment variables, by using sudo --preserve-env=SSH_AUTH_SOCK – Tyler Rick Jan 3 at 1:49
  • @TylerRick gave the correct answer. – greatvovan May 1 at 23:29

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 ;-)

| improve this answer | |
  • 7
    Remember when using this method, other people logged in as the otheruser can also use your ssh authentication. – gitaarik 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
  • 1
    Why rwx and not rw (or r at all)? – anatoly techtonik Oct 21 '14 at 21:21
  • 3
    @anatolytechtonik From man 7 unix - on Linux connecting to socket requires read and write permissions on that socket. Also you need search (execute) and write permission on the directory where you create socket or only search (execute) permission when you connect to this socket. So in the above answer execute permission on socket is redundant. – mixel Mar 18 '17 at 15:21
  • instead of having to edit /etc/sudoers you can use sudo -u otheruser --preserve-env=HOME -s – Sec Jan 31 '19 at 12:29

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

| improve this answer | |
  • 7
    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
  • 5
    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.

| improve this answer | |
  • He mentioned that at the bottom of his question, and said it would be hard to do. – Fahad Sadah 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) – Fahad Sadah Jan 28 '10 at 16:52

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.

| improve this answer | |
  • This don't work if you only have access to otheruser via sudo instead of over SSH (e.g. you want to SCP stuff as www-data) – Gert van den Berg Sep 27 '19 at 9:31
  • This solved my issue of the mysql command using the original ssh user instead of the su user, probably some bug in its automatic user detection convenience routine. – malhal Jan 2 at 20:45

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

| improve this answer | |

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

| 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? – Fahad Sadah Jan 30 '10 at 7:48
  • 7
    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.

| improve this answer | |
  • 1
    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
  • 1
    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

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.

| improve this answer | |

Your Answer

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