Deploy Azure SQL Virtual Machines

The azure-native:sqlvirtualmachine:SqlVirtualMachine resource, part of the Pulumi Azure Native provider, registers Azure VMs running SQL Server with Azure management capabilities. This guide focuses on four capabilities: VM registration with minimal configuration, automated backup scheduling, storage pool configuration, and availability group cluster membership.

SQL VMs reference existing Azure VMs, storage accounts, and optionally SQL virtual machine groups for clustering. The examples are intentionally small. Combine them with your own VM infrastructure, storage accounts, and network configuration.

Register an existing VM with minimal configuration

Most deployments start by registering an existing Azure VM that already has SQL Server installed, establishing the management layer without configuring advanced features.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const sqlVirtualMachine = new azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine", {
    location: "northeurope",
    resourceGroupName: "testrg",
    sqlVirtualMachineName: "testvm",
    virtualMachineResourceId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
});
import pulumi
import pulumi_azure_native as azure_native

sql_virtual_machine = azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine",
    location="northeurope",
    resource_group_name="testrg",
    sql_virtual_machine_name="testvm",
    virtual_machine_resource_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
package main

import (
	sqlvirtualmachine "github.com/pulumi/pulumi-azure-native-sdk/sqlvirtualmachine/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqlvirtualmachine.NewSqlVirtualMachine(ctx, "sqlVirtualMachine", &sqlvirtualmachine.SqlVirtualMachineArgs{
			Location:                 pulumi.String("northeurope"),
			ResourceGroupName:        pulumi.String("testrg"),
			SqlVirtualMachineName:    pulumi.String("testvm"),
			VirtualMachineResourceId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var sqlVirtualMachine = new AzureNative.SqlVirtualMachine.SqlVirtualMachine("sqlVirtualMachine", new()
    {
        Location = "northeurope",
        ResourceGroupName = "testrg",
        SqlVirtualMachineName = "testvm",
        VirtualMachineResourceId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachine;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachineArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var sqlVirtualMachine = new SqlVirtualMachine("sqlVirtualMachine", SqlVirtualMachineArgs.builder()
            .location("northeurope")
            .resourceGroupName("testrg")
            .sqlVirtualMachineName("testvm")
            .virtualMachineResourceId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
            .build());

    }
}
resources:
  sqlVirtualMachine:
    type: azure-native:sqlvirtualmachine:SqlVirtualMachine
    properties:
      location: northeurope
      resourceGroupName: testrg
      sqlVirtualMachineName: testvm
      virtualMachineResourceId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm

The virtualMachineResourceId property links this resource to an existing Azure VM. Registration enables Azure to manage SQL Server features like backups and patching. Without additional configuration blocks, the VM uses default settings for all SQL management features.

Configure automated backups with custom schedules

Production workloads require backup policies that align with business recovery objectives.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const sqlVirtualMachine = new azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine", {
    autoBackupSettings: {
        backupScheduleType: azure_native.sqlvirtualmachine.BackupScheduleType.Manual,
        backupSystemDbs: true,
        daysOfWeek: [
            azure_native.sqlvirtualmachine.AutoBackupDaysOfWeek.Monday,
            azure_native.sqlvirtualmachine.AutoBackupDaysOfWeek.Friday,
        ],
        enable: true,
        enableEncryption: true,
        fullBackupFrequency: azure_native.sqlvirtualmachine.FullBackupFrequencyType.Weekly,
        fullBackupStartTime: 6,
        fullBackupWindowHours: 11,
        logBackupFrequency: 10,
        password: "<Password>",
        retentionPeriod: 17,
        storageAccessKey: "<primary storage access key>",
        storageAccountUrl: "https://teststorage.blob.core.windows.net/",
        storageContainerName: "testcontainer",
    },
    autoPatchingSettings: {
        dayOfWeek: azure_native.sqlvirtualmachine.DayOfWeek.Sunday,
        enable: true,
        maintenanceWindowDuration: 60,
        maintenanceWindowStartingHour: 2,
    },
    keyVaultCredentialSettings: {
        enable: false,
    },
    location: "northeurope",
    resourceGroupName: "testrg",
    serverConfigurationsManagementSettings: {
        additionalFeaturesServerConfigurations: {
            isRServicesEnabled: false,
        },
        sqlConnectivityUpdateSettings: {
            connectivityType: azure_native.sqlvirtualmachine.ConnectivityType.PRIVATE,
            port: 1433,
            sqlAuthUpdatePassword: "<password>",
            sqlAuthUpdateUserName: "sqllogin",
        },
        sqlStorageUpdateSettings: {
            diskConfigurationType: azure_native.sqlvirtualmachine.DiskConfigurationType.NEW,
            diskCount: 1,
            startingDeviceId: 2,
        },
        sqlWorkloadTypeUpdateSettings: {
            sqlWorkloadType: azure_native.sqlvirtualmachine.SqlWorkloadType.OLTP,
        },
    },
    sqlImageSku: azure_native.sqlvirtualmachine.SqlImageSku.Enterprise,
    sqlServerLicenseType: azure_native.sqlvirtualmachine.SqlServerLicenseType.PAYG,
    sqlVirtualMachineName: "testvm",
    virtualMachineResourceId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
});
import pulumi
import pulumi_azure_native as azure_native

