ARM Template to Easily Create an Azure WordPress Website

Posted by:

|

On:

|

Microsoft’s documentation has a link to a QuickStart template that does this, but it doesn’t follow naming conventions for some reason. Here’s an ARM template to fix that.

Resources Created:

  • NetworkWatcherRG resource group w/ Network Watcher
  • Other Resource Groups Specified in Parameters
  • App Service Plan
  • App Service
  • Private DNS Zone
  • MySQL Flexible Server
  • Azure Database for MySQL Flexible Server
  • VNET including app and database subnets

You will still have to retool these JSON files, I’ve noted the properties that you will need to specify like <this>. There are other values that you may prefer to modify regardless. The naming conventions follow those specified in Microsoft’s documentation. This ARM template creates a vnet with a /16 scope and creates two /24 subnets. This usually defaults to 10.0.0.0/24 and 10.0.1.0/24 which may not suit everyone.

Once deployment is finished, you can navigate to the site.

  • Website: www.website.azuresites.net
  • Admin: www.website.azuresites.net/admin
  • Flexible Server: www.website.azuresites.net/phpmyadmin

For the hobbyist, I like the default WordPress current year theme since it’s fast and generally uses good practices. I’ve made several websites from Dreamweaver, or pure HTML, CSS, and Java in high school and college but no point in re-inventing the wheel. If you NEED a bespoke theme don’t pay less than $1,000-2,000 unless you want a reskinned template. Regardless of what you choose, use dark mode and keep content centered.

You will 99% save money using a shared host, but it’s fun to make your own server. Keep in mind your website will be slow unless you set up CDN.

A website should be eye-catching, snappy, and full of useful content. Don’t let web developers bloat your page with spyware and crypto miners.

ARM Template

