Use Azure Files with Linux

Azure Files is Microsoft's easy to use cloud file system. Azure file shares can be mounted in Linux distributions using the SMB kernel client. This article shows two ways to mount an Azure file share: on-demand with the mount command and on-boot by creating an entry in /etc/fstab.

The recommended way to mount an Azure file share on Linux is using SMB 3.0. By default, Azure Files requires encryption in transit, which is only supported by SMB 3.0. Azure Files also supports SMB 2.1, which does not support encryption in transit, but you may not mount Azure file shares with SMB 2.1 from another Azure region or on-premises for security reasons. Unless your application specifically requires SMB 2.1, there is little reason to use it since most popular, recently released Linux distributions support SMB 3.0:

Linux distribution SMB 2.1
(Mounts on VMs within same Azure region)
SMB 3.0
(Mounts from on premises and cross-region)
Ubuntu 14.04+ 16.04+
Red Hat Enterprise Linux (RHEL) 7+ 7.5+
CentOS 7+ 7.5+
Debian 8+ 10+
openSUSE 13.2+ 42.3+
SUSE Linux Enterprise Server 12+ 12 SP2+

If you're using a Linux distribution not listed in the above table, you can check to see if your Linux distribution supports SMB 3.0 with encryption by checking the Linux kernel version. SMB 3.0 with encryption was added to Linux kernel version 4.11. The uname command will return the version of the Linux kernel in use:

uname -r

Prerequisites

  • Ensure the cifs-utils package is installed.
    The cifs-utils package can be installed using the package manager on the Linux distribution of your choice.

    On Ubuntu and Debian-based distributions, use the apt package manager:

    sudo apt update
    sudo apt install cifs-utils
    

    On Fedora, Red Hat Enterprise Linux 8+, and CentOS 8 +, use the dnf package manager:

    sudo dnf install cifs-utils
    

    On older versions of Red Hat Enterprise Linux and CentOS, use the yum package manager:

    sudo yum install cifs-utils 
    

    On openSUSE, use the zypper package manager:

    sudo zypper install cifs-utils
    

    On other distributions, use the appropriate package manager or compile from source

  • The most recent version of the Azure Command Line Interface (CLI). For more information on how to install the Azure CLI, see Install the Azure CLI and select your operating system. If you prefer to use the Azure PowerShell module in PowerShell 6+, you may, however the instructions below are presented for the Azure CLI.

  • Ensure port 445 is open: SMB communicates over TCP port 445 - check to see if your firewall is not blocking TCP ports 445 from client machine. Replace <your-resource-group> and <your-storage-account> then run the following script:

    resourceGroupName="<your-resource-group>"
    storageAccountName="<your-storage-account>"
    
    # This command assumes you have logged in with az login
    httpEndpoint=$(az storage account show \
        --resource-group $resourceGroupName \
        --name $storageAccountName \
        --query "primaryEndpoints.file" | tr -d '"')
    smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))
    fileHost=$(echo $smbPath | tr -d "/")
    
    nc -zvw3 $fileHost 445
    

    If the connection was successful, you should see something similar to the following output:

    Connection to <your-storage-account> 445 port [tcp/microsoft-ds] succeeded!
    

    If you are unable to open up port 445 on your corporate network or are blocked from doing so by an ISP, you may use a VPN connection or ExpressRoute to work around port 445. For more information, see Networking considerations for direct Azure file share access..

Mounting Azure file share

To use an Azure file share with your Linux distribution, you must create a directory to serve as the mount point for the Azure file share. A mount point can be created anywhere on your Linux system, but it's common convention to create this under /mnt. After the mount point, you use the mount command to access the Azure file share.

You can mount the same Azure file share to multiple mount points if desired.

