Loading...

Enable SFTP on Azure File Share using ARM Template and upload files using WinScp

Enable SFTP on Azure File Share using ARM Template and upload files using WinScp

SFTP is a very widely used protocol which many organizations use today for transferring files within their organization or across organizations. Creating a VM based SFTP is costly and high-maintenance. ACI service is very inexpensive and requires very little maintenance, while data is stored in Azure Files which is a fully managed SMB service in cloud.

This template demonstrates an creating a SFTP server using Azure Container Instances (ACI). The template generates two resources:

  1. storage account is the storage account used for persisting data, and contains the Azure Files share
  2. sftp-group is a container group with a mounted Azure File Share. The Azure File Share will provide persistent storage after the container is terminated.

 

ARM Template for creation of SFTP with New Azure File Share and a new Azure Storage account

Resources.json

{

  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

  "contentVersion": "1.0.0.0",

  "metadata": {

    "_generator": {

      "name": "bicep",

      "version": "0.4.63.48766",

      "templateHash": "17013458610905703770"

    }

  },

  "parameters": {

    "storageAccountType": {

      "type": "string",

      "defaultValue": "Standard_LRS",

      "metadata": {

        "description": "Storage account type"

      },

      "allowedValues": [

        "Standard_LRS",

        "Standard_ZRS",

        "Standard_GRS"

      ]

    },

    "storageAccountPrefix": {

      "type": "string",

      "defaultValue": "sftpstg",

      "metadata": {

        "description": "Prefix for new storage account"

      }

    },

    "fileShareName": {

      "type": "string",

      "defaultValue": "sftpfileshare",

      "metadata": {

        "description": "Name of file share to be created"

      }

    },

    "sftpUser": {

      "type": "string",

      "defaultValue": "sftp",

      "metadata": {

        "description": "Username to use for SFTP access"

      }

    },

    "sftpPassword": {

      "type": "securestring",

      "metadata": {

        "description": "Password to use for SFTP access"

      }

    },

    "location": {

      "type": "string",

      "defaultValue": "[resourceGroup().location]",

      "metadata": {

        "description": "Primary location for resources"

      }

    },

    "containerGroupDNSLabel": {

      "type": "string",

      "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]",

      "metadata": {

        "description": "DNS label for container group"

      }

    }

  },

  "functions": [],

  "variables": {

    "sftpContainerName": "sftp",

    "sftpContainerGroupName": "sftp-group",

    "sftpContainerImage": "atmoz/sftp:debian",

    "sftpEnvVariable": "[format('{0}:{1}:1001', parameters('sftpUser'), parameters('sftpPassword'))]",

    "storageAccountName": "[take(toLower(format('{0}{1}', parameters('storageAccountPrefix'), uniqueString(resourceGroup().id))), 24)]"

  },

  "resources": [

    {

      "type": "Microsoft.Storage/storageAccounts",

      "apiVersion": "2019-06-01",

      "name": "[variables('storageAccountName')]",

      "location": "[parameters('location')]",

      "kind": "StorageV2",

      "sku": {

        "name": "[parameters('storageAccountType')]"

      }

    },

    {

      "type": "Microsoft.Storage/storageAccounts/fileServices/shares",

      "apiVersion": "2019-06-01",

      "name": "[toLower(format('{0}/default/{1}', variables('storageAccountName'), parameters('fileShareName')))]",

      "dependsOn": [

        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"

      ]

    },

    {

      "type": "Microsoft.ContainerInstance/containerGroups",

      "apiVersion": "2019-12-01",

      "name": "[variables('sftpContainerGroupName')]",

      "location": "[parameters('location')]",

      "properties": {

        "containers": [

          {

            "name": "[variables('sftpContainerName')]",

            "properties": {

              "image": "[variables('sftpContainerImage')]",

              "environmentVariables": [

                {

                  "name": "SFTP_USERS",

                  "secureValue": "[variables('sftpEnvVariable')]"

                }

              ],

              "resources": {

                "requests": {

                  "cpu": 1,

                  "memoryInGB": 1

                }

              },

              "ports": [

                {

                  "port": 22,

                  "protocol": "TCP"

                }

              ],

              "volumeMounts": [

                {

                  "mountPath": "[format('/home/{0}/upload', parameters('sftpUser'))]",

                  "name": "sftpvolume",

                  "readOnly": false

                }

              ]

            }

          }

        ],

        "osType": "Linux",

        "ipAddress": {

          "type": "Public",

          "ports": [

            {

              "port": 22,

              "protocol": "TCP"

            }

          ],

          "dnsNameLabel": "[parameters('containerGroupDNSLabel')]"

        },

        "restartPolicy": "OnFailure",

        "volumes": [

          {

            "name": "sftpvolume",

            "azureFile": {

              "readOnly": false,

              "shareName": "[parameters('fileShareName')]",

              "storageAccountName": "[variables('storageAccountName')]",

              "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]"

            }

          }

        ]

      },

      "dependsOn": [

        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"

      ]

    }

  ],

  "outputs": {

    "containerDNSLabel": {

      "type": "string",

      "value": "[format('{0}.{1}.azurecontainer.io', reference(resourceId('Microsoft.ContainerInstance/containerGroups', variables('sftpContainerGroupName'))).ipAddress.dnsNameLabel, reference(resourceId('Microsoft.ContainerInstance/containerGroups', variables('sftpContainerGroupName')), '2019-12-01', 'full').location)]"

    }

  }

}

 