JSON
{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "subscriptionId": {
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "hostingPlanName": {
            "type": "string"
        },
        "serverFarmResourceGroup": {
            "type": "string"
        },
        "ftpsState": {
            "type": "string"
        },
        "sku": {
            "type": "string"
        },
        "skuCode": {
            "type": "string"
        },
        "workerSize": {
            "type": "string"
        },
        "workerSizeId": {
            "type": "string"
        },
        "numberOfWorkers": {
            "type": "string"
        },
        "kind": {
            "type": "string"
        },
        "reserved": {
            "type": "bool"
        },
        "alwaysOn": {
            "type": "bool"
        },
        "linuxFxVersion": {
            "type": "string"
        },
        "dockerRegistryUrl": {
            "type": "string"
        },
        "storageSizeGB": {
            "type": "int"
        },
        "storageIops": {
            "type": "int"
        },
        "storageAutoGrow": {
            "type": "string"
        },
        "storageAutoIoScaling": {
            "type": "string"
        },
        "backupRetentionDays": {
            "type": "int"
        },
        "geoRedundantBackup": {
            "type": "string"
        },
        "charset": {
            "type": "string"
        },
        "collation": {
            "type": "string"
        },
        "vmName": {
            "type": "string"
        },
        "serverEdition": {
            "type": "string"
        },
        "vCores": {
            "type": "int"
        },
        "serverName": {
            "type": "string"
        },
        "serverUsername": {
            "type": "string"
        },
        "serverPassword": {
            "type": "securestring"
        },
        "databaseName": {
            "type": "string"
        },
        "publicNetworkAccess": {
            "type": "string"
        },
        "wordpressTitle": {
            "type": "string"
        },
        "wordpressAdminEmail": {
            "type": "string"
        },
        "wordpressUsername": {
            "type": "string"
        },
        "wordpressPassword": {
            "type": "securestring"
        },
        "wpLocaleCode": {
            "type": "string"
        },
        "vnetName": {
            "type": "string"
        },
        "subnetForApp": {
            "type": "string"
        },
        "subnetForDb": {
            "type": "string"
        },
        "privateDnsZoneNameForDb": {
            "type": "string"
        },
        "vnetrg": {
            "type": "string"
        }
    },
    "resources": [
        {
            "apiVersion": "[variables('appServicesApiVersion')]",
            "name": "[parameters('name')]",
            "type": "Microsoft.Web/sites",
            "location": "[parameters('location')]",
            "tags": {
                "AppProfile": "Wordpress"
            },
            "dependsOn": [
                "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                "[concat('Microsoft.DBforMySQL/flexibleServers/', parameters('serverName'))]",
                "[concat('Microsoft.DBforMySQL/flexibleServers/', parameters('serverName'), '/databases/', parameters('databaseName'))]"
            ],
            "properties": {
                "name": "[parameters('name')]",
                "siteConfig": {
                    "appSettings": [
                        {
                            "name": "DOCKER_REGISTRY_SERVER_URL",
                            "value": "[parameters('dockerRegistryUrl')]"
                        },
                        {
                            "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
                            "value": "true"
                        },
                        {
                            "name": "DATABASE_HOST",
                            "value": "[concat(parameters('serverName'),'.mysql.database.azure.com')]"
                        },
                        {
                            "name": "DATABASE_NAME",
                            "value": "[parameters('databaseName')]"
                        },
                        {
                            "name": "DATABASE_USERNAME",
                            "value": "[parameters('serverUsername')]"
                        },
                        {
                            "name": "DATABASE_PASSWORD",
                            "value": "[parameters('serverPassword')]"
                        },
                        {
                            "name": "WORDPRESS_ADMIN_EMAIL",
                            "value": "[parameters('wordpressAdminEmail')]"
                        },
                        {
                            "name": "WORDPRESS_ADMIN_USER",
                            "value": "[parameters('wordpressUsername')]"
                        },
                        {
                            "name": "WORDPRESS_ADMIN_PASSWORD",
                            "value": "[parameters('wordpressPassword')]"
                        },
                        {
                            "name": "WORDPRESS_TITLE",
                            "value": "[parameters('wordpressTitle')]"
                        },
                        {
                            "name": "WEBSITES_CONTAINER_START_TIME_LIMIT",
                            "value": "1800"
                        },
                        {
                            "name": "WORDPRESS_LOCALE_CODE",
                            "value": "[parameters('wpLocaleCode')]"
                        },
                        {
                            "name": "SETUP_PHPMYADMIN",
                            "value": "true"
                        },
                        {
                            "name": "WORDPRESS_LOCAL_STORAGE_CACHE_ENABLED",
                            "value": "true"
                        }
                    ],
                    "connectionStrings": [],
                    "ftpsState": "[parameters('ftpsState')]",
                    "linuxFxVersion": "[parameters('linuxFxVersion')]",
                    "vnetRouteAllEnabled": true
                },
                "serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                "clientAffinityEnabled": false
            }
        },
        {
            "apiVersion": "[variables('appServicesApiVersion')]",
            "name": "[parameters('hostingPlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "location": "[parameters('location')]",
            "kind": "[parameters('kind')]",
            "tags": {
                "AppProfile": "Wordpress"
            },
            "properties": {
                "name": "[parameters('hostingPlanName')]",
                "workerSize": "[parameters('workerSize')]",
                "workerSizeId": "[parameters('workerSizeId')]",
                "numberOfWorkers": "[parameters('numberOfWorkers')]",
                "reserved": "[parameters('reserved')]"
            },
            "sku": {
                "Tier": "[parameters('sku')]",
                "Name": "[parameters('skuCode')]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.DBforMySQL/flexibleServers', parameters('serverName'))]"
            ]
        },
        {
            "apiVersion": "[variables('databaseApiVersion')]",
            "location": "[parameters('location')]",
            "name": "[parameters('serverName')]",
            "type": "Microsoft.DBforMySQL/flexibleServers/",
            "tags": {
                "AppProfile": "Wordpress"
            },
            "properties": {
                "version": "[variables('databaseVersion')]",
                "administratorLogin": "[parameters('serverUsername')]",
                "administratorLoginPassword": "[parameters('serverPassword')]",
                "publicNetworkAccess": "[parameters('publicNetworkAccess')]",
                "Storage": {
                    "StorageSizeGB": "[parameters('storageSizeGB')]",
                    "Iops": "[parameters('storageIops')]",
                    "Autogrow": "[parameters('storageAutoGrow')]",
                    "AutoIoScaling": "[parameters('storageAutoIoScaling')]"
                },
                "Backup": {
                    "backupRetentionDays": "[parameters('backupRetentionDays')]",
                    "geoRedundantBackup": "[parameters('geoRedundantBackup')]"
                },
                "Network": {
                    "PrivateDnsZoneResourceId": "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateDnsZoneNameForDb'))]",
                    "DelegatedSubnetResourceId": "[resourceId(parameters('vnetrg'),'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetForDb'))]"
                }
            },
            "sku": {
                "name": "[parameters('vmName')]",
                "tier": "[parameters('serverEdition')]",
                "capacity": "[parameters('vCores')]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneNameForDb'), format('{0}-vnetlink', parameters('privateDnsZoneNameForDb')))]",
                "[resourceId(parameters('vnetrg'),'Microsoft.Resources/deployments', 'subnet_Resources')]"
            ]
        },
        {
            "type": "Microsoft.DBforMySQL/flexibleServers/databases",
            "name": "[format('{0}/{1}', parameters('serverName'), parameters('databaseName') )]",
            "apiVersion": "[variables('databaseApiVersion')]",
            "properties": {
                "charset": "[parameters('charset')]",
                "collation": "[parameters('collation')]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.DBforMySQL/flexibleServers', parameters('serverName'))]"
            ]
        },
        {
            "type": "Microsoft.Resources/deployments",
            "name": "subnet_Resources",
            "apiVersion": "2020-06-01",
            "dependsOn": [],
            "resourceGroup": "rg-<appname>-prod-001",
            "subscriptionId": "<subscriptionID>",
            "properties": {
                "mode": "Incremental",
                "template": {
                    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.1",
                    "parameters": {},
                    "variables": {},
                    "resources": [
                        {
                            "type": "Microsoft.Network/virtualNetworks/subnets",
                            "apiVersion": "2021-03-01",
                            "name": "[format('{0}/{1}', parameters('vnetName'), parameters('subnetForApp'))]",
                            "properties": {
                                "addressPrefix": "<subnet1>/<cidr>",
                                "delegations": [
                                    {
                                        "name": "dlg-appService",
                                        "properties": {
                                            "serviceName": "Microsoft.Web/serverFarms"
                                        }
                                    }
                                ]
                            }
                        },
                        {
                            "type": "Microsoft.Network/virtualNetworks/subnets",
                            "apiVersion": "2021-03-01",
                            "name": "[format('{0}/{1}',parameters('vnetName'), parameters('subnetForDb'))]",
                            "properties": {
                                "addressPrefix": "<subnet2>/<cidr>",
                                "delegations": [
                                    {
                                        "name": "dlg-appService",
                                        "properties": {
                                            "serviceName": "Microsoft.DBforMySQL/flexibleServers"
                                        }
                                    }
                                ]
                            },
                            "dependsOn": [
                                "[resourceId(parameters('vnetrg'),'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetForApp'))]"
                            ]
                        }
                    ]
                }
            }
        },
        {
            "type": "Microsoft.Network/privateDnsZones",
            "apiVersion": "[variables('privateDnsApiVersion')]",
            "name": "[parameters('privateDnsZoneNameForDb')]",
            "location": "global",
            "tags": {
                "AppProfile": "Wordpress"
            },
            "resources": [
                {
                    "type": "virtualNetworkLinks",
                    "apiVersion": "[variables('privateDnsApiVersion')]",
                    "name": "[format('{0}-vnetlink', parameters('privateDnsZoneNameForDb'))]",
                    "location": "global",
                    "dependsOn": [
                        "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateDnsZoneNameForDb'))]"
                    ],
                    "properties": {
                        "virtualNetwork": {
                            "id": "[resourceId(parameters('vnetrg'),'Microsoft.Network/virtualNetworks/', parameters('vnetName'))]"
                        },
                        "registrationEnabled": false
                    }
                }
            ],
            "dependsOn": [
                "[resourceId(parameters('vnetrg'),'Microsoft.Resources/deployments', 'subnet_Resources')]"
            ]
        },
        {
            "apiVersion": "[variables('appServicesApiVersion')]",
            "type": "Microsoft.Web/sites/networkConfig",
            "name": "[format('{0}/{1}', parameters('name'), 'virtualNetwork')]",
            "properties": {
                "subnetResourceId": "[resourceId(parameters('vnetrg'),'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetForApp'))]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/Sites', parameters('name'))]",
                "[resourceId('Microsoft.Network/privateDnsZones/virtualNetworkLinks', parameters('privateDnsZoneNameForDb'), format('{0}-vnetlink', parameters('privateDnsZoneNameForDb')))]"
            ]
        },
        {
            "type": "Microsoft.Web/sites/config",
            "apiVersion": "[variables('appServicesApiVersion')]",
            "name": "[concat(parameters('name'), '/web')]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/Sites', parameters('name'))]",
                "[resourceId('Microsoft.Web/sites/networkConfig', parameters('name'), 'virtualNetwork')]"
            ],
            "properties": {
                "alwaysOn": "[parameters('alwaysOn')]"
            }
        }
    ],
    "variables": {
        "appServicesApiVersion": "2021-03-01",
        "databaseApiVersion": "2021-12-01-preview",
        "databaseVersion": "8.0.21",
        "vnetDeploymentApiVersion": "2020-07-01",
        "privateDnsApiVersion": "2018-09-01",
        "privateEndpointApiVersion": "2021-03-01",
        "vnetAddress": "<vnetAddressSpace"
    }
}

