Skip to content

Instantly share code, notes, and snippets.

@d11wtq
Created January 29, 2014 23:32
Show Gist options
  • Save d11wtq/8699521 to your computer and use it in GitHub Desktop.
Save d11wtq/8699521 to your computer and use it in GitHub Desktop.
How to SSH agent forward into a docker container
docker run -rm -t -i -v $(dirname $SSH_AUTH_SOCK) -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK ubuntu /bin/bash
@leandrocrs
Copy link

@Sylvain, give a chance to WSL (Windows Subsystem for Linux).

@dragon788
Copy link

@kynan if you aren't using a remote user database for your system (eg LDAP/AD) you can map in /etc/passwd read-only so SSH can find your user.

Copy link

ghost commented Nov 9, 2017

Maybe, there is similar way to integrate gpg into docker container?

@tamsky
Copy link

tamsky commented Aug 4, 2018

@ghost asks

Maybe, there is similar way to integrate gpg into docker container?

Browsing around, I saw this: https://github.com/transifex/docker-gpg-agent-forward

@marxangels
Copy link

marxangels commented Mar 5, 2019

How if docker-compose and docker-daemon not in a same machine such as boot2docker?
I want to put this bunch of parameters in the docker-compose.yaml instead of typing them every time.

@sbussetti
Copy link

sbussetti commented Jul 8, 2019

For anyone who comes across this: This will not work for anyone using Docker for Mac due to os limitations around file socket access. See: docker/for-mac#410

@benjertho
Copy link

This works for me for the first shell logon, but fails for successive attempts. My use case is a remote container that has a longer lifespan, usually of a couple weeks. Is there a solution that is robust against the changing of the SSH_AUTH_SOCK target?

docker run -dit \
	--network host \
	--gpus all \
	--restart unless-stopped \
	--privileged \
	-e "DISPLAY=$DISPLAY" \
	-e "QT_X11_NO_MITSHM=1" \
        -e "$SSH_AUTH_SOCK:/ssh-agent" \
        -e "SSH_AUTH_SOCK=/ssh-agent" \
	-v "$XSOCK:$XSOCK" \
	-v "$HOME/data:/root/data:rw" \
	-v "$HOME/.gitconfig:/root/.gitconfig" \
	--name $NAME $NAME:latest bash

@jameshopkins
Copy link

The official guidance works for me, when nothing else has. It's not very well explained, but the bind mount paths are magic values to allow SSH agent forwarding.

@GuillermoAndrade
Copy link

-e "$SSH_AUTH_SOCK:/ssh-agent" \

maybe -v here instead of -e ?

@timur265
Copy link

timur265 commented Apr 21, 2021

Hi everyone. I have the same problem. Has anyone found the solution?
This works for me for the first shell login, but fails for successive attempts

sudo docker run --restart always --network host --name github-runner -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent -e REPO_URL="$REPO_NAME" -e ACCESS_TOKEN="$ACCESS_TOKEN" myoung34/github-runner:latest

@conf
Copy link

conf commented May 24, 2021

If you're on a mac, the current incantation should be:

docker run -it --rm -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" debian bash

@tomdavies
Copy link

For anyone struggling to get ssh-agent forwarding to work for non-root container users, here's the workaround I came up with, running my entry point script as root, but using socat + su-exec to expose the socket to the non-root user and then run commands as that user:

  1. Add socat and su-exec to the container in your Dockerfile (you might not need the later if you're not using alpine)
USER root
RUN apk add socat su-exec
# for my use case I need www-data to have access to SSH, so 
RUN \
    mkdir -p /home/www-data/.ssh && \
    chown www-data:www-data /home/www-data/.ssh/
  1. In your entrypoint:
#!/bin/sh
# Map docker's "magic" socket to one owned by www-data
socat UNIX-LISTEN:/home/www-data/.ssh/socket,fork,user=www-data,group=www-data,mode=777 \
    UNIX-CONNECT:/run/host-services/ssh-auth.sock \
    &
# set SSH_AUTH_SOCK to the new value
export SSH_AUTH_SOCK=/home/www-data/.ssh/socket
# exec commands as www-data via su-exec
su-exec www-data ssh-add -l
# SSH agent works for the www-data user, in reality you probably have something like su-exec www-data "$@" here
  1. Run your container as @conf states:
docker run -it --rm -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" name cmd

@unphased
Copy link

shrug this: -v "$SSH_AUTH_SOCK:$SSH_AUTH_SOCK" -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK worked for me. The original gist did not.

@josepsmartinez
Copy link

@unphased Probably due to the symlink situation, as @arunthampi noticed here.

The line the worked for me was docker run -i -t -v $(readlink -f $SSH_AUTH_SOCK):/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent ubuntu /bin/bash

@Paprikas
Copy link

Paprikas commented Jun 7, 2022

@unphased
volume $SSH_AUTH_SOCK:/ssh-agent
and ENV SSH_AUTH_SOCK=/ssh-agent worked for me for years.
But after I've upgraded packages to the latest (ubuntu 22), the agent just stopped working! I mean - ssh-add -l was saying that it does not have access to the agent.
Thank you, your snippet works! Spent the whole day on this issue ))

