Provisioning a Red Hat Enterprise Linux 7 virtual machine for Azure Stack

Updated -

Before you start

Register and log in to the Azure Stack environment

You register and log in to the Azure Stack environment to create resources and whenever you need to manage resources in the environment.

  1. Register with the Azure Stack environment using the az cloud register command.

    Note: --name is the Azure Stack cloud name and --endpoint-resource-manager is the Azure Stack endpoint URL. Both of these are supplied by the local Azure Stack administrator. The storage account suffix is usually a portion of the full endpoint. (See the example.)

    $ az cloud register --name <Azure-Stack-Cloud-Name> --endpoint-resource-manager "https://<resource-manager-endpoint>" --suffix-storage-endpoint <suffix-for-storage-accounts>


    [stackuser@localhost ~]$ az cloud register -n AzureStack --endpoint-resource-manager "" --suffix-storage-endpoint

  2. Set your environment to the active Azure Stack cloud.

    $ az cloud set -n <Azure-Stack-Cloud-Name>


    [stackuser@localhost ~]$ az cloud set -n AzureStack
    Switched active cloud to 'AzureStack'.
    Use 'az login' to log in to this cloud.
    Use 'az account set' to set the active subscription.

  3. Log in to your Azure Stack account using the Azure CLI. If you are already logged in, enter az account show to view account details.

    Note: If managing resources in multiple Azure Stack environments, make sure the default environment is the environment where you want to create resources.

    $ az login


    [stackuser@localhost ~] $ az login
    To sign in, use a web browser to open the page and enter the code ATZXXXXJY to authenticate.
        "cloudName": "AzureStack",
        "id": "f11c973e-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "isDefault": true,
        "name": "Account-Name",
        "state": "Enabled",
        "tenantId": "a3f33ab9-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
        "user": {
          "name": "",
          "type": "user"

  4. Update the environment configuration to use the Azure Stack API version profile.

    $ az cloud update --profile 2017-03-09-profile

Create Azure Stack resources

Create the following resources for your components.

  1. Create a resource group.

    $ az group create --name <MyResourceGroup> --location <MyAzureStackLocation>


    [stackuser@localhost ~] $ az group create --name azurestack-003 -l westus
      "id": "/subscriptions/f11c973e-xxxx-xxxx-xxxx-xxxxxxxxxxxxx/resourceGroups/azurestack-003",
      "location": "westus",
      "name": "azurestack-003",
      "properties": {
        "provisioningState": "Succeeded"
      "tags": null

  2. Create a storage account.

    Note: Locally redundant storage (Standard_LRS) is the only redundant storage option applicable to Azure Stack. See Azure Stack Storage: Differences and considerations.

    $ az storage account create --resource-group <MyResourceGroup> --name <MyStorageAccount> --sku Standard_LRS


    [stackuser@localhost ~] $ az storage account create --resource-group azurestack-003 --name stackaccount003 --sku Standard_LRS
      "primaryLocation": "westus",
      "provisioningState": "Succeeded",
      "resourceGroup": "azurestack-003",
      "secondaryEndpoints": null,
      "secondaryLocation": null,
      "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
      "statusOfPrimary": "Available",
      "statusOfSecondary": null,
      "tags": null,
      "type": "Microsoft.Storage/storageaccounts"

  3. Create a storage container.

    $ az storage container create --account-name <MyStorageAccount> --name <MyStorageContainer>


    [stackuser@localhost ~] $ az storage container create --account-name account003 --name storagecontainer003
      "created": true

  4. Create a virtual network.

    $ az network vnet create --resource-group <MyResourceGroup> --name <MyVnet> --subnet-name <MyVnetSubnet>


    [stackuser@localhost ~] $ az network vnet create --resource-group azurestack-003 --name stack003vnet --subnet-name stack003subnet
      "newVNet": {
        "additionalProperties": {},
        "addressSpace": {
          "additionalProperties": {},
          "addressPrefixes": [
          "ipConfigurations": null,
          "name": "stack003subnet",
          "networkSecurityGroup": null,
          "provisioningState": "Succeeded",
          "resourceGroup": "azurestack-003",
          "routeTable": null
      "tags": {},
      "type": "Microsoft.Network/virtualNetworks"

Create an Azure Network Security Group and SSH inbound rule

Azure Stack environments do not have a default public firewall. To protect your resources, create an Azure Network Security Group (NSG) for the resource group. You assign all VMs to this NSG when creating the VMs.

The following steps create the minimum Inbound NSG rule required to launch an SSH session from your local system to your VMs. The default NSG Outbound rule is to allow all traffic outbound. If you need to set additional inbound or outbound rules, see the following resources.

  1. Create an Azure NSG for the resource group.

    $ az network nsg create --name <nsg-name> --resource-group <MyResourceGroup> --location <MyAzureStackLocation>


    [stackuser@localhost ~]$ az network nsg create --name stack003nsg --resource-group azurestack-003 --location westus

  2. Show the Azure NSG for the resource group.

    $ az network nsg show --name <nsg-name> --resource-group <MyResourceGroup> --output table


    [stackuser@localhost ~] $ az network nsg show --name stack003nsg --resource-group azurestack-003 --output table
    Location    Name         ProvisioningState    ResourceGroup          ResourceGuid
    ----------  -----------  -------------------  ---------------------  ------------------------------------
    westus      stack003nsg  Succeeded            azurestack-003         xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

  3. Create an inbound NSG rule to allow SSH TCP traffic over port 22 from a trusted source (such as your system's IP address) or a range of trusted IP addresses.

    Note: Inbound is the default direction when using this command. You add --direction Outbound if you are creating an Outbound rule.

    $ az network nsg rule create --resource-group <MyResourceGroup> --nsg-name <nsg-name> --name <nsg-rule-name> --priority 100 --source-address-prefix <trusted-IP-address/range> --destination-address-prefix '*' --destination-port-range 22 --access Allow --protocol Tcp --description "<description-of-the-nsg-rule>"


    [stackuser@localhost ~] $ az network nsg rule create --resource-group -azurestack-003 --nsg-name stack003nsg --name Port_22 --priority 100 --source-address-prefix --destination-address-prefix '*' --destination-port-range 22 --access Allow --protocol Tcp --description "SSH admin access"
      "access": "Allow",
      "additionalProperties": {},
      "description": "SSH admin access",
      "destinationAddressPrefix": "*",
      "destinationPortRange": "22",
      "direction": "Inbound",
      "etag": "W/\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"",
      "id": "/subscriptions/..../..../..../..../..../..../stack003nsg/securityRules/Inbound",
      "name": "Inbound",
      "priority": 100,
      "protocol": "Tcp",
      "provisioningState": "Succeeded",
      "resourceGroup": "azurestack-003",
      "sourceAddressPrefix": "",
      "sourcePortRange": "*"

  4. Verify that the network security group rule(s) are correct. Add --output table if you do not want json output.

    $ az network nsg rule list --resource-group <MyResourceGroup> --nsg-name <nsg-name>


    [stackuser@localhost ~] $ az network nsg rule list --resource-group azurestack-003 --nsg-name stack003nsg
        "access": "Allow",
        "additionalProperties": {},
          "description": "SSH admin access",
          "destinationAddressPrefix": "*",
          "destinationPortRange": "22",
          "direction": "Inbound",
          "priority": 100,
          "protocol": "Tcp",
          "provisioningState": "Succeeded",
          "resourceGroup": "azurestack-003",
          "sourceAddressPrefix": "",
          "sourcePortRange": "*"

Create a base RHEL 7 VM using virt-manager

Note the following configuration settings are currently required for Azure Stack VMs.

Setting Requirement
ssh ssh must be enabled to provide remote access to your Azure VMs.
dhcp The primary virtual adapter should be configured for dhcp (IPv4 only).
Swap Space Do not create a dedicated swap file or swap partition. Swap space is configured using the Windows Azure Linux Agent (WALinuxAgent).
NIC Choose virtio device for the primary virtual network adapter.
encryption Do not use full disk encryption for the operating system disk. Red Hat does not currently support operating system disk encryption for RHEL VMs in Azure Stack. Data disks can be encrypted.

Complete the following steps to create the VM.

  1. Download the latest version of Red Hat Enterprise Linux from the Red Hat Customer Portal. The Red Hat Enterprise Linux KVM Guest Image is recommended.

    Note: RHEL 7.1 is the earliest version of RHEL supported in Azure Stack.

  2. Move the image to /var/lib/libvirt/images.

  3. Create a new VM using virt-manager. Note the following when creating the VM.

    • Import an existing disk image and select the downloaded qcow2 file.
    • Accept or change the memory and CPU settings to your application requirements.
    • Select the Customize configuration before install check box.
    • On the custom configuration dialog box, make sure that virtio is set as the NIC Device model, and then begin installation.
    • The VM may hang momentarily at the IPV6 eth0 line when booting up. This is normal at this point in the installation.

      Select virtio and Begin Installation

    For detailed virt-manager instructions, see Create the RHEL VM from a RHEL KVM Guest Image.

  4. Shut down the VM when you see the login prompt.

  5. From your RHEL system, set up root access to the VM. Use virt-customize to generate a root password for the VM.

    # virt-customize -a <guest-image-path> --root-password password:<password>


    # virt-customize -a /var/lib/libvirt/images/rhel-server-7.x-update-4-x86_64-kvm.qcow2 --root-password password:<password>
    [   0.0] Examining the guest ...
    [ 103.0] Setting a random seed
    [ 103.0] Setting passwords
    [ 112.0] Finishing off

  6. Verify root access by starting the VM and logging in as root.

Install Hyper-V device drivers (if not present)

Microsoft provides network and storage device drivers as part of their Linux Integration Services for the Hyper-V package. Hyper-V device drivers may need to be installed on the RHEL VM prior to importing it to Microsoft Azure.

Use the lsinitrd | grep hv command to verify that the drivers are installed. If they are not installed, complete the following steps to manually configure the Hyper-V device drivers.

  1. On the RHEL VM, add the driver parameters to the /etc/dracut.conf file. Note the spaces before and after the quotes.

    add_drivers+=" hv_vmbus "
    add_drivers+=" hv_netvsc "
    add_drivers+=" hv_storvsc "

  2. Regenerate the initramfs image.

    # dracut -f -v

  3. Verify the configuration changes.

    # lsinitrd | grep hv

Configure the image for Azure Stack

Complete the following steps to configure the image.

  1. Stop and remove cloud-init. Azure Stack VMs use the WALinuxAgent for provisioning, along with managing Azure extensions.

    # systemctl stop cloud-init
    # yum remove cloud-init

  2. Edit the /etc/ssh/sshd_config file and enable password authentication.

    PasswordAuthentication yes

  3. Edit /etc/sysconfig/network-scripts/ifcfg-eth0 so it matches the following list of configuration details.


  4. Remove any persistent network device rules.

    # rm -f /etc/udev/rules.d/70-persistent-net.rules
    # rm -f /etc/udev/rules.d/75-persistent-net-generator.rules

  5. Set the network service to start automatically.

    # chkconfig network on

  6. Set ssh to start automatically.

    # systemctl enable sshd
    # systemctl is-enabled sshd
    # systemctl restart sshd

  7. Add crashkernel=256M to the start of the GRUB_CMDLINE_LINUX line in the /etc/default/grub file. If crashkernel=auto is present, change this entry to crashkernel=256M.

    Add the following options to the end of the GRUB_CMDLINE_LINUX line.


    Remove the following options, if present.


  8. Regenerate the grub.cfg file.

    # grub2-mkconfig -o /boot/grub2/grub.cfg

  9. Register the VM with Red Hat Subscription Manager.

    # subscription-manager register --username <MyUsername> --password <password>

  10. Attach the subscription to the Red Hat Enterprise Linux 7 Server repository.

    # subscription-manager attach --pool=<POOL_ID>

  11. Enable the RHEL Extras repository.

    # subscription-manager repos --enable rhel-7-server-extras-rpms

  12. Install the Windows Azure Linux Agent (WALinuxAgent).

    # yum install WALinuxAgent
    # systemctl enable waagent.service

  13. Edit the following lines in the /etc/waagent.conf file. Set swap space for whatever is appropriate for the nodes.


  14. Unregister the VM.

    # subscription-manager unregister

  15. Deprovision the VM.

    # waagent -deprovision -force

  16. Clean the shell history and shut down the VM.

    # export HISTSIZE=0
    # poweroff

Convert the RHEL image to VHD format

Refer to Convert the RHEL Image to VHD for steps to convert the image to VHD. Return to this article when the image is converted.

Upload the image and create the Azure Stack VM

Complete the following steps to create the RHEL VM in Azure Stack.

Note: To complete this procedure, you need the resource names you set up in Create Azure resources.

  1. Upload the VHD image file.

    $ az storage blob upload --account-name <MyStorageAccount> --container-name <MyContainer> --type page --file <path-to-local-vhd> --name <image-name>.vhd


    [stackuser@localhost ~]$ az storage blob upload --account-name account003 --container-name storagecontainer003 --type page --file rhelserver75.vhd -n rhel75gold.vhd
    Finished[#############################################################]  100.0000%

  2. Get the URL for the VHD image file. Use the URL in the next step.

    $ az storage blob url --account-name <MyStorageAccount> --container-name <MyContainer> --name <image-name>.vhd


    [stackuser@localhost]$ az storage blob url --account-name account003 --container-name storagecontainer003 --name rhel75gold.vhd

  3. Create the RHEL 7 Azure VM in Azure Stack. The example uses the VM size Standard_A2. Refer to Virtual machine sizes supported in Azure Stack for higher-capacity options.

    $ az vm create --resource-group <MyResourceGroup> --storage-account <MyStorageAccount> --location <MyAzureStackLocation> --name <vm-name> --vnet-name <MyVnet> --subnet <MySubnet> --nsg <network-security-group> --size Standard_A2 --image "<storage-blob-url>" --os-type linux --use-unmanaged-disk --admin-username <MyAdminName> --authentication-type password --admin-password **********


    [stackuser@localhost ~] $ az vm create --resource-group azurestack-003 --storage-account account003 --location westus --name rhel75vm001 --vnet-name stack003vnet --subnet stack003subnet --nsg stack003nsg --size Standard_A2 --image "" --os-type linux --use-unmanaged-disk --admin-username stackuser --authentication-type password --admin-password Password12345!

    You have created resources and a RHEL VM in Azure Stack.

    Note: You can repeat this step for each RHEL VM you want to create. Change the VM name and simple operating system disk name for each VM created.


Hi Jonathan,

These instructions were written as a proof-of-concept for a manual installation/configuration deployment path for Azure Stack. These instructions have not been fully tested and are not supported by Red Hat support engineering. You can certainly use the instructions in a test Azure Stack environment. However, a fully supported deployment path for Azure Stack is in development. When this new RHEL on Azure Stack project is completed, these instructions will be revised with the supported path to Azure Stack.