Preface

I've always had my personal repositories hosted through Bitbucket Cloud due to them having unlimited private repositories (limited by size). Which has been great I can have my SSH key all setup and clone/push/pull without needing to supply my password. Which was fine with the company I was working for at the time had Bitbucket on premise. However this all changed when the workplace brought in Bitbucket Cloud, this meant I had to keep switching between both my "personal" and my "work" keys as you can only have a single SSH key associated to a single Bitbucket account which was frustrating and time sink to say the least.

Generating multiple SSH keys

If we can’t use the same SSH key across multiple accounts (which 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.

The following CLI snippets assume that you don't have a default SSH RSA key already, but I'm assuming if you're here most of you already will so you can safely skip the first step.

ssh-keygen -t rsa -b 4096 -C "andrew.townsend@localhost" -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.
Generate a default SSH RSA Key
ssh-keygen -t rsa -b 4096 -C "andrew.townsend@privateemail.com" -f id_rsa_personal
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_personal.
Your public key has been saved in ~/.ssh/id_rsa_personal.pub.
Generate a personal SSH RSA Key
ssh-keygen -t rsa -b 4096 -C "andrew.townsend@workemail.com" -f id_rsa_work
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_work.
Your public key has been saved in ~/.ssh/id_rsa_work.pub.
Generate a workplace SSH RSA Key

Configure SSH config to use multiple keys

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 name or IP address or IP range. This config file lives in the .ssh folder within your home directory so for example /user/atownsend/.ssh for myself on Linux MINT or /Users/atownsend/.ssh on MacOS, substitute atownsend for your username or use ~ to point to home like in the example below.

touch ~/.ssh/config
Create SSH config file if not already existing
Host bitbucket-work.org
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/id_rsa_work
  IdentitiesOnly yes

Host bitbucket-personal.org
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/id_rsa_personal
  IdentitiesOnly yes

Host *
  IdentityFile ~/.ssh/id_rsa
  
 
Contents of SSH config file

This will then mean we can use the aliases when cloning repositories from Bitbucket so for example:

git clone git@bitbucket-work.org:workplace/a-work-project.git
# or 
git clone git@bitbucket-personal.org:personal/a-personal-project.git
Examples of cloning a workplace repository and personal repository

By doing so, you are skipping a default public key resolution, and explicitly pointing your ssh-agent to always resolve connection to bitbucket-work.org and bitbucket-personal.org; using ~/.ssh/id_rsa_work and  ~/.ssh/id_rsa_personal key respectfully. The default key is going to just work as it did previously.

Updating already cloned repositories by altering the upstream URL

git remote set-url origin git@bitbucket-work.org:workplace/a-work-project.git
# or 
git remote set-url origin git@bitbucket-personal.org:personal/a-personal-project.git
Example of updating the upstream URL of existing repositories

In Conclusion

As you can see you can easily expand upon this to have multiple SSH keys working with multiple Bitbucket accounts easily, this can be expanded further to include various different hosts or be used for specific IP addresses or ranges of addresses but I'll cover that in another article later on.