@wirwolf
Copy link

wirwolf commented Dec 22, 2023

Check if you use docker from snap. In my Kubuntu 22.04 I remove docker from snap and install using apt and problem is fixed

@vokshirg
Copy link

vokshirg commented Feb 6, 2024

the latest official documentation helped me with docker-compose setup
https://docs.docker.com/desktop/networking/#ssh-agent-forwarding

@sourcecodemage
Copy link

is there a version of setup for Redhat linux and distributions based on it like CentOS and Rocky?

@sourcecodemage
Copy link

the latest official documentation helped me with docker-compose setup https://docs.docker.com/desktop/networking/#ssh-agent-forwarding

That seems to be specific to Docker Desktop. What about Colima and/or Podman?

@philippkemmeter
Copy link

Based on @tomdavies post, i created this Dockerfile which uses the USER statement in order to have an unpriviledged container instead of su-exec:

FROM python:3.11.6-alpine

RUN apk --no-cache add --update \
    socat \
    sudo

RUN addgroup --gid 1001 -S ansible && adduser --uid 1001 -S ansible -G ansible -h /home/ansible
RUN echo 'ansible ALL=(ALL:ALL) NOPASSWD:/usr/local/bin/create-ansible-agent-socket.sh' > /etc/sudoers
RUN echo 'socat UNIX-LISTEN:/home/ansible/.ssh/agent,fork,user=ansible,group=ansible,mode=777 UNIX-CONNECT:/root/.ssh/agent' > /usr/local/bin/create-ansible-agent-socket.sh
RUN chmod +x /usr/local/bin/create-ansible-agent-socket.sh
RUN echo 'sudo /usr/local/bin/create-ansible-agent-socket.sh & SSH_AUTH_SOCK=/home/ansible/.ssh/agent "$@"' > /entrypoint.sh

USER ansible
RUN mkdir -p /home/ansible/.ssh && chown ansible:ansible /home/ansible/.ssh

ENTRYPOINT [/bin/sh, /entrypoint.sh]

you run it then with

docker run -it -u ansible \
    -v "$SSH_AUTH_SOCK":/root/.ssh/agent \
    -e SSH_AUTH_SOCK=/root/.ssh/agent \
    name cmd

@sadanand1120
Copy link

@benjertho After struggling for hours with the same problem (works on first shell login but after that fails), I tried a hack and it worked! Sharing here:

  • Add an entrypoint line to dockerfile
    ENTRYPOINT ["/ros_entrypoint.sh"]

  • In entrypoint script, add the following at the top:

# Dynamically set SSH_AUTH_SOCK if it's available in the mounted /tmp directory
if [ -n "$(find /tmp -type s -name 'agent.*' 2>/dev/null)" ]; then
  export SSH_AUTH_SOCK=$(find /tmp -type s -name 'agent.*' 2>/dev/null)
fi
  • Add the following to your compose.yaml:
environment:
    - SSH_AUTH_SOCK=/tmp/ssh-agent
volumes:
    - /tmp:/tmp

Now the ssh auth sock will be set appropriately every time.

@nocanstillbb
Copy link

run docker -p  222:22 && apt install openssh-server &&  $(edit /etc/ssh/sshdconfig to enable root login)

on your mac of git bash

eval $(ssh-agent -s)
ssh-add 
ssh -A  toDockerContainer

@x85446
Copy link

x85446 commented Dec 5, 2024

Thanks! You pointed me in the right direction for a very similar problem. Here’s my take on it, implemented within a Makefile. This is very much specific to a mac os problem with a Docker Desktop solution.

# izumanetworks.com ai-edge-runner
run:
    @if [ -z "$(WORKSPACE_PATH)" ]; then \
        echo "Error: Please specify the path to map using MAP=/path/to/map"; \
        exit 1; \
    fi
    @if [ -z "$(SSH_AUTH_SOCK)" ]; then \
        echo "Error: SSH agent is not running. Please start it with 'eval $$(ssh-agent -s)' and add your key with 'ssh-add'."; \
        exit 1; \
    fi
    docker run -it \
        --name $(CONTAINER_NAME) \
        -e SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock \
        -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock \
        -v $(WORKSPACE_PATH):/izuma \
        --entrypoint /bin/bash \
        $(IMAGE_NAME)

The magic is that even though macOS doesn’t have a /run/blah/blah path, Docker Desktop creates /run/host-services/ssh-auth.sock as a special bridge to your host system’s SSH_AUTH_SOCK.

To test, run ssh-add -l inside the container to list your keys and ssh -T git@github.com to verify connectivity. This approach works seamlessly with Docker Desktop on macOS.

@hannylicious
Copy link

the latest official documentation helped me with docker-compose setup https://docs.docker.com/desktop/networking/#ssh-agent-forwarding

That seems to be specific to Docker Desktop. What about Colima and/or Podman?

Did you ever figure this out on Podman specifically?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment