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

Microsoft Purview: Data Lifecycle Management- Azure PST Import

Azure PST Import enables Microsoft 365 admins to import PST files from Azure Blob Storage into Exchange Online mailboxes using PowerShell. The...

13 hours ago

April Patches for Azure DevOps Server

We are releasing patches for our self‑hosted product, Azure DevOps Server. We strongly recommend that all customers remain on the latest, most...

2 days ago

Integration Testing Azure Functions with Reqnroll and C#, Part 5 - Using Corvus.Testing.ReqnRoll in a build pipeline

If you use Azure Functions on a regular basis, you'll likely have grappled with the challenge of testing them. In the final post in this serie...

5 days ago

Integration Testing Azure Functions with Reqnroll and C#, Part 4 - Controlling your functions with additional configuration

If you use Azure Functions on a regular basis, you'll likely have grappled with the challenge of testing them. In the fourth of this series of...

5 days ago

Integration Testing Azure Functions with Reqnroll and C#, Part 3 - Using hooks to start Functions

If you use Azure Functions on a regular basis, you'll likely have grappled with the challenge of testing them. In the third of a series of pos...

5 days ago

Integration Testing Azure Functions with Reqnroll and C#, Part 2 - Using step bindings to start Functions

If you use Azure Functions on a regular basis, you'll likely have grappled with the challenge of testing them. In the second of a series of po...

5 days ago

Integration Testing Azure Functions with Reqnroll and C#, Part 1 - Introduction

If you use Azure Functions on a regular basis, you'll likely have grappled with the challenge of testing them. In the first of a series of pos...

5 days ago
Stay up to date with latest Microsoft Dynamics 365 and Power Platform news!
* Yes, I agree to the privacy policy