How to get SSH to work with 1password + Docker Desktop + macOS (within a container)

Jay Rogers avatar
Jay Rogers October 11th, 2024

Background

@nckrtl and I have been working together on trying to resolve his issue. We learned a lot and I am putting together this guide as initial notes.

Important concepts to understand

  • 1password stores your SSH keys in it’s vault (you don’t keep your keys in ~/.ssh
  • You must follow their guide on how to create/import SSH keys
  • Once a key is saved, you use the 1password SSH Agent to securely load and authorize use of your keys
  • šŸ‘‰ REMEMBER: Docker Desktop does not run docker natively on your Mac, so they created this /run/host-services/ssh-auth.sock that will return a mounted

Set up

Use these steps to complete set up.

Generate your SSH key

Follow the 1password docs to generate your SSH key. The SSH key should be stored in their vault, not in your ~/.ssh.

Enable the 1password SSH Agent

Follow the docs to enable the 1password SSH Agent.

Where things start to get confusing

When you first enable your agent, you’ll be prompted to add this to your ~/.ssh/config file.

NOTE: If you mount your SSH directory into your container (which you probably want to), your container will want to reference ~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock which probably WILL NOT exist without some configuration.

Screenshot 2024-10-11 at 14 30 55@2x

Understanding IdentityAgent vs SSH_AUTH_SOCK

In my testing, the IdentityAgent wasn’t always required but the 1password documentation talks about this more in their Working with SSH clients section on how you can pick and choose.

In this example, we’re assuming you’re following what 1password wants you to do with the SSH config, which adds a little extra work for your container.

We’re assuming you have a ~/.ssh/config that looks like this on your host:

Host *
    # You might not need this line. Read this for more:
    # https://developer.1password.com/docs/ssh/agent/compatibility/#working-with-ssh-clients
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

Another layer of confusion: Docker Desktop on macOS

When you’re running Docker Desktop, Docker runs very differently as it would on a Linux machine running the Docker engine. Docker Desktop runs a tiny virtual machine to run the Docker daemon that sits in between your macOS host and the Docker engine. This adds another level of complexity.

Docker Desktop Doesn’t inherit shell environments by default

One really confusing thing was I was setting all of these configurations and I couldn’t get it to work. It wasn’t until I saw this post by a 1password employee that explains Docker Desktop is managed by launchd on macOS and it will not inherit the shell environment by default.

I had to close Docker Desktop and launch it with:

open -a /Applications/Docker.app/

To get this to work permanently, you need to configure a .plist file following the “Configure SSH_AUTH_SOCK globally for every client” in the 1password documentation.

Exposing the SSH Auth socket with Docker + macOS

Docker Desktop provides a “magic” path to share your SSH Auth Socket at /run/host-services/ssh-auth.sock. This means we need to mount this path and set the $SSH_AUTH_SOCK variable in the container.

docker run -it --rm \
 \
  # Mount the `.ssh` directory as READONLY
  -v "$HOME/.ssh:/.ssh:ro" \
  # Mount the known_hosts as READ-WRITE
  -v "$HOME/.ssh/known_hosts:/.ssh/known_hosts:rw" \
  # Set the magic auth socket for Docker Desktop
  -v "/run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock" \
  # Set the SSH_AUTH_SOCK variable in the container to point to our magic
  -e "SSH_AUTH_SOCK=/run/host-services/ssh-auth.sock" \
  # Set your image (this is our image with SSH installed)
  docker.io/serversideup/ansible-core:alpine sh

Where the SSH Config confusion comes in

Now that we have the following:

  • āœ… A mounted SSH directory (as read only)
  • āœ… A mounted authorized keys file (as read/write)
  • āœ… The /run/host-services/ssh-auth.sock mounted to /run/host-services/ssh-auth.sock in the container
  • āœ… The SSH_AUTH_SOCK variable set to /run/host-services/ssh-auth.sock in the container
  • āŒ The ability for Alpine Linux to understand your ~/.ssh/config file

The problem lies with this part of the config:

IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

That does not exist in the Alpine container. As a workaround, we create this :

mkdir -p "$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t"
ln -sf "$SSH_AUTH_SOCK" "$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

This essentially creates the file and we symbolically link it to the Docker Socket, which then links it to your host šŸ¤Æ

Testing

You’ll know if everything is working correctly if you run ssh-add -l in the container and it comes back with something like:

256 SHA256:4G9mDIDnn1VsLZFSWYMzvsyzF9I4n4HghjKDIeMIKcE SSH Key (ED25519)

Advanced Usage: Dropping Privileges

If you intend to run an unprivileged user, be sure your user has permissions to access the sockets.

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Jay

Jay Rogers avatar Jay Rogers

Iā€™m a DevOps engineer who accidentally ended up in application & user-experience design. ?? I'm a husband and proud dog-dad who co-founded 521 Dimensions & Server Side Up. I like to having meaningful conversations with people who love building things. Please reach out and say hello!

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.