Quickstart: Direct web traffic with Azure Application Gateway - Bicep
In this quickstart, you use Bicep to create an Azure Application Gateway. Then you test the application gateway to make sure it works correctly. The Standard v2 SKU is used in this example.
Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. It provides concise syntax, reliable type safety, and support for code reuse. Bicep offers the best authoring experience for your infrastructure-as-code solutions in Azure.
Note
Application Gateway frontend now supports dual-stack IP addresses (Preview). You can now create up to four frontend IP addresses: Two IPv4 addresses (public and private) and two IPv6 addresses (public and private).
Prerequisites
- An Azure account with an active subscription. Create an account for free.
Review the Bicep file
This Bicep file creates a simple setup with a public frontend IP address, a basic listener to host a single site on the application gateway, a basic request routing rule, and two virtual machines in the backend pool.
The Bicep file used in this quickstart is from Azure Quickstart Templates
@description('Admin username for the backend servers')
param adminUsername string
@description('Password for the admin account on the backend servers')
@secure()
param adminPassword string
@description('Location for all resources.')
param location string = resourceGroup().location
@description('Size of the virtual machine.')
param vmSize string = 'Standard_B2ms'
var virtualMachineName = 'myVM'
var virtualNetworkName = 'myVNet'
var networkInterfaceName = 'net-int'
var ipconfigName = 'ipconfig'
var publicIPAddressName = 'public_ip'
var nsgName = 'vm-nsg'
var applicationGateWayName = 'myAppGateway'
var virtualNetworkPrefix = '10.0.0.0/16'
var subnetPrefix = '10.0.0.0/24'
var backendSubnetPrefix = '10.0.1.0/24'
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-09-01' = [for i in range(0, 2): {
name: '${nsgName}${i + 1}'
location: location
properties: {
securityRules: [
{
name: 'RDP'
properties: {
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRange: '3389'
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
access: 'Allow'
priority: 300
direction: 'Inbound'
}
}
]
}
}]
resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-09-01' = [for i in range(0, 3): {
name: '${publicIPAddressName}${i}'
location: location
sku: {
name: 'Standard'
}
properties: {
publicIPAddressVersion: 'IPv4'
publicIPAllocationMethod: 'Static'
idleTimeoutInMinutes: 4
}
}]
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-09-01' = {
name: virtualNetworkName
location: location
properties: {
addressSpace: {
addressPrefixes: [
virtualNetworkPrefix
]
}
subnets: [
{
name: 'myAGSubnet'
properties: {
addressPrefix: subnetPrefix
privateEndpointNetworkPolicies: 'Enabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
}
{
name: 'myBackendSubnet'
properties: {
addressPrefix: backendSubnetPrefix
privateEndpointNetworkPolicies: 'Enabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
}
]
enableDdosProtection: false
enableVmProtection: false
}
}
resource virtualMachine 'Microsoft.Compute/virtualMachines@2023-09-01' = [for i in range(0, 2): {
name: '${virtualMachineName}${i + 1}'
location: location
properties: {
hardwareProfile: {
vmSize: vmSize
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: '2016-Datacenter'
version: 'latest'
}
osDisk: {
osType: 'Windows'
createOption: 'FromImage'
caching: 'ReadWrite'
managedDisk: {
storageAccountType: 'StandardSSD_LRS'
}
diskSizeGB: 127
}
}
osProfile: {
computerName: '${virtualMachineName}${i + 1}'
adminUsername: adminUsername
adminPassword: adminPassword
windowsConfiguration: {
provisionVMAgent: true
enableAutomaticUpdates: true
}
allowExtensionOperations: true
}
networkProfile: {
networkInterfaces: [
{
id: resourceId('Microsoft.Network/networkInterfaces', '${networkInterfaceName}${i + 1}')
}
]
}
}
dependsOn: [
networkInterface
]
}]
resource virtualMachine_IIS 'Microsoft.Compute/virtualMachines/extensions@2023-09-01' = [for i in range(0, 2): {
name: '${virtualMachineName}${(i + 1)}/IIS'
location: location
properties: {
autoUpgradeMinorVersion: true
publisher: 'Microsoft.Compute'
type: 'CustomScriptExtension'
typeHandlerVersion: '1.4'
settings: {
commandToExecute: 'powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path "C:\\inetpub\\wwwroot\\Default.htm" -Value $($env:computername)'
}
}
dependsOn: [
virtualMachine
]
}]
resource applicationGateWay 'Microsoft.Network/applicationGateways@2023-09-01' = {
name: applicationGateWayName
location: location
properties: {
sku: {
name: 'Standard_v2'
tier: 'Standard_v2'
}
gatewayIPConfigurations: [
{
name: 'appGatewayIpConfig'
properties: {
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', virtualNetworkName, 'myAGSubnet')
}
}
}
]
frontendIPConfigurations: [
{
name: 'appGwPublicFrontendIp'
properties: {
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: resourceId('Microsoft.Network/publicIPAddresses', '${publicIPAddressName}0')
}
}
}
]
frontendPorts: [
{
name: 'port_80'
properties: {
port: 80
}
}
]
backendAddressPools: [
{
name: 'myBackendPool'
properties: {}
}
]
backendHttpSettingsCollection: [
{
name: 'myHTTPSetting'
properties: {
port: 80
protocol: 'Http'
cookieBasedAffinity: 'Disabled'
pickHostNameFromBackendAddress: false
requestTimeout: 20
}
}
]
httpListeners: [
{
name: 'myListener'
properties: {
frontendIPConfiguration: {
id: resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', applicationGateWayName, 'appGwPublicFrontendIp')
}
frontendPort: {
id: resourceId('Microsoft.Network/applicationGateways/frontendPorts', applicationGateWayName, 'port_80')
}
protocol: 'Http'
requireServerNameIndication: false
}
}
]
requestRoutingRules: [
{
name: 'myRoutingRule'
properties: {
ruleType: 'Basic'
priority: 1
httpListener: {
id: resourceId('Microsoft.Network/applicationGateways/httpListeners', applicationGateWayName, 'myListener')
}
backendAddressPool: {
id: resourceId('Microsoft.Network/applicationGateways/backendAddressPools', applicationGateWayName, 'myBackendPool')
}
backendHttpSettings: {
id: resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection', applicationGateWayName, 'myHTTPSetting')
}
}
}
]
enableHttp2: false
autoscaleConfiguration: {
minCapacity: 0
maxCapacity: 10
}
}
dependsOn: [
virtualNetwork
publicIPAddress[0]
]
}
resource networkInterface 'Microsoft.Network/networkInterfaces@2023-09-01' = [for i in range(0, 2): {
name: '${networkInterfaceName}${i + 1}'
location: location
properties: {
ipConfigurations: [
{
name: '${ipconfigName}${i + 1}'
properties: {
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: resourceId('Microsoft.Network/publicIPAddresses', '${publicIPAddressName}${i + 1}')
}
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', virtualNetworkName, 'myBackendSubnet')
}
primary: true
privateIPAddressVersion: 'IPv4'
applicationGatewayBackendAddressPools: [
{
id: resourceId('Microsoft.Network/applicationGateways/backendAddressPools', applicationGateWayName, 'myBackendPool')
}
]
}
}
]
enableAcceleratedNetworking: false
enableIPForwarding: false
networkSecurityGroup: {
id: resourceId('Microsoft.Network/networkSecurityGroups', '${nsgName}${i + 1}')
}
}
dependsOn: [
publicIPAddress
applicationGateWay
nsg
]
}]
output location string = location
output name string = applicationGateWay.name
output resourceGroupName string = resourceGroup().name
output resourceId string = applicationGateWay.id
Tip
You can modify values of the Name
and Tier
parameters under resource\applicationGateWay\properties\sku
to use a different SKU. For example: Basic
.
Multiple Azure resources are defined in the Bicep file:
- Microsoft.Network/applicationgateways
- Microsoft.Network/publicIPAddresses : one for the application gateway, and two for the virtual machines.
- Microsoft.Network/networkSecurityGroups
- Microsoft.Network/virtualNetworks
- Microsoft.Compute/virtualMachines : two virtual machines
- Microsoft.Network/networkInterfaces : two for the virtual machines
- Microsoft.Compute/virtualMachine/extensions : to configure IIS and the web pages
Deploy the Bicep file
Save the Bicep file as main.bicep to your local computer.
Deploy the Bicep file using either Azure CLI or Azure PowerShell.
az group create --name myResourceGroupAG --location eastus az deployment group create --resource-group myResourceGroupAG --template-file main.bicep --parameters adminUsername=<admin-username>
Note
Replace <admin-username> with the admin username for the backend servers. You'll also be prompted to enter adminPassword.
When the deployment finishes, you should see a message indicating the deployment succeeded.
Validate the deployment
Use the Azure portal, Azure CLI, or Azure PowerShell to list the deployed resources in the resource group.
az resource list --resource-group myResourceGroupAG
Clean up resources
When no longer needed, use the Azure portal, Azure CLI, or Azure PowerShell to delete the resource group and its resources.
az group delete --name myResourceGroupAG