I have successfully created a VM as part of a Resource Group on Azure using Terraform. Next step is to ssh in the new machine and run a few commands. For that, I have created a provisioner as part of the VM resource and set up an SSH connection:
resource "azurerm_virtual_machine" "helloterraformvm" { name = "terraformvm" location = "West US" resource_group_name = "${azurerm_resource_group.helloterraform.name}" network_interface_ids = ["${azurerm_network_interface.helloterraformnic.id}"] vm_size = "Standard_A0" storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "14.04.2-LTS" version = "latest" } os_profile { computer_name = "hostname" user = "some_user" password = "some_password" } os_profile_linux_config { disable_password_authentication = false } provisioner "remote-exec" { inline = [ "sudo apt-get install docker.io -y" ] connection { type = "ssh" user = "some_user" password = "some_password" } } }
If I run “terraform apply”, it seems to get into an infinite loop trying to ssh unsuccessfully, repeating this log over and over:
azurerm_virtual_machine.helloterraformvm (remote-exec): Connecting to remote host via SSH... azurerm_virtual_machine.helloterraformvm (remote-exec): Host: azurerm_virtual_machine.helloterraformvm (remote-exec): User: testadmin azurerm_virtual_machine.helloterraformvm (remote-exec): Password: true azurerm_virtual_machine.helloterraformvm (remote-exec): Private key: false azurerm_virtual_machine.helloterraformvm (remote-exec): SSH Agent: true
I’m sure I’m doing something wrong, but I don’t know what it is 🙁
EDIT:
I have tried setting up this machine without the provisioner, and I can SSH to it no problems with the given username/passwd. However I need to look up the host name in the Azure portal because I don’t know how to retrieve it from Terraform. It’s suspicious that the “Host:” line in the log is empty, so I wonder if it has anything to do with that?
UPDATE:
I’ve tried with different things like indicating the host name in the connection with
host = "${azurerm_public_ip.helloterraformip.id}"
and
host = "${azurerm_public_ip.helloterraformips.ip_address}"
as indicated in the docs, but with no success.
I’ve also tried using ssh-keys instead of password, but same result – infinite loop of connection tries, with no clear error message as of why it’s not connecting.
Advertisement
Answer
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 theprovisioner
element.
Here’s the full working Terraform file, replacing the data like SSH keys, etc.:
# Configure Azure provider provider "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 exist resource "azurerm_resource_group" "rg" { name = "sometestrg" location = "ukwest" } # create virtual network resource "azurerm_virtual_network" "vnet" { name = "tfvnet" address_space = ["10.0.0.0/16"] location = "ukwest" resource_group_name = "${azurerm_resource_group.rg.name}" } # create subnet resource "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 IPs resource "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 interface resource "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 account resource "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 container resource "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 machine resource "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" } }