Azure Cloud Automation Quickstart – Virtual Machine and cloud-init
So far in Part 1 and Part 2 of this series we have shown how to use the Azure Portal to create a Virtual Network and a Network Security group that opens up ports 80 (HTTP) and 22 (SSH). After all of the ingredients were assembled we associated that Network Security Group with our Virtual Networks subnet.
We then took all of those manual steps and in under 40 lines of “code” created a Tuono Blueprint that will repeatedly and reliably create that infrastructure for you.
In this part, we are going to deploy an Ubuntu virtual machine that will be attached to our network and leverage cloud-init to configure NGINX and display a custom message that is accessible on the public interface via port 80.
How do I deploy a Virtual Machine in the Azure Portal?
Navigate to the Virtual Machines page in the Azure Portal with the side blade or using the search bar.

From the Virtual machines page in the portal click “Add → Virtual machine”.

There are a lot of options to pick from in the Azure Create a virtual machine page so lets break the ‘Basics’ section into pieces.
Select the Resource Group we created earlier as a location to deploy this VM, this also automatically sets our region and Virtual Network to use.

Now we are going to provide our virtual machine with a name and use the default image which is an Ubuntu Server 18.04 LTS VM.

The standard default size is a Basic_A2 size VM with a cost of $49.64 a month. Our webserver does not need that much power right now so let’s change it to a lower spec’d and lower cost VM size!
Click the dropdown for the VM size and click “See all sizes”.

Sort by Cost/Month and let’s select a B1s VM size for this walk-through. you can see the cost per month is $7.59, this could be a costly mistake if you forget to change your VM size when deploying infrastructure manually! Once you have highlighted VM size click “Select”.

Now we will configure our authentication type to use an existing public key that will allow us to SSH into the VM. Select the dropdown for the SSH Public Key Source and select “Use existing public key”. You can paste your SSH public key into the SSH public key box. If you don’t know why you should be using SSH keys or know how to create one we have a blog article to help you with that!

We will leave the Inbound port rules selection with default values as we will be using our subnet Network Security Group to control our port access.

How do I configure NGINX at boot time with cloud-init in the Azure Portal?
Select the “Advanced” tab and copy in the following cloud-init script which will setup NGINX and configure index.html with a custom welcome message.
Now you can “Review + create” and review what we have done and finally click “Create” to start the deploy!
#cloud-config package_upgrade: false packages: - nginx runcmd: - sudo su - echo 'Congratulations on configuring an Azure web server! ' > /var/www/html/index.nginx-debian.html

Your Resource group now has the following objects and a running NGINX web server. Click the “Virtual Machine” so we can get to the details.

Now copy the public IP of the webserver from the VM portal page side blade under the “Overview” section.

When browsing to the IP you will see NGINX serving up our customized message!

Tuono delivers consistent, secure deployable infrastructure every time
Let’s build on our network infrastructure Blueprint we created in the previous parts. We are now going to add the pieces to define an image and deploy our VM along with configuring NGINX with cloud-init using Tuono.
Compute
Below you can see that we are selecting the same Canonical Ubuntu 18.04 image as our manual deploy.
compute: image: bionic: publisher: Canonical product: UbuntuServer sku: 18.04-LTS venue: aws: image_id: ami-04bb0cc469b2b81cc
VM
We define the VM size and image and assign it a network interface bound to our previously created firewall and subnet.
vm: webserver: cores: 1 memory: 1 GB image: bionic nics: external: ips: - private: type: dynamic public: type: static firewall: fw-external-access subnet: subnet-walkthrough
User Data
Setting up the SSH key and NGINX is accomplished with a configure stanza where we pass in our details and use cloud-init after first boot to customize NGINX.
configure: admin: username: adminuser public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDu= dummy_key@tuono.wpengine.com userdata: type: cloud-init content: | #cloud-config package_upgrade: false packages: - nginx users: - name: adminuser groups: - sudo sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDu= dummy_key@tuono.wpengine.com runcmd: - sudo su - echo 'Congratulations on configuring an Azure web server! ' > /var/www/html/index.nginx-debian.html
Your Resource group now has the following objects and a running NGINX web server.

You may notice that there is an extra Network Security Group when deploying a VM with Tuono. We believe in control of network security and default to the rule of least privilege at every level we can. Creating this VM with Tuono placed it under a Virtual Network with a distinct Network Security Group and a network interface with it’s own dedicated network security group allowing for granular access and port control at the network and VM level.
Complete Blueprint
Our complete Blueprint that deploys and configures an Azure NGINX web server is outlined below. It accomplishes this in 80 lines of “code” (if we remove the comments).
Although this is an Azure walkthrough, I have to mention now that what we have been learning to build will also deploy functionally equivalent infrastructure to AWS! Learn, write and deploy portable cloud IaC with Tuono.
# # This is an example blueprint that demonstrates the creation of an Azure webservice # --- location: region: my-region: country: USA area: northwest folder: azure-walkthrough: region: my-region networking: network: vnet-walkthrough: range: 10.0.0.0/16 public: true subnet: subnet-walkthrough: range: 10.0.0.0/24 network: vnet-walkthrough firewall: fw-external-access # Part 2 adds a Firewall to the subnet and marks it public public: true # Part 2 Protocols protocol: ssh: ports: - port: 22 proto: tcp http: ports: - port: 80 proto: tcp # Part 2 adds a Firewall using a protocol firewall: fw-external-access: rules: - protocols: ssh to: self - protocols: http to: self # Part 3 adds VM and configures NGINX with cloud-init compute: image: bionic: publisher: Canonical product: UbuntuServer sku: 18.04-LTS venue: aws: # if provisioning fails due to image not found, go to: # https://cloud-images.ubuntu.com/locator/ec2/ # and search for "bionic amd64 ebs" and also add your AWS zone name like "us-west-2" image_id: ami-04bb0cc469b2b81cc vm: webserver: cores: 1 memory: 1 GB image: bionic nics: external: ips: - private: type: dynamic public: type: static firewall: fw-external-access subnet: subnet-walkthrough configure: admin: username: adminuser public_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDu= dummy_key@tuono.wpengine.com userdata: type: cloud-init content: | #cloud-config package_upgrade: false packages: - nginx users: - name: adminuser groups: - sudo sudo: ALL=(ALL) NOPASSWD:ALL ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDummyDu= dummy_key@tuono.wpengine.com runcmd: - sudo su - echo 'Congratulations on configuring an Azure web server!' > /var/www/html/index.nginx-debian.html
Don’t miss out on the previous parts in the series – Part 1 details how to create a resource group, virtual network, and subnet while Part 2 is a step-by-step guide to creating a network security group. The bonus in the series will put you in control, teaching you how to create variables to modify your preferences when it comes time to Apply.
And for another great resource, check out our guide on “How to deploy an Application Gateway in Azure“.
You can try this out for yourself by signing up for our free Community Edition too! Experience how Tuono’s complete automation platform enables you to quickly and confidently build repeatable infrastructure in Azure.