How to Get SSH to Work with 1Password, Docker Desktop, and macOS Within a Container

Jay Rogers

October 11st, 2024

Blog post header image

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.

SSH Agent Configuration

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:

SSH Config

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:

Launch Docker Desktop

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 Command

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:

SSH Config Issue

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

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

Workaround Commands

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:

SSH Key Test

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.

Want to work together?

Professional developers choose Server Side Up to ship quality applications without surrendering control. Explore our tools and resources or work directly with us.

Join our community

We're a community of 3,000+ members help each other level up our development skills.

Platinum Sponsors

Active Discord Members

We help each other through the challenges and share our knowledge when we learn something cool.

Stars on GitHub

Our community is active and growing.

Newsletter Subscribers

We send periodic updates what we're learning and what new tools are available. No spam. No BS.

Sign up for our newsletter

Be the first to know about our latest releases and product updates.

    Privacy first. No spam. No sharing. Just updates.