sql_virtual_machine = azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine",
    auto_backup_settings={
        "backup_schedule_type": azure_native.sqlvirtualmachine.BackupScheduleType.MANUAL,
        "backup_system_dbs": True,
        "days_of_week": [
            azure_native.sqlvirtualmachine.AutoBackupDaysOfWeek.MONDAY,
            azure_native.sqlvirtualmachine.AutoBackupDaysOfWeek.FRIDAY,
        ],
        "enable": True,
        "enable_encryption": True,
        "full_backup_frequency": azure_native.sqlvirtualmachine.FullBackupFrequencyType.WEEKLY,
        "full_backup_start_time": 6,
        "full_backup_window_hours": 11,
        "log_backup_frequency": 10,
        "password": "<Password>",
        "retention_period": 17,
        "storage_access_key": "<primary storage access key>",
        "storage_account_url": "https://teststorage.blob.core.windows.net/",
        "storage_container_name": "testcontainer",
    },
    auto_patching_settings={
        "day_of_week": azure_native.sqlvirtualmachine.DayOfWeek.SUNDAY,
        "enable": True,
        "maintenance_window_duration": 60,
        "maintenance_window_starting_hour": 2,
    },
    key_vault_credential_settings={
        "enable": False,
    },
    location="northeurope",
    resource_group_name="testrg",
    server_configurations_management_settings={
        "additional_features_server_configurations": {
            "is_r_services_enabled": False,
        },
        "sql_connectivity_update_settings": {
            "connectivity_type": azure_native.sqlvirtualmachine.ConnectivityType.PRIVATE,
            "port": 1433,
            "sql_auth_update_password": "<password>",
            "sql_auth_update_user_name": "sqllogin",
        },
        "sql_storage_update_settings": {
            "disk_configuration_type": azure_native.sqlvirtualmachine.DiskConfigurationType.NEW,
            "disk_count": 1,
            "starting_device_id": 2,
        },
        "sql_workload_type_update_settings": {
            "sql_workload_type": azure_native.sqlvirtualmachine.SqlWorkloadType.OLTP,
        },
    },
    sql_image_sku=azure_native.sqlvirtualmachine.SqlImageSku.ENTERPRISE,
    sql_server_license_type=azure_native.sqlvirtualmachine.SqlServerLicenseType.PAYG,
    sql_virtual_machine_name="testvm",
    virtual_machine_resource_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
package main

