Multiple SSH Keys for the same host with PuTTY & Pageant

I’ve been using SSH to access my various source code repositories for quite some time now.  I’ve always used PuTTY and the related tools of Plink and Pageant in order to connect to my various online providers (mainly BitBucket and Github).  Until now, I’ve only ever needed one SSH Key per provider (or “host”) however, I recently started a new job whereby I needed to connect to two different BitBucket accounts, using two different SSH Keys.

As the two SSH Keys are connecting to the same host, it’s not possible to simply load both of the keys into Pageant and go from there as only the first key loaded will be sent to a given host.  If the account you’re trying to connect to uses the other SSH Key, Pageant will send the first (incorrect) key and your connection will fail.

The way to ensure the correct key is sent is by creating multiple “sessions” within PuTTY itself.

Here’s the steps to create a “session” within PuTTY (which Plink and Pageant will honor it you’re using the correct “host” alias – see later):

  1. putty1Start PuTTY
  2. Type in the relevant “real” host name in the Host Name field (i.e. or
  3. Navigate to the Connection > SSH > Auth node in the treeview.
  4. Specify the correct private key file in the “Private Key File for Authentication” section (this is the same key that you’d load into Pageant).
  5. Navigate back to the “Session” node in the treeview.
  6. Type a “host alias” name in the “Saved Sessions” box and click Save.

You can repeat the above steps for as many different keys you wish to add.  You can have multiple “sessions” using the same Host Name, just give each of them a different “Saved Session” name.

Once PuTTY is configured in this way, you will continue to load Pageant and load in each of the keys that you’ll want “cached”, just as you did before.

The key to making this now work is in the Remote URL that you’ll use for your repositories.

Whereas the “standard” SSH URL would look like this:


you simply replace the actual host (in the above example, it’s with the Saved Session name (aka “host alias”) that you entered in PuTTY (in the example from the animated gif on the right, I used “bitbucket-craig”).  So you remote host URL for your source repository becomes:


Of course, this works for both Mercurial and Git repositories on any actual remote host.  So long as you use the host alias, Pageant and the PLink program that acts as a “bridge”  between Pageant and PuTTY will use the host alias in the URL to both look up the actual host to connect to and to identify the correct private key file to send for the given alias.  This is the PuTTY/Pageant equivalent of OpenSSH’s IdentityFile, which performs the same function.

MVC Razor Views and automated Azure deployments

The other day, I decided that I’d publish a work-in-progress website to an Azure Website.  This was a free Website as part of the free package that Azure subscribers can use.  The website was a plain old vanilla ASP.NET MVC site.  Nothing fancy, just some models, some controllers , some infrastructure code and of course, some views.

I was deploying this to Azure via a direct connection to a private BitBucket Git repository I had within my BitBucket account.  This way, a simple “git commit” and “git push” would have, in a matter of seconds, my latest changes available for me to see in a real “on-the-internet” hosted site, thus giving me a better idea of how my site would look and feel than simply running the site on localhost.

An issue I almost instantly came up against was that, whenever I’d make a tiny change to just a view file – i.e. no code changes, just tweaks to HTML markup in the .cshtml Razor view file, and commit and push that change – the automated deployment process would kick in and the site would be successfully deployed to Azure, however, the newly changed Razor View would remain unchanged.

What on earth was going on?   I could run the site locally and see the layout change just fine, however, the version deployed to Azure was the older version, prior to the change.   I first decided that I now had to manually FTP the changed .cshtml files from my local machine to the relevant place in the Azure website, which did work, but was an inelegant solution.  I needed to find out why the changed Razor views were not being reflected in the Azure deployments.

image After some research, I found the answer.

Turns out that some of my view files (the .cshtml files themselves) had the “Build Action” property set to “None”.  In order for your view to be correctly deployed when using automated Azure deployments, the Build Action property must be set to “Content”.

Now, quite how the Build Action property had come to be set that way, I have no idea.  Some of the first views I’d added to the project had the Build Action set correctly, however, some of the newer views I’d added were set incorrectly.  I had not explicitly changed any of these properties on any files, so how some were originally set to Content and others set to None was a mystery.  And then I had an idea…..

I had been creating Views in a couple of different ways.  Turns out that when I was creating the View files using the Visual Studio context menu options, the files were being created with the correct default Build Action of Content.  However, when I was creating the View files using ReSharper’s QuickFix commands by hitting Alt + Enter on the line return View(); which shows the ReSharper menu allowing you to create a new Razor view with or without layout, it would create the View file with a default Build Action of None.

Bizarrely, attempting to recreate this issue in a brand new ASP.NET MVC project did not reproduce the issue (i.e. the ReSharper QuickFix command correctly created a View with a default Build Action of Content!)

I can only assume that this is some strange intermittent issue with ReSharper, although it’s quite probably caused by a specific difference between the projects that I’ve tested this on, thus far I have no idea what that difference may be…   I’ll keep looking and if I find the culprit, I’ll post an update here.

Until then, I’ll remain vigilant and always remember to double-check the Build Action property and ensure it’s set to Content for all newly created Razor Views.