Note: Scroll down this article to download the terrafom files in zip format.


Azure Jump Host with Terraform

This Terraform project deploys a secure Ubuntu 24.04 LTS jump host (Bastion Host) into an existing Azure virtual network.

It is designed to provide a secure entry point to your private Azure environment. It creates the VM and its necessary components (like a Public IP and NSG) in a resource group.

Features

  • Creates VM Resource Group (or use existing): Creates a new resource group for the jump host. Includes a prevent_destroy lifecycle hook to prevent accidental deletion.
  • Deploys Ubuntu 24.04 VM: Deploys a Standard_B2ats_v2 Ubuntu 24.04 VM.
  • Secure by Default: Creates a Network Security Group (NSG) that only allows inbound SSH (port 22) from the admin_public_ip you specify.
  • Public IP: Provisions a static public IP address for the VM.
  • Adds Explicit Route: Adds a single route to your existing route table. This route forces traffic destined for your admin_public_ip to go directly to the Internet, ensuring your SSH connection isn't hijacked by a forced-tunneling (e.g., to a firewall).

Prerequisites

Before you begin, you must have the following:

  1. Terraform (v1.0.0+) installed.
  2. Azure CLI installed.
  3. An active Azure Subscription.
  4. An existing Virtual Network (VNet) and Subnet.
  5. An existing Route Table (UDR) associated with your Subnet.

Configuration

  1. Authenticate with Azure:

    az login
    
  2. Configure Variables: Edit terraform.auto.tfvars and fill in your environment's specific values.

terraform.auto.tfvars Example

# -----------------------------------------------------------------
# --- Fill in these values before running 'terraform apply' ---
# -----------------------------------------------------------------

# 1. Location
# The Azure region for your resources.
location = "uksouth"

# 2. Resource Groups
# The RG where your VNet, Subnet, and Route Table are.
network_resource_group_name = "rg-my-existing-network"

# The name of the RG for the new Jump Host.
# It will be CREATED if it does not exist.
vm_resource_group_name = "rg-my-new-jumphosts"

# 3. Existing Network Details
vnet_name           = "vnet-my-production-vnet"
subnet_name         = "snet-jumphosts"

# 4. Existing Route Table
# The name of the route table (UDR) already associated with your subnet.
existing_route_table_name = "rt-my-subnet-routes"

# 5. Security Details
# Find your IP by searching "what is my IP" in Google.
admin_public_ip = "YOUR_HOME_OR_OFFICE_IP_HERE"

# Path to your public SSH key.
# Example: "C:/Users/YourUser/.ssh/id_rsa.pub" or "/home/youruser/.ssh/id_rsa.pub"
admin_ssh_key_path = "~/.ssh/id_rsa.pub"

Usage

  1. Initialize Terraform: This downloads the Azure provider.

    terraform init
    
  2. Plan Deployment: This shows you what resources will be created, modified, or destroyed.

    terraform plan
    
  3. Apply Configuration: This will build the resources in Azure.

    terraform apply
    

    Type yes when prompted to approve the plan.

Outputs

After a successful deployment, Terraform will output the following values:

NameDescription
jump_host_public_ipThe public IP address of the newly created jump host.
ssh_commandThe full SSH command to connect to your new VM.
jump_host_vm_idThe full Azure Resource ID of the created VM.

You can connect to your VM using the ssh_command output:

ssh -k 'ssh-key' azureuser@YOUR_NEW_PUBLIC_IP

Destroying Resources

To remove all resources except the protected resource group, run:

terraform destroy

Note on Resource Group Destruction

The VM resource group (vm_resource_group_name) is protected by a prevent_destroy = true lifecycle block. If you run terraform destroy, all resources (VM, NIC, PIP, NSG, Route) will be deleted, but Terraform will stop with an error, refusing to delete the resource group.

This is a safety feature. To delete the resource group, you must either:

  1. Manually delete it from the Azure Portal.
  2. Comment out or remove the lifecycle block in main.tf and run terraform apply (to update the state) and then terraform destroy again.