Mount the Azure file share on-demand with mount

  1. Create a folder for the mount point: Replace <your-resource-group>, <your-storage-account>, and <your-file-share> with the appropriate information for your environment:

    resourceGroupName="<your-resource-group>"
    storageAccountName="<your-storage-account>"
    fileShareName="<your-file-share>"
    
    mntPath="/mnt/$storageAccountName/$fileShareName"
    
    sudo mkdir -p $mntPath
    
  2. Use the mount command to mount the Azure file share. In the example below, the local Linux file and folder permissions default 0755, which means read, write, and execute for the owner (based on the file/directory Linux owner), read and execute for users in owner group, and read and execute for others on the system. You can use the uid and gid mount options to set the user ID and group ID for the mount. You can also use dir_mode and file_mode to set custom permissions as desired. For more information on how to set permissions, see UNIX numeric notation on Wikipedia.

    # This command assumes you have logged in with az login
    httpEndpoint=$(az storage account show \
        --resource-group $resourceGroupName \
        --name $storageAccountName \
        --query "primaryEndpoints.file" | tr -d '"')
    smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))$fileShareName
    
    storageAccountKey=$(az storage account keys list \
        --resource-group $resourceGroupName \
        --account-name $storageAccountName \
        --query "[0].value" | tr -d '"')
    
    sudo mount -t cifs $smbPath $mntPath -o vers=3.0,username=$storageAccountName,password=$storageAccountKey,serverino
    

    Note

    The above mount command mounts with SMB 3.0. If your Linux distribution does not support SMB 3.0 with encryption or if it only supports SMB 2.1, you may only mount from an Azure VM within the same region as the storage account. To mount your Azure file share on a Linux distribution that does not support SMB 3.0 with encryption, you will need to disable encryption in transit for the storage account.

When you are done using the Azure file share, you may use sudo umount $mntPath to unmount the share.

Create a persistent mount point for the Azure file share with /etc/fstab

  1. Create a folder for the mount point: A folder for a mount point can be created anywhere on the file system, but it's common convention to create this under /mnt. For example, the following command creates a new directory, replace <your-resource-group>, <your-storage-account>, and <your-file-share> with the appropriate information for your environment:

    resourceGroupName="<your-resource-group>"
    storageAccountName="<your-storage-account>"
    fileShareName="<your-file-share>"
    
    mntPath="/mnt/$storageAccountName/$fileShareName"
    
    sudo mkdir -p $mntPath
    
  2. Create a credential file to store the username (the storage account name) and password (the storage account key) for the file share.

    if [ ! -d "/etc/smbcredentials" ]; then
        sudo mkdir "/etc/smbcredentials"
    fi
    
    storageAccountKey=$(az storage account keys list \
        --resource-group $resourceGroupName \
        --account-name $storageAccountName \
        --query "[0].value" | tr -d '"')
    
    smbCredentialFile="/etc/smbcredentials/$storageAccountName.cred"
    if [ ! -f $smbCredentialFile ]; then
        echo "username=$storageAccountName" | sudo tee $smbCredentialFile > /dev/null
        echo "password=$storageAccountKey" | sudo tee -a $smbCredentialFile > /dev/null
    else 
        echo "The credential file $smbCredentialFile already exists, and was not modified."
    fi
    
  3. Change permissions on the credential file so only root can read or modify the password file. Since the storage account key is essentially a super-administrator password for the storage account, setting the permissions on the file such that only root can access is important so that lower privilege users cannot retrieve the storage account key.

    sudo chmod 600 $smbCredentialFile
    
  4. Use the following command to append the following line to /etc/fstab: In the example below, the local Linux file and folder permissions default 0755, which means read, write, and execute for the owner (based on the file/directory Linux owner), read and execute for users in owner group, and read and execute for others on the system. You can use the uid and gid mount options to set the user ID and group ID for the mount. You can also use dir_mode and file_mode to set custom permissions as desired. For more information on how to set permissions, see UNIX numeric notation on Wikipedia.

    # This command assumes you have logged in with az login
    httpEndpoint=$(az storage account show \
        --resource-group $resourceGroupName \
        --name $storageAccountName \
        --query "primaryEndpoints.file" | tr -d '"')
    smbPath=$(echo $httpEndpoint | cut -c7-$(expr length $httpEndpoint))$fileShareName
    
    if [ -z "$(grep $smbPath\ $mntPath /etc/fstab)" ]; then
        echo "$smbPath $mntPath cifs nofail,vers=3.0,credentials=$smbCredentialFile,serverino" | sudo tee -a /etc/fstab > /dev/null
    else
        echo "/etc/fstab was not modified to avoid conflicting entries as this Azure file share was already present. You may want to double check /etc/fstab to ensure the configuration is as desired."
    fi
    
    sudo mount -a
    

    Note

    The above mount command mounts with SMB 3.0. If your Linux distribution does not support SMB 3.0 with encryption or if it only supports SMB 2.1, you may only mount from an Azure VM within the same region as the storage account. To mount your Azure file share on a Linux distribution that does not support SMB 3.0 with encryption, you will need to disable encryption in transit for the storage account.

