Running Cloud Shell from your Virtual Network

Azure Cloud Shell is a super useful tool that can be used to manage Azure resources directly from your browser (or Windows Terminal) via a CLI. It comes with a lot of useful tools like Terraform, Kubectl, Ansible and many more. Basically everything you need for a day up in the cloud. A life-saver if you’re on a locked down workstation!

One thing that has been a limitation of Cloud Shell is that you cannot use it to access resources that are behind a firewall. Like a VM, or a AKS cluster with an IP-address blocklist for the master nodes. Well, that is until now. Cloud Shell just got support for running directly in your Virtual Network, and in this post we’re gonna look at how!

Solution overview

High-level design of private Cloud Shell

Source: Microsoft

Historically, Azure Cloud Shell has been running somewhere and somehow in Microsoft’s datacenter, and the only part you get to know about is the storage account that you can store your home folder in.

In order to make Azure Cloud Shell reach your private network resources, and allow you to reach Azure Cloud Shell, two important Azure services are used:

  • Azure Container Instances lets you run the Cloud Shell container without the overhead of setting up and managing servers, Kubernetes clusters, or similiar container hosts.
  • Azure Relay allows you to connect securely to your container without having to open firewall ports and expose it directly to the internet.

Now when we know the important ingredients that make up the solution, lets get started!

Setting up Cloud Shell

To make this a bit more confusing, we will use Azure Cloud Shell to set-up Azure Cloud Shell. If you already have Cloud Shell configured, you can skip this part. Otherwise, carry on!

Log in to the Azure Portal and open up Cloud Shell by clicking the prompt icon in the menu bar:

Cloud Shell in the Menu Bar

If you haven’t used Cloud Shell before it will ask you to set create storage for it. Just click the “Create storage” button, we’ll get more into this part later on.

Cloud Shell storage configuration screen

A screenshot of Cloud Shell Bash prompt

After a few seconds, Cloud Shell should be up and running!

Deploying the solution

Resource group and virtual network

First, we create a resource group that contains all the resources that we need. Since private Cloud Shell is a preview feature, it is currently only available in West US and West Central US. So I’ll create my resource group in West US.

Then, we need to create a virtual network which will contain all our isolated workloads. I’m using a address prefix for the Virtual Network, but you can use anything you see fit.

Now you can go ahead and deploy the rest of the network resources using the ARM Template Microsoft has nicely prepared for us. But that’s not why we’re here, so lets continue!

Service subnets

If you recall from earlier in this blog post, one of the important services for making the private Cloud Shell work is Azure Container Instances. In order to reach your private resources, this needs to be deployed to a subnet in your virtual network. So lets make some subnets!

What are all these subnets good for?

  • Subnet sn-containers-dev is used for Azure Container Instances, and will be the source for Azure Cloud Shell container networking.
  • Subnet sn-relay-dev will be the home for Azure Relays private endpoint.

Network profile

Azure CLI does not support only creating a network profile with the az container command module, it also wants you to start a container. To workaround this, we use a more unorthodox method.

We also need to delegate access to the network profile to Azure Container Instances, so it can be used by the service.

Now the network profile should now be ready for use!

Azure Relay namespace

It is time to set up Azure Relay! We begin by creating the namespace resource.

Then, we create the private endpoint that Azure Relay will use to communicate with the Cloud Shell container. We connect it to the subnet we created earlier.

In order for us to reach Azure Relay, we need to open up its firewall. To keep it simple, we open up for all IP-addresses. But in reality, you would want to only open it for your own IP-address to prevent unwanted visitors.

This is only supported in the Azure Portal and Azure Management API, so here we have to get our hands real dirty.

When this is done, we can finish the setup by delegating Azure Container Instances access to the Azure Relay namespace as well.

And that’s it! The Azure Relay namespace should now be ready to use.

Storage account

Our goal here is to create a storage account and a file share, and only allow it to be accessed from our Cloud Shell container. The last part is important in order for the storage account to show up later on.

Now we have a storage account.

Setting up Cloud Shell (again)

Phew! That was quite a lot of preparation to do (you did it manually, right?). But now we’re done with our resources, and you should have something like this in your resource group.

A screenshot of Azure Resources

Now we can finally put the final piece into place, the Cloud Shell itself! To reconfigure Cloud Shell, we need to unmount our current storage.

You’ll get a few prompts that your connection will be terminated, and that you have to reconfigure Cloud Shell. Don’t worry, you won’t lose any data (as long as you don’t delete your old storage account) and you can always transfer it to your new storage account later.

Reconnect to Cloud Shell, and you should see the setup guide once again. This time, we click the “Show advanced settings” button.

Check the “Hide VNET isolation settings checkbox” to settings related to setting up private Cloud Shell. Pick the region you used previously (West US or West Central US) and the resource group you created for your resources. Everything should now be filled in automatically, except for the file share name. Use the name of the file share you created earlier. You should now have something like this.

Screenshot showing private Cloud Shell settings

If something doesn’t show up, it is because it has been misconfigured. Review what you did earlier and then come back again.

Now, go ahead and click “Create storage”. Cloud Shell will now be created in your Virtual Network! This could take a little longer than you’re used to. It took me a couple of minutes for the container to start the first time, and I had to start it twice (first time my token expired before it was finished).

Screenshot showing the private Cloud Shell prompt

After a bit of waiting it’s up and running! Just to confirm, our Cloud Shell instance also has a private IP-address from our subnet.

Screenshot of the Cloud Shell IP-configuration

Wrapping up

Congratulations! You have now created a private Cloud Shell instance. You can now use this to connect to your isolated resources, such as your VMs.

Don’t forget to clean up when you’re done. Azure Container Instances and Azure Relay are not free services, so you might end up unexpected costs if you don’t. You can do so by running the following command.


Cloud Shell in an Azure Virtual Network by Microsoft