Skip to content

Instantly share code, notes, and snippets.

@devops-school
Last active October 13, 2026 11:38
Show Gist options
  • Select an option

  • Save devops-school/ae2b9754eabeacd276a31fafcdf8bed2 to your computer and use it in GitHub Desktop.

Select an option

Save devops-school/ae2b9754eabeacd276a31fafcdf8bed2 to your computer and use it in GitHub Desktop.
azure terraform Meta Arguments
```hcl
terraform {
required_version = ">= 1.5.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = var.subscription_id
}
# --------------------------------------------------
# VARIABLES
# --------------------------------------------------
variable "subscription_id" {
description = "Azure subscription ID"
type = string
}
variable "location" {
description = "Azure region"
type = string
default = "East US"
}
variable "resource_group_name" {
type = string
default = "rg-terraform-ubuntu"
}
variable "vm_name" {
type = string
default = "vm-ubuntu2604-01"
}
variable "vm_size" {
type = string
default = "Standard_D2ds_v6"
}
variable "admin_username" {
type = string
default = "azureuser"
}
variable "admin_password" {
description = "Training password; keep secret"
type = string
sensitive = true
}
variable "allowed_ssh_cidr" {
description = "Trusted client public IP in CIDR notation"
type = string
}
variable "create_instance" {
description = "Whether to create the Ubuntu VM"
type = bool
default = true
}
# --------------------------------------------------
# RESOURCE GROUP
# --------------------------------------------------
resource "azurerm_resource_group" "lab" {
name = var.resource_group_name
location = var.location
}
# --------------------------------------------------
# VIRTUAL NETWORK
# --------------------------------------------------
resource "azurerm_virtual_network" "main" {
name = "vnet-ubuntu-lab"
address_space = ["10.10.0.0/16"]
location = azurerm_resource_group.lab.location
resource_group_name = azurerm_resource_group.lab.name
}
# --------------------------------------------------
# SUBNET
# --------------------------------------------------
resource "azurerm_subnet" "main" {
name = "subnet-ubuntu"
resource_group_name = azurerm_resource_group.lab.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.10.1.0/24"]
}
# --------------------------------------------------
# count: CREATE TWO PUBLIC IP ADDRESSES
# --------------------------------------------------
resource "azurerm_public_ip" "ubuntu" {
count = 2
name = "pip-ubuntu-${count.index + 1}"
location = azurerm_resource_group.lab.location
resource_group_name = azurerm_resource_group.lab.name
allocation_method = "Static"
sku = "Standard"
}
# --------------------------------------------------
# NETWORK SECURITY GROUP
# --------------------------------------------------
resource "azurerm_network_security_group" "main" {
name = "nsg-ubuntu-lab"
location = azurerm_resource_group.lab.location
resource_group_name = azurerm_resource_group.lab.name
}
# --------------------------------------------------
# for_each: CREATE SSH AND RDP RULES
# --------------------------------------------------
resource "azurerm_network_security_rule" "access" {
for_each = {
ssh = {
priority = 100
port = "22"
}
rdp = {
priority = 110
port = "3389"
}
}
name = "allow-${each.key}"
priority = each.value.priority
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = each.value.port
source_address_prefix = var.allowed_ssh_cidr
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.lab.name
network_security_group_name = azurerm_network_security_group.main.name
}
# --------------------------------------------------
# ASSOCIATE NSG WITH SUBNET
# --------------------------------------------------
resource "azurerm_subnet_network_security_group_association" "main" {
subnet_id = azurerm_subnet.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
# --------------------------------------------------
# NETWORK INTERFACE
# --------------------------------------------------
resource "azurerm_network_interface" "ubuntu" {
name = "nic-ubuntu2604-01"
location = azurerm_resource_group.lab.location
resource_group_name = azurerm_resource_group.lab.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.main.id
private_ip_address_allocation = "Dynamic"
# Attach the first Public IP
public_ip_address_id = azurerm_public_ip.ubuntu[0].id
}
depends_on = [
azurerm_subnet_network_security_group_association.main
]
}
# --------------------------------------------------
# UBUNTU 26.04 LTS VIRTUAL MACHINE
# --------------------------------------------------
resource "azurerm_linux_virtual_machine" "ubuntu" {
count = var.create_instance ? 1 : 0
name = var.vm_name
location = azurerm_resource_group.lab.location
resource_group_name = azurerm_resource_group.lab.name
size = var.vm_size
admin_username = var.admin_username
admin_password = var.admin_password
disable_password_authentication = false
network_interface_ids = [
azurerm_network_interface.ubuntu.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "ubuntu-26_04-lts"
sku = "server"
version = "latest"
}
depends_on = [
azurerm_network_security_rule.access,
azurerm_subnet_network_security_group_association.main
]
}
# --------------------------------------------------
# OUTPUTS
# --------------------------------------------------
output "resource_group_name" {
value = azurerm_resource_group.lab.name
}
output "ubuntu_vm_name" {
value = try(azurerm_linux_virtual_machine.ubuntu[0].name, null)
}
output "ubuntu_private_ip" {
value = try(azurerm_network_interface.ubuntu.private_ip_address, null)
}
output "ubuntu_public_ip" {
value = azurerm_public_ip.ubuntu[0].ip_address
}
output "second_public_ip" {
value = azurerm_public_ip.ubuntu[1].ip_address
}
output "ssh_command" {
value = try(
"ssh ${var.admin_username}@${azurerm_public_ip.ubuntu[0].ip_address}",
null
)
}
```
Create a `terraform.tfvars` file alongside `main.tf`:
```hcl
subscription_id = "YOUR-AZURE-SUBSCRIPTION-ID"
location = "East US"
admin_username = "azureuser"
admin_password = "ReplaceWithYourStrongTrainingPassword!"
allowed_ssh_cidr = "YOUR_PUBLIC_IP/32"
create_instance = true
```
Replace the subscription ID, password, and SSH CIDR with your actual values.
Run:
```bash
az login
terraform init
terraform fmt
terraform validate
terraform plan
terraform apply
```
**Notes:**
- `count = 2` creates two Public IP resources, but only the first is attached to the VM.
- `for_each` creates the SSH and RDP rules. RDP is included for demonstration only; Ubuntu does not need it.
- `depends_on` enforces the specified resource ordering.
- If Azure reports that the Ubuntu image SKU is unavailable, verify the image with `az vm image list` for your selected region before applying.
- For production, prefer SSH key authentication over password authentication.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment