Introduction
Previously I have written one article on how to create an Azure Linux Virtual Machine with Terraform. In that article, I have explained how to create a Virtual Machine with a password using Terraform. Now in this article, I will explain how to create a VM with an SSH Key using Terraform.
Prerequisite
Azure subscription
Terraform installed
Azure CLI installed
Terraform Configuration Files
We will use configuration files from the previous article only and will start making changes to them. I have created git repo of that for your reference.
We will add the following configuration in main.tf configuration file. It's creating SSH private key and saving in the local system.
# Create an SSH key
resource "tls_private_key" "linux_key" {
algorithm = "RSA"
rsa_bits = 4096
}
# Save the private key to our local machine
# Use this key to connect to our Linux VM
resource "local_file" "linuxkey" {
filename="linuxkey.pem"
content=tls_private_key.linux_key.private_key_pem
}
Now scroll down to the same main.tf configuration file and locate azurerm_linux_virtual_machine section and remove the following lines from it as it suggests we are disabling password authentication.
disable_password_authentication = false
admin_username = "${var.username}"
Add the following configuration in the same section as above. It specifies the username and public key to connect the VM.
admin_ssh_key {
username = "${var.username}"
public_key = tls_private_key.linux_key.public_key_openssh
}
That's it we have done all changes required. Our section will look like below
resource "azurerm_linux_virtual_machine" "main" {
name = "${var.prefix}-vm"
computer_name = "linuxtestcomputername"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = "Standard_D2s_v4"
admin_username = "${var.username}"
network_interface_ids = [
azurerm_network_interface.main.id,
]
admin_ssh_key {
username = "${var.username}"
public_key = tls_private_key.linux_key.public_key_openssh
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18_04-lts-gen2"
version = "latest"
}
os_disk {
storage_account_type = "Premium_LRS"
caching = "ReadWrite"
}
}
Final main.tf configuration will be as follows
provider "azurerm" {
features {}
}
# Create an SSH key
resource "tls_private_key" "linux_key" {
algorithm = "RSA"
rsa_bits = 4096
}
# Save the private key to our local machine
# Use this key to connect to our Linux VM
resource "local_file" "linuxkey" {
filename="linuxkey.pem"
content=tls_private_key.linux_key.private_key_pem
}
resource "azurerm_resource_group" "main" {
name = "${var.prefix}-rg"
location = var.location
}
# Create virtual network
resource "azurerm_virtual_network" "main" {
name = "${var.prefix}-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
}
# Create subnet
resource "azurerm_subnet" "internal" {
name = "${var.prefix}-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.1.0/24"]
}
# Create public IP
resource "azurerm_public_ip" "main" {
name = "${var.prefix}-public-ip"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
allocation_method = "Static"
}
# Create Network Security Group and rule
resource "azurerm_network_security_group" "main" {
name = "${var.prefix}-network-security-group"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "SSH"
priority = 300
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "HTTP"
priority = 310
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
# Create network interface
resource "azurerm_network_interface" "main" {
name = "${var.prefix}-nic"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
ip_configuration {
name = "${var.prefix}-nic-config"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.main.id
}
}
# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "main" {
network_interface_id = azurerm_network_interface.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
resource "azurerm_linux_virtual_machine" "main" {
name = "${var.prefix}-vm"
computer_name = "linuxtestcomputername"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
size = "Standard_D2s_v4"
admin_username = "${var.username}"
network_interface_ids = [
azurerm_network_interface.main.id,
]
admin_ssh_key {
username = "${var.username}"
public_key = tls_private_key.linux_key.public_key_openssh
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18_04-lts-gen2"
version = "latest"
}
os_disk {
storage_account_type = "Premium_LRS"
caching = "ReadWrite"
}
}
Apply configuration
As we have learned how to apply configuration in the previous article. We will do it once again with the following commands
terraform init
terraform apply
After the successful implementation of applying the configuration, you will see a message in the console saying that 1 resource added to the infrastructure. You will see one linuxkey.pem file also created in the local directory. You can use this file to connect to VM using the following command for connection. Replace xx.xx.xx.xx with the public IP address of the newly created VM.
ssh -i linuxkey.pem adminlinux@xx.xx.xx.xx
Conclusion
Terraform makes it easy for administrators to provision cloud resources in Azure. Using Terraform’s command files, you can automate provisioning to reduce the overhead of manually creating resources in the Azure portal.