Using autofs to automatically mount the Azure file share(s)

  1. Ensure the autofs package is installed.

    The autofs package can be installed using the package manager on the Linux distribution of your choice.

    On Ubuntu and Debian-based distributions, use the apt package manager:

    sudo apt update
    sudo apt install autofs
    

    On Fedora, Red Hat Enterprise Linux 8+, and CentOS 8 +, use the dnf package manager:

    sudo dnf install autofs
    

    On older versions of Red Hat Enterprise Linux and CentOS, use the yum package manager:

    sudo yum install autofs 
    

    On openSUSE, use the zypper package manager:

    sudo zypper install autofs
    
  2. Create a mount point for the share(s):

     sudo mkdir /fileshares
    
  3. Crete a new custom autofs configuration file

    sudo vi /etc/auto.fileshares
    
  4. Add the following entries to /etc/auto.fileshares

    echo "$fileShareName -fstype=cifs,credentials=$smbCredentialFile :$smbPath"" > /etc/auto.fileshares
    
  5. Add the following entry to /etc/auto.master

    /fileshares /etc/auto.fileshares --timeout=60
    
  6. Restart autofs

    sudo systemctl restart autofs
    
  7. Access the folder designated for the share

    cd /fileshares/$filesharename
    

Securing Linux

In order to mount an Azure file share on Linux, port 445 must be accessible. Many organizations block port 445 because of the security risks inherent with SMB 1. SMB 1, also known as CIFS (Common Internet File System), is a legacy file system protocol included with many Linux distributions. SMB 1 is an outdated, inefficient, and most importantly insecure protocol. The good news is that Azure Files does not support SMB 1, and starting with Linux kernel version 4.18, Linux makes it possible to disable SMB 1. We always strongly recommend disabling the SMB 1 on your Linux clients before using SMB file shares in production.

Starting with Linux kernel 4.18, the SMB kernel module, called cifs for legacy reasons, exposes a new module parameter (often referred to as parm by various external documentations), called disable_legacy_dialects. Although introduced in Linux kernel 4.18, some vendors have backported this change to older kernels that they support. For convenience, the following table details the availability of this module parameter on common Linux distributions.

Distribution Can disable SMB 1
Ubuntu 14.04-16.04 No
Ubuntu 18.04 Yes
Ubuntu 19.04+ Yes
Debian 8-9 No
Debian 10+ Yes
Fedora 29+ Yes
CentOS 7 No
CentOS 8+ Yes
Red Hat Enterprise Linux 6.x-7.x No
Red Hat Enterprise Linux 8+ Yes
openSUSE Leap 15.0 No
openSUSE Leap 15.1+ Yes
openSUSE Tumbleweed Yes
SUSE Linux Enterprise 11.x-12.x No
SUSE Linux Enterprise 15 No
SUSE Linux Enterprise 15.1 No

You can check to see if your Linux distribution supports the disable_legacy_dialects module parameter via the following command.

sudo modinfo -p cifs | grep disable_legacy_dialects

This command should output the following message:

disable_legacy_dialects: To improve security it may be helpful to restrict the ability to override the default dialects (SMB2.1, SMB3 and SMB3.02) on mount with old dialects (CIFS/SMB1 and SMB2) since vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker and less secure. Default: n/N/0 (bool)

Before disabling SMB 1, you must check to make sure that the SMB module is not currently loaded on your system (this happens automatically if you have mounted an SMB share). You can do this with the following command, which should output nothing if SMB is not loaded:

lsmod | grep cifs

To unload the module, first unmount all SMB shares (using the umount command as described above). You can identify all the mounted SMB shares on your system with the following command:

mount | grep cifs

Once you have unmounted all SMB file shares, it's safe to unload the module. You can do this with the modprobe command:

sudo modprobe -r cifs

You can manually load the module with SMB 1 unloaded using the modprobe command:

sudo modprobe cifs disable_legacy_dialects=Y

Finally, you can check the SMB module has been loaded with the parameter by looking at the loaded parameters in /sys/module/cifs/parameters:

cat /sys/module/cifs/parameters/disable_legacy_dialects

To persistently disable SMB 1 on Ubuntu and Debian-based distributions, you must create a new file (if you don't already have custom options for other modules) called /etc/modprobe.d/local.conf with the setting. You can do this with the following command:

echo "options cifs disable_legacy_dialects=Y" | sudo tee -a /etc/modprobe.d/local.conf > /dev/null

You can verify that this has worked by loading the SMB module:

sudo modprobe cifs
cat /sys/module/cifs/parameters/disable_legacy_dialects

Next steps

See these links for more information about Azure Files: