Skip to content
Theme:

Multiple SSH keys for multiple Bitbucket/GitHub accounts

I recently joined a new project whereby a version control repository is hosted on Bitucket. It is time to create an account, clone the repo and smash some code! Not that easy — this is what I got when I tried to add my public SSH key to newly created account.

Someone has already added that SSH key.

That’s right, I had this key already added under my personal account. Luckily the solution is simple and it applies the same, not only to Bitbucket, but also to other popular version control hosting services like GitHub or GitLab.

“Key is already in use” alert on GitHub
  1. Generate multiple SSH keys
  2. Add new keys to SSH agent
  3. Add public keys to individual Bitbucket accounts
  4. Configure SSH
  5. Change the upstream URL of already existing repository

Generate multiple SSH keys

If we can’t use the same SSH key across multiple accounts (what makes perfect sense) the solution is to have multiple. Let’s create two new pairs of SSH keys, one for personal use and the other one for the clients project.

ssh-keygen -t rsa -b 4096 -C "personal@email.com" -f id_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ~/.ssh/id_rsa.
Your public key has been saved in ~/.ssh/id_rsa.pub.
ssh-keygen -t rsa -b 4096 -C "client@email.com" -f id_rsa-client
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ~/.ssh/id_rsa-client.
Your public key has been saved in ~/.ssh/id_rsa-client.pub.

Add new keys to SSH agent

To make use of the newly created keys, we need to add them to ssh-agent, a program that holds private keys used for public authentication. The ssh-agent is probably running in the background of your operating system, but just in case lets turn it on and add new keys to it using ssh-add.

eval "$(ssh-agent -s)"
ssh-add -K id_rsa
ssh-add -K id_rsa-client

The -K flag adds a new key to the macOS keychain. If you’re not using Apple’s operating system, please skip this flag. To confirm that both keys have been successfully added we can use ssh-add -l command.

4096 SHA256:XXXXXX personal@email.com (RSA)
4096 SHA256:XXXXXX client@email.com (RSA)

Add public keys to individual Bitbucket accounts

Add the newly created public keys to individual Bitbucket account. To copy the content of a file to the clipboard, use the pbcopy program.

pbcopy < ~/.ssh/id_rsa.pub
pbcopy < ~/.ssh/id_rsa-client.pub
Add SSH key to Bitbucket account

Configure SSH

SSH config file is where the magic lies. We need to create a configuration file and create custom aliases that are going to enforce usage or particular key for particular host. Let’s do it!

touch .ssh/config
Host bitbucket-client.org
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/id_rsa-client
  IdentitiesOnly yes

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa

From now on, every time when you clone a repo from client’s account simply replace bitbucket.com with bitbucket-client.com. Example:

❌ git clone git@bitbucket.org:client/project.git
✅ git clone git@bitbucket-client.org:client/project.git

By doing so, you are skipping a default public key resolution, and explicitly pointing your ssh-agent to always resolve connection to bitbucket-client.org using ~/.ssh/id_rsa-client key. Your default key is going to just work as it did before. Neat trick, isn’t it?

Change the upstream URL of already existing repository

You may be asking, what should you do with already existing repositories. Cloning all of them one by one doesn’t sound like fun. Not it’s not and there is a solution! To change a URL of currently existing repository use git remote set-url command. For example:

git remote set-url origin git@bitbucket-client.org:client/project.git

This solution solved my problem and served me well. I hope it’s going to help you out as well. Stay curious and keep on coding 👩‍💻👨‍💻

Comments

  • B
    Bruce Lee

    man, you saved my day)

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      I am glad it helped you out 👌

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • T
    Thushara

    This is great.

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      I am glad it helped you out.

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • J
    Jason

    Honestly... I spent a whole day trying to figure this out. I'm using Bitbucket and I followed their documentation from top to bottom, word by word, and it still didn't work. But this worked flawlessly. Bitbucket should update their documentation.

    Thank you so much!

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      Comments like this make me publish more articles. Thanks for feedback and I am super glad it helped you out 🤗

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • A
    Andrew Michienzi

    Thank you so much this helped me out a ton!

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
  • Y
    YoungSoul

    Thank you very much for this post. I have been searching for how to do this and your blog was direct, clear and correct! You rock! Thanks for sharing

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      I am glad it helped you out!

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • M
    Matt Burns

    Urgh, I mean, it fixes my problem which is good, but, urgh. Thanks for sharing!

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
  • D
    Dimas Crocco

    Thank you for sharing this... it works like a charm!

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      I am glad you found it helpful 🤓

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • B
    Bruce Lee

    SSH doesn't seem to wish to work with ~/.ssh/config on win10 unix subsystem, unfortunately:

    fatal: unable to access 'https://gituser@bitbucket-private.org/gituser/dev.git/': Could not resolve host: bitbucket-private.org

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      I am so sorry, I am a macOS user and it is hard for me to understand why it is not working on your environment.

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • G
    Greg

    I don't know what's going on, but it doesn't work for me (Ubuntu)

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      Sorry, I am a macOS user and for me this solution still works like a charm. Sorry for being helpless Greg.

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • S
    SRJ

    after git remote set-url when i'm trying to pull /c/Users/suraj/.ssh/config: line 9: Bad configuration option: usekeychain /c/Users/suraj/.ssh/config: terminating, 1 bad configuration options fatal: Could not read from remote repository.

    Please make sure you have the correct access rights and the repository exists.

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      Sorry. I have never had this issues before. It is going to be hard to help me on this one :(

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!
  • C
    Chuck Norris

    Maybe mention $ cd into Users//.shh before creating keys

    👆 you can use Markdown here

    Your comment is awaiting moderation. Thanks!
    • Pawel Grzybek
      Pawel Grzybek

      This one is not a mandatory step, because this is the default location for new keys.

      👆 you can use Markdown here

      Your comment is awaiting moderation. Thanks!

Leave a comment

👆 you can use Markdown here

Your comment is awaiting moderation. Thanks!