import (
	sqlvirtualmachine "github.com/pulumi/pulumi-azure-native-sdk/sqlvirtualmachine/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqlvirtualmachine.NewSqlVirtualMachine(ctx, "sqlVirtualMachine", &sqlvirtualmachine.SqlVirtualMachineArgs{
			AutoBackupSettings: &sqlvirtualmachine.AutoBackupSettingsArgs{
				BackupScheduleType: pulumi.String(sqlvirtualmachine.BackupScheduleTypeManual),
				BackupSystemDbs:    pulumi.Bool(true),
				DaysOfWeek: pulumi.StringArray{
					pulumi.String(sqlvirtualmachine.AutoBackupDaysOfWeekMonday),
					pulumi.String(sqlvirtualmachine.AutoBackupDaysOfWeekFriday),
				},
				Enable:                pulumi.Bool(true),
				EnableEncryption:      pulumi.Bool(true),
				FullBackupFrequency:   pulumi.String(sqlvirtualmachine.FullBackupFrequencyTypeWeekly),
				FullBackupStartTime:   pulumi.Int(6),
				FullBackupWindowHours: pulumi.Int(11),
				LogBackupFrequency:    pulumi.Int(10),
				Password:              pulumi.String("<Password>"),
				RetentionPeriod:       pulumi.Int(17),
				StorageAccessKey:      pulumi.String("<primary storage access key>"),
				StorageAccountUrl:     pulumi.String("https://teststorage.blob.core.windows.net/"),
				StorageContainerName:  pulumi.String("testcontainer"),
			},
			AutoPatchingSettings: &sqlvirtualmachine.AutoPatchingSettingsArgs{
				DayOfWeek:                     sqlvirtualmachine.DayOfWeekSunday,
				Enable:                        pulumi.Bool(true),
				MaintenanceWindowDuration:     pulumi.Int(60),
				MaintenanceWindowStartingHour: pulumi.Int(2),
			},
			KeyVaultCredentialSettings: &sqlvirtualmachine.KeyVaultCredentialSettingsArgs{
				Enable: pulumi.Bool(false),
			},
			Location:          pulumi.String("northeurope"),
			ResourceGroupName: pulumi.String("testrg"),
			ServerConfigurationsManagementSettings: &sqlvirtualmachine.ServerConfigurationsManagementSettingsArgs{
				AdditionalFeaturesServerConfigurations: &sqlvirtualmachine.AdditionalFeaturesServerConfigurationsArgs{
					IsRServicesEnabled: pulumi.Bool(false),
				},
				SqlConnectivityUpdateSettings: &sqlvirtualmachine.SqlConnectivityUpdateSettingsArgs{
					ConnectivityType:      pulumi.String(sqlvirtualmachine.ConnectivityTypePRIVATE),
					Port:                  pulumi.Int(1433),
					SqlAuthUpdatePassword: pulumi.String("<password>"),
					SqlAuthUpdateUserName: pulumi.String("sqllogin"),
				},
				SqlStorageUpdateSettings: &sqlvirtualmachine.SqlStorageUpdateSettingsArgs{
					DiskConfigurationType: pulumi.String(sqlvirtualmachine.DiskConfigurationTypeNEW),
					DiskCount:             pulumi.Int(1),
					StartingDeviceId:      pulumi.Int(2),
				},
				SqlWorkloadTypeUpdateSettings: &sqlvirtualmachine.SqlWorkloadTypeUpdateSettingsArgs{
					SqlWorkloadType: pulumi.String(sqlvirtualmachine.SqlWorkloadTypeOLTP),
				},
			},
			SqlImageSku:              pulumi.String(sqlvirtualmachine.SqlImageSkuEnterprise),
			SqlServerLicenseType:     pulumi.String(sqlvirtualmachine.SqlServerLicenseTypePAYG),
			SqlVirtualMachineName:    pulumi.String("testvm"),
			VirtualMachineResourceId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var sqlVirtualMachine = new AzureNative.SqlVirtualMachine.SqlVirtualMachine("sqlVirtualMachine", new()
    {
        AutoBackupSettings = new AzureNative.SqlVirtualMachine.Inputs.AutoBackupSettingsArgs
        {
            BackupScheduleType = AzureNative.SqlVirtualMachine.BackupScheduleType.Manual,
            BackupSystemDbs = true,
            DaysOfWeek = new[]
            {
                AzureNative.SqlVirtualMachine.AutoBackupDaysOfWeek.Monday,
                AzureNative.SqlVirtualMachine.AutoBackupDaysOfWeek.Friday,
            },
            Enable = true,
            EnableEncryption = true,
            FullBackupFrequency = AzureNative.SqlVirtualMachine.FullBackupFrequencyType.Weekly,
            FullBackupStartTime = 6,
            FullBackupWindowHours = 11,
            LogBackupFrequency = 10,
            Password = "<Password>",
            RetentionPeriod = 17,
            StorageAccessKey = "<primary storage access key>",
            StorageAccountUrl = "https://teststorage.blob.core.windows.net/",
            StorageContainerName = "testcontainer",
        },
        AutoPatchingSettings = new AzureNative.SqlVirtualMachine.Inputs.AutoPatchingSettingsArgs
        {
            DayOfWeek = AzureNative.SqlVirtualMachine.DayOfWeek.Sunday,
            Enable = true,
            MaintenanceWindowDuration = 60,
            MaintenanceWindowStartingHour = 2,
        },
        KeyVaultCredentialSettings = new AzureNative.SqlVirtualMachine.Inputs.KeyVaultCredentialSettingsArgs
        {
            Enable = false,
        },
        Location = "northeurope",
        ResourceGroupName = "testrg",
        ServerConfigurationsManagementSettings = new AzureNative.SqlVirtualMachine.Inputs.ServerConfigurationsManagementSettingsArgs
        {
            AdditionalFeaturesServerConfigurations = new AzureNative.SqlVirtualMachine.Inputs.AdditionalFeaturesServerConfigurationsArgs
            {
                IsRServicesEnabled = false,
            },
            SqlConnectivityUpdateSettings = new AzureNative.SqlVirtualMachine.Inputs.SqlConnectivityUpdateSettingsArgs
            {
                ConnectivityType = AzureNative.SqlVirtualMachine.ConnectivityType.PRIVATE,
                Port = 1433,
                SqlAuthUpdatePassword = "<password>",
                SqlAuthUpdateUserName = "sqllogin",
            },
            SqlStorageUpdateSettings = new AzureNative.SqlVirtualMachine.Inputs.SqlStorageUpdateSettingsArgs
            {
                DiskConfigurationType = AzureNative.SqlVirtualMachine.DiskConfigurationType.NEW,
                DiskCount = 1,
                StartingDeviceId = 2,
            },
            SqlWorkloadTypeUpdateSettings = new AzureNative.SqlVirtualMachine.Inputs.SqlWorkloadTypeUpdateSettingsArgs
            {
                SqlWorkloadType = AzureNative.SqlVirtualMachine.SqlWorkloadType.OLTP,
            },
        },
        SqlImageSku = AzureNative.SqlVirtualMachine.SqlImageSku.Enterprise,
        SqlServerLicenseType = AzureNative.SqlVirtualMachine.SqlServerLicenseType.PAYG,
        SqlVirtualMachineName = "testvm",
        VirtualMachineResourceId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachine;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachineArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.AutoBackupSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.AutoPatchingSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.KeyVaultCredentialSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.ServerConfigurationsManagementSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.AdditionalFeaturesServerConfigurationsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.SqlConnectivityUpdateSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.SqlStorageUpdateSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.SqlWorkloadTypeUpdateSettingsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var sqlVirtualMachine = new SqlVirtualMachine("sqlVirtualMachine", SqlVirtualMachineArgs.builder()
            .autoBackupSettings(AutoBackupSettingsArgs.builder()
                .backupScheduleType("Manual")
                .backupSystemDbs(true)
                .daysOfWeek(                
                    "Monday",
                    "Friday")
                .enable(true)
                .enableEncryption(true)
                .fullBackupFrequency("Weekly")
                .fullBackupStartTime(6)
                .fullBackupWindowHours(11)
                .logBackupFrequency(10)
                .password("<Password>")
                .retentionPeriod(17)
                .storageAccessKey("<primary storage access key>")
                .storageAccountUrl("https://teststorage.blob.core.windows.net/")
                .storageContainerName("testcontainer")
                .build())
            .autoPatchingSettings(AutoPatchingSettingsArgs.builder()
                .dayOfWeek("Sunday")
                .enable(true)
                .maintenanceWindowDuration(60)
                .maintenanceWindowStartingHour(2)
                .build())
            .keyVaultCredentialSettings(KeyVaultCredentialSettingsArgs.builder()
                .enable(false)
                .build())
            .location("northeurope")
            .resourceGroupName("testrg")
            .serverConfigurationsManagementSettings(ServerConfigurationsManagementSettingsArgs.builder()
                .additionalFeaturesServerConfigurations(AdditionalFeaturesServerConfigurationsArgs.builder()
                    .isRServicesEnabled(false)
                    .build())
                .sqlConnectivityUpdateSettings(SqlConnectivityUpdateSettingsArgs.builder()
                    .connectivityType("PRIVATE")
                    .port(1433)
                    .sqlAuthUpdatePassword("<password>")
                    .sqlAuthUpdateUserName("sqllogin")
                    .build())
                .sqlStorageUpdateSettings(SqlStorageUpdateSettingsArgs.builder()
                    .diskConfigurationType("NEW")
                    .diskCount(1)
                    .startingDeviceId(2)
                    .build())
                .sqlWorkloadTypeUpdateSettings(SqlWorkloadTypeUpdateSettingsArgs.builder()
                    .sqlWorkloadType("OLTP")
                    .build())
                .build())
            .sqlImageSku("Enterprise")
            .sqlServerLicenseType("PAYG")
            .sqlVirtualMachineName("testvm")
            .virtualMachineResourceId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
            .build());

    }
}
resources:
  sqlVirtualMachine:
    type: azure-native:sqlvirtualmachine:SqlVirtualMachine
    properties:
      autoBackupSettings:
        backupScheduleType: Manual
        backupSystemDbs: true
        daysOfWeek:
          - Monday
          - Friday
        enable: true
        enableEncryption: true
        fullBackupFrequency: Weekly
        fullBackupStartTime: 6
        fullBackupWindowHours: 11
        logBackupFrequency: 10
        password: <Password>
        retentionPeriod: 17
        storageAccessKey: <primary storage access key>
        storageAccountUrl: https://teststorage.blob.core.windows.net/
        storageContainerName: testcontainer
      autoPatchingSettings:
        dayOfWeek: Sunday
        enable: true
        maintenanceWindowDuration: 60
        maintenanceWindowStartingHour: 2
      keyVaultCredentialSettings:
        enable: false
      location: northeurope
      resourceGroupName: testrg
      serverConfigurationsManagementSettings:
        additionalFeaturesServerConfigurations:
          isRServicesEnabled: false
        sqlConnectivityUpdateSettings:
          connectivityType: PRIVATE
          port: 1433
          sqlAuthUpdatePassword: <password>
          sqlAuthUpdateUserName: sqllogin
        sqlStorageUpdateSettings:
          diskConfigurationType: NEW
          diskCount: 1
          startingDeviceId: 2
        sqlWorkloadTypeUpdateSettings:
          sqlWorkloadType: OLTP
      sqlImageSku: Enterprise
      sqlServerLicenseType: PAYG
      sqlVirtualMachineName: testvm
      virtualMachineResourceId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm

The autoBackupSettings block defines when backups run and where they’re stored. The backupScheduleType of Manual lets you specify daysOfWeek for weekly backups. The fullBackupFrequency controls whether backups run daily or weekly. Backups are encrypted and stored in the Azure Storage account specified by storageAccountUrl, with retentionPeriod controlling how long backups are kept.

Configure storage pools for data and log files

SQL Server performance depends on storage layout. The storageConfigurationSettings block maps Azure managed disks to SQL file locations.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const sqlVirtualMachine = new azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine", {
    location: "northeurope",
    resourceGroupName: "testrg",
    sqlVirtualMachineName: "testvm",
    storageConfigurationSettings: {
        diskConfigurationType: azure_native.sqlvirtualmachine.DiskConfigurationType.NEW,
        sqlDataSettings: {
            defaultFilePath: "F:\\folderpath\\",
            luns: [0],
        },
        sqlLogSettings: {
            defaultFilePath: "G:\\folderpath\\",
            luns: [1],
        },
        sqlSystemDbOnDataDisk: true,
        sqlTempDbSettings: {
            dataFileCount: 8,
            dataFileSize: 256,
            dataGrowth: 512,
            defaultFilePath: "D:\\TEMP",
            logFileSize: 256,
            logGrowth: 512,
        },
        storageWorkloadType: azure_native.sqlvirtualmachine.StorageWorkloadType.OLTP,
    },
    virtualMachineResourceId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
});
import pulumi
import pulumi_azure_native as azure_native

