Terraform create an Azure Linux Virtual Machine with SSH key

I am a software engineer. Documenting my DevOps journey
Search for a command to run...

I am a software engineer. Documenting my DevOps journey
No comments yet. Be the first to comment.
Introduction SSH is method of securely connect to remote server and execute command on that server. To provide user access to remote server either password or SSH key needs to be shared. But this becomes cumbersome when there are many users as well a...

Introduction In this article, we ran a Python application in AWS Lambda using Docker. Now we want to add some licencing mechanism by keeping the access key or any secret key to another service or application to restrict the use of this application. H...

Introduction I have been using Ubuntu for a long time on Intel Core i5 system. The daily routine was to pull the code from the Git repositories, build docker images, push it to Dockerhub and run docker containers with those images in the production U...

Introduction In the last article, we discovered how to monitor a NodeJs application with Prometheus and Grafana. In that, we learned to collect metrics from the application like the rate of requests in the last 5 minutes, the rate of 5xx responses, b...

Introduction Application monitoring is essential in the production environment. Once the application is deployed, the traffic to the application starts increasing, after some time the application starts responding slowly or sometimes it gets failed. ...

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.
Azure subscription
Terraform installed
Azure CLI installed
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"
}
}
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
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.