Template Parameters

JSON
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "subscriptionId": {
      "value": "<subscriptionID>"
    },
    "name": {
      "value": "azapp-<appname>"
    },
    "location": {
      "value": "East US"
    },
    "hostingPlanName": {
      "value": "asp-<appname>-prod-001"
    },
    "serverFarmResourceGroup": {
      "value": "rg-<appname>-prod-001"
    },
    "ftpsState": {
      "value": "FtpsOnly"
    },
    "sku": {
      "value": "Basic"
    },
    "skuCode": {
      "value": "B1"
    },
    "workerSize": {
      "value": "3"
    },
    "workerSizeId": {
      "value": "3"
    },
    "numberOfWorkers": {
      "value": "1"
    },
    "kind": {
      "value": "linux"
    },
    "reserved": {
      "value": true
    },
    "alwaysOn": {
      "value": true
    },
    "linuxFxVersion": {
      "value": "DOCKER|mcr.microsoft.com/appsvc/wordpress-alpine-php:8.2"
    },
    "dockerRegistryUrl": {
      "value": "https://mcr.microsoft.com"
    },
    "storageSizeGB": {
      "value": 20
    },
    "storageIops": {
      "value": 700
    },
    "storageAutoGrow": {
      "value": "Enabled"
    },
    "storageAutoIoScaling": {
      "value": "Enabled"
    },
    "backupRetentionDays": {
      "value": 7
    },
    "geoRedundantBackup": {
      "value": "Disabled"
    },
    "charset": {
      "value": "utf8"
    },
    "collation": {
      "value": "utf8_general_ci"
    },
    "vmName": {
      "value": "Standard_B1ms"
    },
    "serverEdition": {
      "value": "Burstable"
    },
    "vCores": {
      "value": 1
    },
    "serverName": {
      "value": "vm<appname>db01"
    },
    "serverUsername": {
      "value": "<serverUsername>"
    },
    "serverPassword": {
      "value": "<serverPassword>"
    },
    "databaseName": {
      "value": "mysql-<appname>-prod"
    },
    "publicNetworkAccess": {
      "value": "Disabled"
    },
    "wordpressTitle": {
      "value": "<wordpressTitle>"
    },
    "wordpressAdminEmail": {
      "value": "<wordpressAdminEmail>"
    },
    "wordpressUsername": {
      "value": "<wordpressAdminUsername>"
    },
    "wordpressPassword": {
      "value": "<wordpressPassword>"
    },
    "wpLocaleCode": {
      "value": "en_US"
    },
    "vnetName": {
      "value": "vnet-prod-eastus-001"
    },
    "subnetForApp": {
      "value": "snet-app-eastus-001"
    },
    "subnetForDb": {
      "value": "snet-db-eastus-001"
    },
    "privateDnsZoneNameForDb": {
      "value": "azapp-<appname>-privatelink.mysql.database.azure.com"
    },
    "vnetrg": {
      "value": "rg-<appname>-prod-001"
    }
  }
}