Parameters.json

{

  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",

  "contentVersion": "1.0.0.0",

  "parameters": {

    "storageAccountType": {

      "value": "Standard_LRS"

    },

    "storageAccountPrefix": {

      "value": "sftpstg"

    },

    "fileShareName": {

      "value": "sftpfileshare"

    },

    "sftpUser": {

      "value": "sftp"

    },

    "sftpPassword": {

      "value": null

    },

    "location": {

      "value": "[resourceGroup().location]"

    },

    "containerGroupDNSLabel": {

      "value": "[uniqueString(resourceGroup().id, deployment().name)]"

    }

  }

}

 

 

ARM Template to Enable SFTP for an Existing Azure File Share in Azure Storage account

Resources.json

{

  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

  "contentVersion": "1.0.0.0",

  "metadata": {

    "_generator": {

      "name": "bicep",

      "version": "0.4.63.48766",

      "templateHash": "16190402726175806996"

    }

  },

  "parameters": {

    "existingStorageAccountResourceGroupName": {

      "type": "string",

      "metadata": {

        "description": "Resource group for existing storage account"

      }

    },

    "existingStorageAccountName": {

      "type": "string",

      "metadata": {

        "description": "Name of existing storage account"

      }

    },

    "existingFileShareName": {

      "type": "string",

      "metadata": {

        "description": "Name of existing file share to be mounted"

      }

    },

    "sftpUser": {

      "type": "string",

      "defaultValue": "sftp",

      "metadata": {

        "description": "Username to use for SFTP access"

      }

    },

    "sftpPassword": {

      "type": "securestring",

      "metadata": {

        "description": "Password to use for SFTP access"

      }

    },

    "location": {

      "type": "string",

      "defaultValue": "[resourceGroup().location]",

      "metadata": {

        "description": "Primary location for resources"

      }

    },

    "containerGroupDNSLabel": {

      "type": "string",

      "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]",

      "metadata": {

        "description": "DNS label for container group"

      }

    }

  },

  "functions": [],

  "variables": {

    "sftpContainerName": "sftp",

    "sftpContainerGroupName": "sftp-group",

    "sftpContainerImage": "atmoz/sftp:debian",

    "sftpEnvVariable": "[format('{0}:{1}:1001', parameters('sftpUser'), parameters('sftpPassword'))]"

  },

  "resources": [

    {

      "type": "Microsoft.ContainerInstance/containerGroups",

      "apiVersion": "2019-12-01",

      "name": "[variables('sftpContainerGroupName')]",

      "location": "[parameters('location')]",

      "properties": {

        "containers": [

          {

            "name": "[variables('sftpContainerName')]",

            "properties": {

              "image": "[variables('sftpContainerImage')]",

              "environmentVariables": [

                {

                  "name": "SFTP_USERS",

                  "secureValue": "[variables('sftpEnvVariable')]"

                }

              ],

              "resources": {

                "requests": {

                  "cpu": 1,

                  "memoryInGB": 1

                }

              },

              "ports": [

                {

                  "port": 22,

                  "protocol": "TCP"

                }

              ],

              "volumeMounts": [

                {

                  "mountPath": "[format('/home/{0}/upload', parameters('sftpUser'))]",

                  "name": "sftpvolume",

                  "readOnly": false

                }

              ]

            }

          }

        ],

        "osType": "Linux",

        "ipAddress": {

          "type": "Public",

          "ports": [

            {

              "port": 22,

              "protocol": "TCP"

            }

          ],

          "dnsNameLabel": "[parameters('containerGroupDNSLabel')]"

        },

        "restartPolicy": "OnFailure",

        "volumes": [

          {

            "name": "sftpvolume",

            "azureFile": {

              "readOnly": false,

              "shareName": "[parameters('existingFileShareName')]",

              "storageAccountName": "[parameters('existingStorageAccountName')]",

              "storageAccountKey": "[listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('existingStorageAccountResourceGroupName')), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').keys[0].value]"

            }

          }

        ]

      }

    }

  ],

  "outputs": {

    "containerDNSLabel": {

      "type": "string",

      "value": "[format('{0}.{1}.azurecontainer.io', reference(resourceId('Microsoft.ContainerInstance/containerGroups', variables('sftpContainerGroupName'))).ipAddress.dnsNameLabel, reference(resourceId('Microsoft.ContainerInstance/containerGroups', variables('sftpContainerGroupName')), '2019-12-01', 'full').location)]"

    }

  }

}

 

