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:
- storage account is the storage account used for persisting data, and contains the Azure Files share
- 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.
- Choose the subscription you want to create the sftp service in
- Create a new Resource Group
- It will automatically create a storage account
- Give a File Share Name
- Provide a SFTP user name
- Provide a SFTP password
- Wait till the deployment is done successfully
- Click on the container sftp-group
- Copy the FQDN from the container group
- Download WinScp from WinSCP :: Official Site :: Download
- Provide Hostname : FQDN for ACI; Port Number: 22; User Name and Password
- Click on Login
13. Drag and drop a file from the left side to the Right side.
14. Now, go to the Storage Account and Navigate to File share. The file appears on the file share.
Published on:
Learn more