SSH connection to Azure VM with Terraform SSH connection to Azure VM with Terraform azure azure

SSH connection to Azure VM with Terraform


I have managed to make this work. I changed several things:

  • Gave name of host to connection.
  • Configured SSH keys properly - they need to be unencrypted.
  • Took the connection element out of the provisioner element.

Here's the full working Terraform file, replacing the data like SSH keys, etc.:

# Configure Azure providerprovider "azurerm" {  subscription_id = "${var.azure_subscription_id}"  client_id       = "${var.azure_client_id}"  client_secret   = "${var.azure_client_secret}"  tenant_id       = "${var.azure_tenant_id}"}# create a resource group if it doesn't existresource "azurerm_resource_group" "rg" {    name = "sometestrg"    location = "ukwest"}# create virtual networkresource "azurerm_virtual_network" "vnet" {    name = "tfvnet"    address_space = ["10.0.0.0/16"]    location = "ukwest"    resource_group_name = "${azurerm_resource_group.rg.name}"}# create subnetresource "azurerm_subnet" "subnet" {    name = "tfsub"    resource_group_name = "${azurerm_resource_group.rg.name}"    virtual_network_name = "${azurerm_virtual_network.vnet.name}"    address_prefix = "10.0.2.0/24"    #network_security_group_id = "${azurerm_network_security_group.nsg.id}"}# create public IPsresource "azurerm_public_ip" "ip" {    name = "tfip"    location = "ukwest"    resource_group_name = "${azurerm_resource_group.rg.name}"    public_ip_address_allocation = "dynamic"    domain_name_label = "sometestdn"    tags {        environment = "staging"    }}# create network interfaceresource "azurerm_network_interface" "ni" {    name = "tfni"    location = "ukwest"    resource_group_name = "${azurerm_resource_group.rg.name}"    ip_configuration {        name = "ipconfiguration"        subnet_id = "${azurerm_subnet.subnet.id}"        private_ip_address_allocation = "static"        private_ip_address = "10.0.2.5"        public_ip_address_id = "${azurerm_public_ip.ip.id}"    }}# create storage accountresource "azurerm_storage_account" "storage" {    name = "someteststorage"    resource_group_name = "${azurerm_resource_group.rg.name}"    location = "ukwest"    account_type = "Standard_LRS"    tags {        environment = "staging"    }}# create storage containerresource "azurerm_storage_container" "storagecont" {    name = "vhd"    resource_group_name = "${azurerm_resource_group.rg.name}"    storage_account_name = "${azurerm_storage_account.storage.name}"    container_access_type = "private"    depends_on = ["azurerm_storage_account.storage"]}# create virtual machineresource "azurerm_virtual_machine" "vm" {    name = "sometestvm"    location = "ukwest"    resource_group_name = "${azurerm_resource_group.rg.name}"    network_interface_ids = ["${azurerm_network_interface.ni.id}"]    vm_size = "Standard_A0"    storage_image_reference {        publisher = "Canonical"        offer = "UbuntuServer"        sku = "16.04-LTS"        version = "latest"    }    storage_os_disk {        name = "myosdisk"        vhd_uri = "${azurerm_storage_account.storage.primary_blob_endpoint}${azurerm_storage_container.storagecont.name}/myosdisk.vhd"        caching = "ReadWrite"        create_option = "FromImage"    }    os_profile {        computer_name = "testhost"        admin_username = "testuser"        admin_password = "Password123"    }    os_profile_linux_config {      disable_password_authentication = false      ssh_keys = [{        path     = "/home/testuser/.ssh/authorized_keys"        key_data = "ssh-rsa xxx email@something.com"      }]    }    connection {        host = "sometestdn.ukwest.cloudapp.azure.com"        user = "testuser"        type = "ssh"        private_key = "${file("~/.ssh/id_rsa_unencrypted")}"        timeout = "1m"        agent = true    }    provisioner "remote-exec" {        inline = [          "sudo apt-get update",          "sudo apt-get install docker.io -y",          "git clone https://github.com/somepublicrepo.git",          "cd Docker-sample",          "sudo docker build -t mywebapp .",          "sudo docker run -d -p 5000:5000 mywebapp"        ]    }    tags {        environment = "staging"    }}


According to your description, Azure Custom Script Extension is an option for you.

The Custom Script Extension downloads and executes scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration / management task.

Remove provisioner "remote-exec" instead of below:

resource "azurerm_virtual_machine_extension" "helloterraformvm" {  name                 = "hostname"  location             = "West US"  resource_group_name  = "${azurerm_resource_group.helloterraformvm.name}"  virtual_machine_name = "${azurerm_virtual_machine.helloterraformvm.name}"  publisher            = "Microsoft.OSTCExtensions"  type                 = "CustomScriptForLinux"  type_handler_version = "1.2"  settings = <<SETTINGS    {        "commandToExecute": "apt-get install docker.io -y"    }SETTINGS}

Note: Command is executed by root user, don't use sudo.

More information please refer to this link: azurerm_virtual_machine_extension.

For a list of possible extensions, you can use the Azure CLI command az vm extension image list -o table

Update: The above example only supports single command. If you need to multiple commands. Like install docker on your VM, you need

apt-get update apt-get install docker.io -y  

Save it as a file named script.sh and save it to Azure Storage account or GitHub(The file should be public). Modify terraform file like below:

 settings = <<SETTINGS    {        "fileUris": ["https://gist.githubusercontent.com/Walter-Shui/dedb53f71da126a179544c91d267cdce/raw/bb3e4d90e3291530570eca6f4ff7981fdcab695c/script.sh"],        "commandToExecute": "sh script.sh"    }SETTINGS