Parameters.json

{

  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",

  "contentVersion": "1.0.0.0",

  "parameters": {

    "existingStorageAccountResourceGroupName": {

      "value": null

    },

    "existingStorageAccountName": {

      "value": null

    },

    "existingFileShareName": {

      "value": null

    },

    "sftpUser": {

      "value": "sftp"

    },

    "sftpPassword": {

      "value": null

    },

    "location": {

      "value": "[resourceGroup().location]"

    },

    "containerGroupDNSLabel": {

      "value": "[uniqueString(resourceGroup().id, deployment().name)]"

    }

  }

}

 

Deploy the ARM Templates using PowerShell or Azure CLI or Custom Template deployment using Azure Portal.

  1. Choose the subscription you want to create the sftp service in
  2. Create a new Resource Group
  3. It will automatically create a storage account
  4. Give a File Share Name
  5. Provide a SFTP user name
  6. Provide a SFTP password
  7. Wait till the deployment is done successfully
  8. Click on the container sftp-group
  9. Copy the FQDN from the container group
  10. Download WinScp from WinSCP :: Official Site :: Download
  11. Provide Hostname : FQDN for ACI; Port Number: 22; User Name and Password
  12. Click on Login    

      Sudipta_Chakraborty_0-1666779055622.png

    13. Drag and drop a file from the left side to the Right side.    Sudipta_Chakraborty_1-1666779092579.png

   14. Now, go to the Storage Account and Navigate to File share. The file appears on the file share.

Sudipta_Chakraborty_2-1666779239538.png

 

Published on:

Learn more
Azure PaaS Blog articles
Azure PaaS Blog articles

Azure PaaS Blog articles

Share post:

Related posts

Azure Storage - TLS 1.0 and 1.1 retirement

Overview TLS 1.0 and 1.1 retirement on Azure Storage was previously announced for Nov 1st, 2024, and it was postponed recently to 1 year later...

1 year ago

Efficient Management of Append and Page Blobs Using Azure Storage Actions

  Overview In Azure Storage, Blob Lifecycle Management (BLM) allows you to automate the management of your data based on rules defined by...

1 year ago

[Azure AI Search] Internal Server Error when creating CMK encrypted objects

Scenario Customers follow the Microsoft doc to create CMK encrypted objects (data source, index etc.), but get the 500 Internal Serv...

1 year ago

Optimizing Azure Table Storage: Automated Data Cleanup using a PowerShell script with Azure Automate

Scenario This blog’s aim is to manage Table Storage data efficiently. Imagine you have a large Azure Table Storage that accumulates logs from ...

1 year ago

Optimizing Azure Table Storage: Automated Data Clean-up using a PowerShell script with Azure Automat

Scenario This blog’s aim is to manage Table Storage data efficiently. Imagine you have a large Azure Table Storage that accumulates logs from ...

1 year ago

Restoring Soft-Deleted Blobs with multithreading in Azure Storage Using C#

Blob soft delete is an essential feature that safeguards your data against accidental deletions or overwrites. By retaining deleted data for a...

1 year ago

Performing simple Azure Table Storage REST API operations using curl command.

The blog provides guidance to perform simple Table Storage REST API operations such as Create table, Delete Table, Insert entity, Delete entit...

1 year ago

Bulk delete all the old jobs from the batch account

Deleting a Job also deletes all Tasks that are part of that Job, and all Job statistics. This also overrides the retention period for Task dat...

1 year ago

Utilizing Azure Storage and Runbooks for scheduled automated backups of Azure SQL Databases

In this article, we are going to provide detailed steps to create a scheduled Azure SQL Database backup to storage account using automation. T...

2 years ago

[Azure Service Bus] JMS messages getting dead-lettered

The article discusses a problem where numerous messages end up in the dead letter queue (DLQ) when the JMS service bus consumer connects to th...

2 years ago

Newsletter

Get the latest Dynamics 365 and Power Platform content in your inbox

A curated digest of community blogs, product news, videos, and podcasts — delivered without the noise.

Weekly updates Unsubscribe anytime Fresh community picks
We use your email only for the newsletter and you can unsubscribe at any time.
By subscribing, you agree to the privacy policy.