sql_virtual_machine = azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine",
    location="northeurope",
    resource_group_name="testrg",
    sql_virtual_machine_name="testvm",
    storage_configuration_settings={
        "disk_configuration_type": azure_native.sqlvirtualmachine.DiskConfigurationType.NEW,
        "sql_data_settings": {
            "default_file_path": "F:\\folderpath\\",
            "luns": [0],
        },
        "sql_log_settings": {
            "default_file_path": "G:\\folderpath\\",
            "luns": [1],
        },
        "sql_system_db_on_data_disk": True,
        "sql_temp_db_settings": {
            "data_file_count": 8,
            "data_file_size": 256,
            "data_growth": 512,
            "default_file_path": "D:\\TEMP",
            "log_file_size": 256,
            "log_growth": 512,
        },
        "storage_workload_type": azure_native.sqlvirtualmachine.StorageWorkloadType.OLTP,
    },
    virtual_machine_resource_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
package main

import (
	sqlvirtualmachine "github.com/pulumi/pulumi-azure-native-sdk/sqlvirtualmachine/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqlvirtualmachine.NewSqlVirtualMachine(ctx, "sqlVirtualMachine", &sqlvirtualmachine.SqlVirtualMachineArgs{
			Location:              pulumi.String("northeurope"),
			ResourceGroupName:     pulumi.String("testrg"),
			SqlVirtualMachineName: pulumi.String("testvm"),
			StorageConfigurationSettings: &sqlvirtualmachine.StorageConfigurationSettingsArgs{
				DiskConfigurationType: pulumi.String(sqlvirtualmachine.DiskConfigurationTypeNEW),
				SqlDataSettings: &sqlvirtualmachine.SQLStorageSettingsArgs{
					DefaultFilePath: pulumi.String("F:\\folderpath\\"),
					Luns: pulumi.IntArray{
						pulumi.Int(0),
					},
				},
				SqlLogSettings: &sqlvirtualmachine.SQLStorageSettingsArgs{
					DefaultFilePath: pulumi.String("G:\\folderpath\\"),
					Luns: pulumi.IntArray{
						pulumi.Int(1),
					},
				},
				SqlSystemDbOnDataDisk: pulumi.Bool(true),
				SqlTempDbSettings: &sqlvirtualmachine.SQLTempDbSettingsArgs{
					DataFileCount:   pulumi.Int(8),
					DataFileSize:    pulumi.Int(256),
					DataGrowth:      pulumi.Int(512),
					DefaultFilePath: pulumi.String("D:\\TEMP"),
					LogFileSize:     pulumi.Int(256),
					LogGrowth:       pulumi.Int(512),
				},
				StorageWorkloadType: pulumi.String(sqlvirtualmachine.StorageWorkloadTypeOLTP),
			},
			VirtualMachineResourceId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var sqlVirtualMachine = new AzureNative.SqlVirtualMachine.SqlVirtualMachine("sqlVirtualMachine", new()
    {
        Location = "northeurope",
        ResourceGroupName = "testrg",
        SqlVirtualMachineName = "testvm",
        StorageConfigurationSettings = new AzureNative.SqlVirtualMachine.Inputs.StorageConfigurationSettingsArgs
        {
            DiskConfigurationType = AzureNative.SqlVirtualMachine.DiskConfigurationType.NEW,
            SqlDataSettings = new AzureNative.SqlVirtualMachine.Inputs.SQLStorageSettingsArgs
            {
                DefaultFilePath = "F:\\folderpath\\",
                Luns = new[]
                {
                    0,
                },
            },
            SqlLogSettings = new AzureNative.SqlVirtualMachine.Inputs.SQLStorageSettingsArgs
            {
                DefaultFilePath = "G:\\folderpath\\",
                Luns = new[]
                {
                    1,
                },
            },
            SqlSystemDbOnDataDisk = true,
            SqlTempDbSettings = new AzureNative.SqlVirtualMachine.Inputs.SQLTempDbSettingsArgs
            {
                DataFileCount = 8,
                DataFileSize = 256,
                DataGrowth = 512,
                DefaultFilePath = "D:\\TEMP",
                LogFileSize = 256,
                LogGrowth = 512,
            },
            StorageWorkloadType = AzureNative.SqlVirtualMachine.StorageWorkloadType.OLTP,
        },
        VirtualMachineResourceId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachine;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachineArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.StorageConfigurationSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.SQLStorageSettingsArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.SQLTempDbSettingsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var sqlVirtualMachine = new SqlVirtualMachine("sqlVirtualMachine", SqlVirtualMachineArgs.builder()
            .location("northeurope")
            .resourceGroupName("testrg")
            .sqlVirtualMachineName("testvm")
            .storageConfigurationSettings(StorageConfigurationSettingsArgs.builder()
                .diskConfigurationType("NEW")
                .sqlDataSettings(SQLStorageSettingsArgs.builder()
                    .defaultFilePath("F:\\folderpath\\")
                    .luns(0)
                    .build())
                .sqlLogSettings(SQLStorageSettingsArgs.builder()
                    .defaultFilePath("G:\\folderpath\\")
                    .luns(1)
                    .build())
                .sqlSystemDbOnDataDisk(true)
                .sqlTempDbSettings(SQLTempDbSettingsArgs.builder()
                    .dataFileCount(8)
                    .dataFileSize(256)
                    .dataGrowth(512)
                    .defaultFilePath("D:\\TEMP")
                    .logFileSize(256)
                    .logGrowth(512)
                    .build())
                .storageWorkloadType("OLTP")
                .build())
            .virtualMachineResourceId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm")
            .build());

    }
}
resources:
  sqlVirtualMachine:
    type: azure-native:sqlvirtualmachine:SqlVirtualMachine
    properties:
      location: northeurope
      resourceGroupName: testrg
      sqlVirtualMachineName: testvm
      storageConfigurationSettings:
        diskConfigurationType: NEW
        sqlDataSettings:
          defaultFilePath: F:\folderpath\
          luns:
            - 0
        sqlLogSettings:
          defaultFilePath: G:\folderpath\
          luns:
            - 1
        sqlSystemDbOnDataDisk: true
        sqlTempDbSettings:
          dataFileCount: 8
          dataFileSize: 256
          dataGrowth: 512
          defaultFilePath: D:\TEMP
          logFileSize: 256
          logGrowth: 512
        storageWorkloadType: OLTP
      virtualMachineResourceId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm

The diskConfigurationType of NEW creates storage pools from attached disks. The sqlDataSettings, sqlLogSettings, and sqlTempDbSettings blocks each specify luns (logical unit numbers) that identify which managed disks to use. The defaultFilePath properties set where SQL Server places files. This configuration separates data, log, and tempdb across dedicated storage pools for optimal I/O performance.

Join a VM to a SQL virtual machine group

High availability configurations like Always On Availability Groups require VMs to join a SQL virtual machine group, which coordinates cluster membership.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const sqlVirtualMachine = new azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine", {
    location: "northeurope",
    resourceGroupName: "testrg",
    sqlVirtualMachineGroupResourceId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup",
    sqlVirtualMachineName: "testvm",
    virtualMachineResourceId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2",
    wsfcDomainCredentials: {
        clusterBootstrapAccountPassword: "<Password>",
        clusterOperatorAccountPassword: "<Password>",
        sqlServiceAccountPassword: "<Password>",
    },
    wsfcStaticIp: "10.0.0.7",
});
import pulumi
import pulumi_azure_native as azure_native

