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.

Azure-virtual-machine-resource-group

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.

Azure-virtual-machine-details

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”.

Azure-virtual-machine-size

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!

Azure-virtual-machine-ssh

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.

Azure-virtual-machine-inbound

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
Azure-virtual-machine-advanced

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!

Azure-nginx-webserver

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.

Deploy your first environment