Why Your SSH Keys Vanish When 1Password Is Your Agent

When 1Password is your SSH agent, ssh-copy-id can't find your keys — and ssh-add can't either. Here's the workaround.

Why ssh-copy-id exists

When you set up SSH key auth on a new server, you need to get your public key into ~/.ssh/authorized_keys on the remote machine. You can do this manually — SSH in with a password, create the directory, set the permissions, paste the key, set more permissions. It’s like five commands and you have to get the chmod numbers right or SSH silently ignores the whole thing.

ssh-copy-id does all of that in one shot. It reads your public key, SSHs into the remote host, creates the directory, appends the key, sets the permissions. Done. On macOS it doesn’t come preinstalled, but it’s a brew install ssh-copy-id away.

Except if you’re using 1Password as your SSH agent, it doesn’t work. And figuring out why it doesn’t work is the annoying part.

How it’s supposed to work

Right, so normally with SSH, you’ve got two files sitting on your disk like a pair of socks. A private key and a public key.

# Your two little files, living their best life on disk.
~/.ssh/id_ed25519      # private key — the one you never show anyone
~/.ssh/id_ed25519.pub  # public key — the one you hand out like a business card

The ssh-agent loads the private key into memory so you’re not typing your passphrase every thirty seconds like some kind of animal. And the whole system talks through one socket — SSH_AUTH_SOCK. Both ssh and ssh-add use it. ssh-copy-id reads the .pub file from disk and shoves it onto the remote server. Simple. Everything knows where everything is. It’s beautiful.

# The old way. It just works. Remember when things just worked?
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
ssh-copy-id user@server

What 1Password changes

You moved your SSH keys into 1Password. And look, it’s a good idea. Your private key now lives in an encrypted vault behind biometrics instead of sitting in a plaintext file on your laptop like it’s 2009. 1Password runs its own SSH agent, and your ~/.ssh/config tells SSH to use it:

Host *
    # "Talk to 1Password, not the default macOS agent."
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

And SSH works great. You type ssh user@server, 1Password pops up, you touch your fingerprint like you’re in a spy film, key gets served. Lovely.

Then you get a new server and you go to copy your key over.

ssh-copy-id user@newhost
# /usr/bin/ssh-copy-id: ERROR: No identities found

Right. Because ssh-copy-id wants to read a .pub file off disk. There is no file. Your key’s in 1Password. You’ve taken the file away and ssh-copy-id is standing there going “where’s the file? I was told there’d be a file.”

OK fine. You’ll ask the agent for the public key:

ssh-add -L
# "The agent has no identities."

But you JUST used SSH. 1Password JUST served the key. What the hell?

Here’s the thing. IdentityAgent is an SSH config directive. It only applies to programs that actually read ~/.ssh/config — that’s ssh, scp, sftp. Programs that went to the effort of reading the config file.

ssh-add? It doesn’t read your SSH config. It talks directly to whatever SSH_AUTH_SOCK points at. And SSH_AUTH_SOCK still points at the macOS default agent, which has absolutely nothing in it.

echo $SSH_AUTH_SOCK
# /var/run/com.apple.launchd.xxxxx/Listeners  — the macOS agent, not 1Password

So you’ve got two agents running. SSH talks to the right one because it reads the config. ssh-add talks to the wrong one because it doesn’t. Two paths to get the public key, both broken. Fantastic.

The fix

Stop trying to go through the agent. 1Password has a CLI. It can read any field from any item in your vault, and that includes the public key. Pipe it to the remote host the same way ssh-copy-id would’ve:

# Goes straight to 1Password. Doesn't care about agents or sockets.
op read "op://VaultName/id_ed25519/public key" | ssh user@newhost \
    "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

That’s it. One command. No socket juggling. op talks to 1Password directly — it couldn’t care less about SSH_AUTH_SOCK or IdentityAgent or any of that.

Don’t skip this bit

If op read fails — wrong vault name, 1Password locked, you forgot to sign in to the CLI — the pipe doesn’t care. It keeps going. Whatever lands on stdout gets written into authorized_keys on the remote host.

And this is exactly what happens if you try the ssh-add -L approach with the wrong agent:

cat ~/.ssh/authorized_keys
# The agent has no identities.

That. That string. That error message. Is now sitting in your authorized_keys file. On your server. SSH will ignore it because it’s not a valid key format, but imagine finding that at 11pm when you’re trying to figure out why key auth isn’t working. You’ll lose your mind.

So check the output first:

pubkey=$(op read "op://VaultName/id_ed25519/public key")
echo "$pubkey"  # should start with ssh-ed25519 or ssh-rsa, not an error message
echo "$pubkey" | ssh user@newhost \
    "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Once that’s done, ssh user@newhost should drop you straight into a shell — no password prompt, no drama. If it still asks for a password, SSH in the old-fashioned way and cat ~/.ssh/authorized_keys — if you see an error message where a key should be, you know what happened.

  • ssh-copy-id fails with 1Password because there's no .pub file on disk and ssh-add talks to the wrong agent
  • Use op read to pull the public key straight from your vault — no agent socket needed
  • Always check the output before piping to authorized_keys — error messages make surprisingly convincing-looking key files

If you’ve been burned by SSH agent confusion or have opinions on password managers doubling as key stores, come find me on Bluesky, Mastodon, Twitter X, or LinkedIn. More code and config tinkering on GitHub.