sql_virtual_machine = azure_native.sqlvirtualmachine.SqlVirtualMachine("sqlVirtualMachine",
    location="northeurope",
    resource_group_name="testrg",
    sql_virtual_machine_group_resource_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup",
    sql_virtual_machine_name="testvm",
    virtual_machine_resource_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2",
    wsfc_domain_credentials={
        "cluster_bootstrap_account_password": "<Password>",
        "cluster_operator_account_password": "<Password>",
        "sql_service_account_password": "<Password>",
    },
    wsfc_static_ip="10.0.0.7")
package main

import (
	sqlvirtualmachine "github.com/pulumi/pulumi-azure-native-sdk/sqlvirtualmachine/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sqlvirtualmachine.NewSqlVirtualMachine(ctx, "sqlVirtualMachine", &sqlvirtualmachine.SqlVirtualMachineArgs{
			Location:                         pulumi.String("northeurope"),
			ResourceGroupName:                pulumi.String("testrg"),
			SqlVirtualMachineGroupResourceId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup"),
			SqlVirtualMachineName:            pulumi.String("testvm"),
			VirtualMachineResourceId:         pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2"),
			WsfcDomainCredentials: &sqlvirtualmachine.WsfcDomainCredentialsArgs{
				ClusterBootstrapAccountPassword: pulumi.String("<Password>"),
				ClusterOperatorAccountPassword:  pulumi.String("<Password>"),
				SqlServiceAccountPassword:       pulumi.String("<Password>"),
			},
			WsfcStaticIp: pulumi.String("10.0.0.7"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var sqlVirtualMachine = new AzureNative.SqlVirtualMachine.SqlVirtualMachine("sqlVirtualMachine", new()
    {
        Location = "northeurope",
        ResourceGroupName = "testrg",
        SqlVirtualMachineGroupResourceId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup",
        SqlVirtualMachineName = "testvm",
        VirtualMachineResourceId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2",
        WsfcDomainCredentials = new AzureNative.SqlVirtualMachine.Inputs.WsfcDomainCredentialsArgs
        {
            ClusterBootstrapAccountPassword = "<Password>",
            ClusterOperatorAccountPassword = "<Password>",
            SqlServiceAccountPassword = "<Password>",
        },
        WsfcStaticIp = "10.0.0.7",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachine;
import com.pulumi.azurenative.sqlvirtualmachine.SqlVirtualMachineArgs;
import com.pulumi.azurenative.sqlvirtualmachine.inputs.WsfcDomainCredentialsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var sqlVirtualMachine = new SqlVirtualMachine("sqlVirtualMachine", SqlVirtualMachineArgs.builder()
            .location("northeurope")
            .resourceGroupName("testrg")
            .sqlVirtualMachineGroupResourceId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup")
            .sqlVirtualMachineName("testvm")
            .virtualMachineResourceId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2")
            .wsfcDomainCredentials(WsfcDomainCredentialsArgs.builder()
                .clusterBootstrapAccountPassword("<Password>")
                .clusterOperatorAccountPassword("<Password>")
                .sqlServiceAccountPassword("<Password>")
                .build())
            .wsfcStaticIp("10.0.0.7")
            .build());

    }
}
resources:
  sqlVirtualMachine:
    type: azure-native:sqlvirtualmachine:SqlVirtualMachine
    properties:
      location: northeurope
      resourceGroupName: testrg
      sqlVirtualMachineGroupResourceId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/testvmgroup
      sqlVirtualMachineName: testvm
      virtualMachineResourceId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/testrg/providers/Microsoft.Compute/virtualMachines/testvm2
      wsfcDomainCredentials:
        clusterBootstrapAccountPassword: <Password>
        clusterOperatorAccountPassword: <Password>
        sqlServiceAccountPassword: <Password>
      wsfcStaticIp: 10.0.0.7

The sqlVirtualMachineGroupResourceId property links this VM to an existing group. The wsfcDomainCredentials block provides passwords for cluster service accounts. The wsfcStaticIp assigns a static IP address for cluster communication. The VM must be domain-joined before joining the group, and the specified static IP must be available in the subnet.

Beyond these examples

These snippets focus on specific SQL VM features: VM registration and group membership, automated backup and patching schedules, and storage pool configuration for SQL files. They’re intentionally minimal rather than full SQL Server deployments.

The examples reference pre-existing infrastructure such as Azure VMs with SQL Server installed, SQL virtual machine groups for cluster scenarios, Azure Storage accounts for backups, and managed disks attached to VMs for storage configuration. They focus on configuring the SQL VM resource rather than provisioning the underlying infrastructure.

To keep things focused, common SQL VM patterns are omitted, including:

  • SQL instance settings (collation, memory, MaxDOP)
  • Assessment schedules and best practices analysis
  • Azure AD authentication configuration
  • Managed identity integration
  • Connectivity and port configuration
  • License type selection (PAYG vs AHUB)

These omissions are intentional: the goal is to illustrate how each SQL VM feature is wired, not provide drop-in production modules. See the SqlVirtualMachine resource reference for all available configuration options.

Let's deploy Azure SQL Virtual Machines

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Setup & Requirements
What's required to create a SQL virtual machine resource?
You must provide virtualMachineResourceId pointing to an existing Azure VM with SQL Server installed, along with location and resourceGroupName. These properties are immutable after creation.
What properties can't be changed after creating the SQL VM resource?
The following properties are immutable: location, virtualMachineResourceId, sqlImageOffer, identity, resourceGroupName, and sqlVirtualMachineName.
Should I set the sqlManagement parameter?
No, don’t use sqlManagement. The API automatically detects SQL management mode, and this parameter is deprecated.
Storage Configuration
What's the difference between NEW and EXTEND disk configuration types?
NEW creates new storage pools for data, log, and tempdb files with specified LUNs and file paths. EXTEND adds disks to existing storage pools by specifying additional LUNs.
How do I configure separate storage for data, log, and tempdb files?
Use storageConfigurationSettings with diskConfigurationType set to NEW. Configure sqlDataSettings, sqlLogSettings, and sqlTempDbSettings with their respective LUNs and defaultFilePath values.
Backup & Maintenance
How do I set up automated backups on specific days of the week?
Configure autoBackupSettings with backupScheduleType set to Manual, fullBackupFrequency to Weekly, and provide a daysOfWeek array (e.g., Monday, Friday). Also specify retention period, storage account details, and backup window times.
How do I configure automatic patching maintenance windows?
Use autoPatchingSettings to specify dayOfWeek, maintenanceWindowStartingHour, and maintenanceWindowDuration (in minutes). Set enable to true to activate automatic patching.
How do I enable SQL best practices assessments?
Configure assessmentSettings with enable set to true. Optionally set runImmediately to true and define a schedule with dayOfWeek, startTime, and weeklyInterval.
Cluster Configuration
How do I join a SQL VM to a Windows Server Failover Cluster?
Set sqlVirtualMachineGroupResourceId to the cluster group resource ID, provide wsfcDomainCredentials with passwords for cluster bootstrap, operator, and SQL service accounts, and specify wsfcStaticIp for the cluster IP address.
What credentials are needed for failover cluster setup?
You need three passwords in wsfcDomainCredentials: clusterBootstrapAccountPassword, clusterOperatorAccountPassword, and sqlServiceAccountPassword.
Security & Identity
How do I use a managed identity with my SQL VM?
Configure virtualMachineIdentitySettings with type set to UserAssigned and provide the resourceId of your user-assigned managed identity.
What does least privilege mode do?
leastPrivilegeMode controls SQL IaaS Agent permissions. It defaults to NotSet but can be set to Enabled to restrict agent privileges. This is configured via the leastPrivilegeMode property.
How do I configure SQL Server connectivity and authentication?
Use serverConfigurationsManagementSettings.sqlConnectivityUpdateSettings to set connectivityType (e.g., PRIVATE), port, and SQL authentication credentials with sqlAuthUpdateUserName and sqlAuthUpdatePassword.
Advanced Configuration
How do I optimize SQL Server instance settings?
Configure serverConfigurationsManagementSettings.sqlInstanceSettings to set maxDop, maxServerMemoryMB, minServerMemoryMB, collation, and enable features like isIfiEnabled (Instant File Initialization) or isOptimizeForAdHocWorkloadsEnabled.
Is automatic upgrade of the SQL IaaS extension enabled by default?
No, enableAutomaticUpgrade defaults to false. Set it to true to enable automatic upgrades of the SQL IaaS extension agent.

Using a different cloud?

Explore database guides for other cloud providers: