Using Terraform to create Private Endpoint for Azure Database for MySQL

Published Apr 03 2020 02:25 PM 8,480 Views

Private Link enables users to have private connectivity from a Microsoft Azure Virtual Network to Azure Database for MySQL. This feature creates a private endpoint that maps a private IP address from the Virtual Network to an Azure Database for MySQL instance.


Hashicorp Terraform is an open-source tool for provisioning and managing cloud infrastructure. It codifies infrastructure in configuration files that describe the topology of cloud resources. The Terraform CLI provides a simple mechanism to deploy and version the configuration files to Azure.


Step-by-step instructions on how to use Terraform to provision private endpoint for Azure Database for MySQL are outlined below.



  1. If you don't have an Azure subscription, create a free account before you begin.
  2. Install Azure CLI latest version
  3. Download and Install Terraform latest version
  4. You can also use Azure Cloud Shell which has Azure CLI and Terraform installed already.




1. Login to the subscription in which you wish to create resources


az login
az account set --subscription=ffffffff-ffff-ffff-ffff-ffffffffffff


2. Create resource group


az group create -l australiaeast -n MysqlResourceGroup


3. Create service principal to be used by Terraform. Assign the service principal as Contributor for the subscription so that it can be used for creating resources.


az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/ffffffff-ffff-ffff-ffff-ffffffffffff"


Record output of the above command


  "appId": "917aeb14-bf7f-4687-8bdb-6d2f5b972eae",
  "displayName": "azure-cli-2020-04-01-23-03-44",
  "name": "http://azure-cli-2020-04-01-23-03-44",
  "password": "4f6833a0-afdf-498d-99f9-02d9b59a06f0",
  "tenant": "59297e42-ba2f-4eca-909a-bc93656bfdbc"


4. Create a file named with the following content. Replace subscription_id, client_id (appId), client_secret (password), tenant_id with appropriate values from above output


terraform {
  required_version = ">= 0.12"

provider "azurerm" {
  version = ">=1.29.0"
  subscription_id = "ffffffff-ffff-ffff-ffff-ffffffffffff"
  client_id       = "917aeb14-bf7f-4687-8bdb-6d2f5b972eae"
  client_secret   = "4f6833a0-afdf-498d-99f9-02d9b59a06f0"
  tenant_id       = "59297e42-ba2f-4eca-909a-bc93656bfdbc"

resource "random_string" "random" {
  length = 6
  special = false
  upper = false

resource "azurerm_virtual_network" "example" {
  name                = "${random_string.random.result}-network"
  address_space       = [""]
  location            = "Australia East"
  resource_group_name = "MysqlResourceGroup"

resource "azurerm_subnet" "example" {
  name                 = "${random_string.random.result}-subnet"
  resource_group_name  = "MysqlResourceGroup"
  virtual_network_name =
  address_prefix       = ""

  enforce_private_link_endpoint_network_policies = true

resource "azurerm_mysql_server" "example" {
  name                = "${random_string.random.result}-mysql"
  location            = "Australia East"
  resource_group_name = "MysqlResourceGroup"

  sku_name = "GP_Gen5_2"

  storage_profile {
    storage_mb            = 51200
    backup_retention_days = 7
    geo_redundant_backup  = "Disabled"
    auto_grow             = "Enabled"

  administrator_login          = "mysqladmin"
  administrator_login_password = "H@Sh1CoR3!"
  version                      = "5.7"
  ssl_enforcement              = "Enabled"

resource "azurerm_private_endpoint" "example" {
  name                = "${random_string.random.result}-endpoint"
  location            = "Australia East"
  resource_group_name = "MysqlResourceGroup"
  subnet_id           =

  private_service_connection {
    name                           = "${random_string.random.result}-privateserviceconnection"
    private_connection_resource_id =
    subresource_names              = [ "mysqlServer" ]
    is_manual_connection           = false


5. Provision the above resources using the following commands


terraform init
rm terraform.tfstate
terraform plan
terraform apply



  1. Private endpoints feature is supported only on General Purpose and Memory Optimized pricing tiers of Azure Database for MySQL.
  2. For manual approval of private endpoint connection, you can use is_manual_connection = true
  3. If you already have a subnet and mysql server, you can just provision “azurerm_private_endpoint” resource with appropriate values passed for subnet_id and private_connection_resource_id

Once the resources are provisioned successfully without any errors, you will be able to connect to the MySQL Server from the VNET using the following command. (Replace host, user, password with appropriate values):


mysql --host= --port=3306 --database=mysql --user=mysqladmin@server-mysql --ssl-mode=REQUIRED --password=H@Sh1CoR3!




Remove the service principal and resource group if needed


az ad sp delete --id 917aeb14-bf7f-4687-8bdb-6d2f5b972eae
az group delete -n MysqlResourceGroup 
Version history
Last update:
‎Apr 03 2020 02:25 PM
Updated by: