├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── create-aci-sftp-server-and-azure-files ├── azuredeploy.bicep ├── azuredeploy.json ├── azuredeploy.parameters.json ├── azuredeploy_cli_container.json └── metadata.json ├── create-aci-sftp-server-with-existing-azure-file-share ├── azuredeploy.bicep ├── azuredeploy.json ├── azuredeploy.parameters.json ├── azuredeploy_cli_container.json ├── metadata.json └── prereqs │ ├── prereq.azuredeploy.json │ └── prereq.azuredeploy.parameters.json └── media ├── 07d51c6830a6975b0fe1869f08378c35.png ├── 0f9a21b676c64a6de53bff3a317977f9.png ├── 1-changepassword.png ├── 2-changepassword.png ├── 27eb882cc865681917477f753c7361aa.png ├── 3-changepassword.png ├── 4-changepassword.png ├── 45f6559a0fdcd3f6e300153d13eb3fde.jpg ├── 490ad362e0903ed66eefeb06fc9b0264.png ├── 5-changepassword.png ├── b78de12062ed4a83bbe8fc3a1e916dc9.png ├── f851279263a95b834f590158154fa7db.png └── fqdn_image.PNG /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Azure SFTP Creation Template Changelog 2 | 3 | 4 | # Ben Hummerstone (2021-06-24) 5 | 6 | *Features* 7 | * Added Bicep version of template 8 | * Changed file share creation to use native ARM rather than Azure CLI 9 | 10 | *Bug Fixes* 11 | * Specified Debian version of SFTP container image rather than 'latest' 12 | 13 | *Breaking Changes* 14 | * None 15 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 6 | 7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | languages: 3 | - json 4 | products: 5 | - azure 6 | page_type: sample 7 | description: "SFTP is a widely used protocol which many organizations use for transferring files." 8 | --- 9 | 10 | # SFTP on Azure 11 | 12 | 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. 13 | 14 | ‼️ Azure now offers a fully-managed SFTP service built on top of Blob Storage that may be more suitable for your use case; have a look at the documentation here to see if it meets your requirements: https://docs.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support ‼️ 15 | 16 | ## Key Value Prop 17 | 18 | * Simple SFTP Creation 19 | * Persistent and Durable Storage 20 | * Cost efficient solution 21 | * No VM maintenance overhead 22 | * Fast to deploy 23 | 24 | ## How-To create an on-demand SFTP Server with a new Azure Files persistent storage 25 | 26 | 27 | Deploy To Azure 28 | 29 | 30 | Visualize 31 | 32 | 33 | ## How-To create an on-demand SFTP Server with an existing Azure Files persistent storage 34 | 35 | 36 | Deploy To Azure 37 | 38 | 39 | Visualize 40 | 41 | 42 | 43 | ## Overview 44 | This template demonstrates an on-demand SFTP server using Azure Container Instances ([ACI](https://docs.microsoft.com/en-us/azure/container-instances/)). The template generates two resources: 45 | 1. **storage account** is the storage account used for persisting data, and contains the Azure Files share 46 | 2. **sftp-group** is a container group with a mounted [Azure File Share](https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-create-file-share). The Azure File Share will provide persistent storage after the container is terminated. 47 | 48 | The previous version of the templates, which are stored as azuredeploy_cli_container.json files, also create the following resources: 49 | 1. **create-share-group** is a container group that acts as an [init container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) by generating the second container group and an [Azure Storage](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-overview) account (based on the [101-aci-storage-file-share template](https://github.com/Azure/azure-quickstart-templates/tree/master/101-aci-storage-file-share)) 50 | 51 | 52 | `Tags: Azure Container Instance, az-cli, sftp` 53 | 54 | ### Deployment steps - Portal 55 | 56 | Click the "Deploy to Azure" button at the beginning of this document or follow the instructions for command line deployment using the scripts in the root of this repository. 57 | 58 | Fill in the information 59 | 60 | 1. Choose the subscription you want to create the sftp service in 61 | 62 | 2. Create a new Resource Group 63 | 64 | 3. It will automatically create a storage account of specified **Redundancy** 65 | 66 | 4. Give a **File Share Name** 67 | 68 | 5. Provide a **SFTP user name** 69 | 70 | 6. Provide a **SFTP password** 71 | 72 | 7. Click on **I agree to terms and conditions above** 73 | 74 | 8. Click **Purchase** 75 | 76 | ![](media/f851279263a95b834f590158154fa7db.png) 77 | 78 | > cid:image011.png\@01D4AC19.C75D08F0 79 | 80 | Pin to the dashboard 81 | 82 | ![](media/b78de12062ed4a83bbe8fc3a1e916dc9.png) 83 | 84 | > cid:image012.png\@01D4AC19.C75D08F0 85 | 86 | ### Deployment steps - Command Line 87 | 88 | The deployment steps for the Azure CLI are as follows: 89 | 90 | 1. Create a resource group 91 | ```bash 92 | az group create --name sftp-rg --location uksouth 93 | ``` 94 | 95 | 2. Navigate to the directory and create a deployment 96 | ```bash 97 | az deployment group create --resource-group sftp-rg --template-file azuredeploy.bicep 98 | ``` 99 | 100 | 3. Check the outputs to get the container DNS label 101 | 102 | 103 | ## Usage 104 | 105 | Once deployed, connect Azure to the Filezilla client via the fully qualified domain name (FQDN) of the ACI container group named **sftp-group** and upload files. 106 | 107 | :bangbang: ACI _does not_ support static IPs for their container groups. Use the container group's FQDN for consistent network connectivity :bangbang: 108 | 109 | After connecting to **sftp-group**'s FQDN, these files should be placed into the Azure File Share. Once transfers are complete, [manually stop](https://docs.microsoft.com/bs-latn-ba/azure/container-instances/container-instances-stop-start#stop) the **sftp-group** to pause ACI's billing. The files will remain accessible. You can [manually start](https://docs.microsoft.com/bs-latn-ba/azure/container-instances/container-instances-stop-start#start) **sftp-group** and to copy more files at anytime. If you choose to delete and redeploy **sftp-group** make sure to update the FQDN connection on Filezilla since this template randomly generates the FQDN during deployment time. 110 | 111 | 1. Click on the container sftp-group 112 | 113 | ![cid:image013.png\@01D4AC19.C75D08F0](media/27eb882cc865681917477f753c7361aa.png) 114 | 115 | 2. Copy the FQDN from the container group 116 | 117 | ![cid:image014.png\@01D4AC19.C75D08F0](media/fqdn_image.PNG) 118 | 119 | 3. Open Filezilla and open File Site Manager and enter the FQDN, username and 120 | password that was originally added during creation 121 | 122 | ![cid:image015.png\@01D4AC19.C75D08F0](media/0f9a21b676c64a6de53bff3a317977f9.png) 123 | 124 | 125 | 4. Upload a file 126 | 127 | ![cid:image016.png\@01D4AC19.C75D08F0](media/07d51c6830a6975b0fe1869f08378c35.png) 128 | 129 | 130 | 5. The file appears in your file share 131 | 132 | ![cid:image017.jpg\@01D4AC19.C75D08F0](media/45f6559a0fdcd3f6e300153d13eb3fde.jpg) 133 | 134 | 135 | ### Troubleshoot - Lost Password 136 | 137 | ## Steps to Update Password 138 | Selected the resource group and go to the SFTP server. 139 | 140 | ![](media/1-changepassword.png) 141 | 142 |   143 | 144 | Click on the “ Export Template” icon. 145 | 146 |   147 | 148 | ![](media/2-changepassword.png) 149 | 150 |   151 | 152 |   153 | 154 |   155 | 156 | ![](media/3-changepassword.png) 157 | 158 |   159 | 160 |   161 | 162 | ![](media/4-changepassword.png) 163 | 164 |   165 | 166 | Under “ EnvironmentVariables” changes could be made to the username and 167 | password. 168 | 169 |   170 | 171 | ![](media/5-changepassword.png) 172 | 173 |   174 | 175 | Once changes are done redeploy it again.  176 | 177 | 178 | 179 | ### Notes 180 | 181 | Azure Container Instances is available in selected [locations](https://docs.microsoft.com/en-us/azure/container-instances/container-instances-quotas#region-availability). Please use one of the available location for Azure Container Instances resource. 182 | The container image used by this template is hosted on [Docker Hub](https://hub.docker.com/r/atmoz/sftp). It is not affiliated with Microsoft in any way, and usage is at your own risk. 183 | 184 | ### Support 185 | 186 | This is a sample provided for customer guidance on an end-to-end deployment. This template is open source and contributions are welcome. While there is full support available for Azure Container Instances and Azure Files, this template does not come under the Azure Support's scope. 187 | -------------------------------------------------------------------------------- /create-aci-sftp-server-and-azure-files/azuredeploy.bicep: -------------------------------------------------------------------------------- 1 | @allowed([ 2 | 'Standard_LRS' 3 | 'Standard_ZRS' 4 | 'Standard_GRS' 5 | ]) 6 | @description('Storage account type') 7 | param storageAccountType string = 'Standard_LRS' 8 | 9 | @description('Prefix for new storage account') 10 | param storageAccountPrefix string = 'sftpstg' 11 | 12 | @description('Name of file share to be created') 13 | param fileShareName string = 'sftpfileshare' 14 | 15 | @description('Username to use for SFTP access') 16 | param sftpUser string = 'sftp' 17 | 18 | @secure() 19 | @description('Password to use for SFTP access') 20 | param sftpPassword string 21 | 22 | @description('Primary location for resources') 23 | param location string = resourceGroup().location 24 | 25 | @description('DNS label for container group') 26 | param containerGroupDNSLabel string = uniqueString(resourceGroup().id, deployment().name) 27 | 28 | var sftpContainerName = 'sftp' 29 | var sftpContainerGroupName = 'sftp-group' 30 | var sftpContainerImage = 'atmoz/sftp:debian' 31 | var sftpEnvVariable = '${sftpUser}:${sftpPassword}:1001' 32 | var storageAccountName = take(toLower('${storageAccountPrefix}${uniqueString(resourceGroup().id)}'), 24) //storage account must be =< 24 characters 33 | 34 | resource stgacct 'Microsoft.Storage/storageAccounts@2019-06-01' = { 35 | name: storageAccountName 36 | location: location 37 | kind: 'StorageV2' 38 | sku:{ 39 | name: storageAccountType 40 | } 41 | } 42 | 43 | resource fileshare 'Microsoft.Storage/storageAccounts/fileServices/shares@2019-06-01' = { 44 | name: toLower('${stgacct.name}/default/${fileShareName}') 45 | } 46 | 47 | resource containergroup 'Microsoft.ContainerInstance/containerGroups@2019-12-01' = { 48 | name: sftpContainerGroupName 49 | location: location 50 | properties: { 51 | containers: [ 52 | { 53 | name: sftpContainerName 54 | properties: { 55 | image: sftpContainerImage 56 | environmentVariables: [ 57 | { 58 | name: 'SFTP_USERS' 59 | secureValue: sftpEnvVariable 60 | } 61 | ] 62 | resources: { 63 | requests: { 64 | cpu: 1 65 | memoryInGB: 1 66 | } 67 | } 68 | ports:[ 69 | { 70 | port: 22 71 | protocol: 'TCP' 72 | } 73 | ] 74 | volumeMounts: [ 75 | { 76 | mountPath: '/home/${sftpUser}/upload' 77 | name: 'sftpvolume' 78 | readOnly: false 79 | } 80 | ] 81 | } 82 | } 83 | ] 84 | 85 | osType:'Linux' 86 | ipAddress: { 87 | type: 'Public' 88 | ports:[ 89 | { 90 | port: 22 91 | protocol:'TCP' 92 | } 93 | ] 94 | dnsNameLabel: containerGroupDNSLabel 95 | } 96 | restartPolicy: 'OnFailure' 97 | volumes: [ 98 | { 99 | name: 'sftpvolume' 100 | azureFile:{ 101 | readOnly: false 102 | shareName: fileShareName 103 | storageAccountName: stgacct.name 104 | storageAccountKey: listKeys(stgacct.id, '2019-06-01').keys[0].value 105 | } 106 | } 107 | ] 108 | } 109 | } 110 | 111 | output containerDNSLabel string = '${containergroup.properties.ipAddress.dnsNameLabel}.${containergroup.location}.azurecontainer.io' 112 | -------------------------------------------------------------------------------- /create-aci-sftp-server-and-azure-files/azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "metadata": { 5 | "_generator": { 6 | "name": "bicep", 7 | "version": "0.4.63.48766", 8 | "templateHash": "17013458610905703770" 9 | } 10 | }, 11 | "parameters": { 12 | "storageAccountType": { 13 | "type": "string", 14 | "defaultValue": "Standard_LRS", 15 | "metadata": { 16 | "description": "Storage account type" 17 | }, 18 | "allowedValues": [ 19 | "Standard_LRS", 20 | "Standard_ZRS", 21 | "Standard_GRS" 22 | ] 23 | }, 24 | "storageAccountPrefix": { 25 | "type": "string", 26 | "defaultValue": "sftpstg", 27 | "metadata": { 28 | "description": "Prefix for new storage account" 29 | } 30 | }, 31 | "fileShareName": { 32 | "type": "string", 33 | "defaultValue": "sftpfileshare", 34 | "metadata": { 35 | "description": "Name of file share to be created" 36 | } 37 | }, 38 | "sftpUser": { 39 | "type": "string", 40 | "defaultValue": "sftp", 41 | "metadata": { 42 | "description": "Username to use for SFTP access" 43 | } 44 | }, 45 | "sftpPassword": { 46 | "type": "securestring", 47 | "metadata": { 48 | "description": "Password to use for SFTP access" 49 | } 50 | }, 51 | "location": { 52 | "type": "string", 53 | "defaultValue": "[resourceGroup().location]", 54 | "metadata": { 55 | "description": "Primary location for resources" 56 | } 57 | }, 58 | "containerGroupDNSLabel": { 59 | "type": "string", 60 | "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]", 61 | "metadata": { 62 | "description": "DNS label for container group" 63 | } 64 | } 65 | }, 66 | "functions": [], 67 | "variables": { 68 | "sftpContainerName": "sftp", 69 | "sftpContainerGroupName": "sftp-group", 70 | "sftpContainerImage": "atmoz/sftp:debian", 71 | "sftpEnvVariable": "[format('{0}:{1}:1001', parameters('sftpUser'), parameters('sftpPassword'))]", 72 | "storageAccountName": "[take(toLower(format('{0}{1}', parameters('storageAccountPrefix'), uniqueString(resourceGroup().id))), 24)]" 73 | }, 74 | "resources": [ 75 | { 76 | "type": "Microsoft.Storage/storageAccounts", 77 | "apiVersion": "2019-06-01", 78 | "name": "[variables('storageAccountName')]", 79 | "location": "[parameters('location')]", 80 | "kind": "StorageV2", 81 | "sku": { 82 | "name": "[parameters('storageAccountType')]" 83 | } 84 | }, 85 | { 86 | "type": "Microsoft.Storage/storageAccounts/fileServices/shares", 87 | "apiVersion": "2019-06-01", 88 | "name": "[toLower(format('{0}/default/{1}', variables('storageAccountName'), parameters('fileShareName')))]", 89 | "dependsOn": [ 90 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 91 | ] 92 | }, 93 | { 94 | "type": "Microsoft.ContainerInstance/containerGroups", 95 | "apiVersion": "2019-12-01", 96 | "name": "[variables('sftpContainerGroupName')]", 97 | "location": "[parameters('location')]", 98 | "properties": { 99 | "containers": [ 100 | { 101 | "name": "[variables('sftpContainerName')]", 102 | "properties": { 103 | "image": "[variables('sftpContainerImage')]", 104 | "environmentVariables": [ 105 | { 106 | "name": "SFTP_USERS", 107 | "secureValue": "[variables('sftpEnvVariable')]" 108 | } 109 | ], 110 | "resources": { 111 | "requests": { 112 | "cpu": 1, 113 | "memoryInGB": 1 114 | } 115 | }, 116 | "ports": [ 117 | { 118 | "port": 22, 119 | "protocol": "TCP" 120 | } 121 | ], 122 | "volumeMounts": [ 123 | { 124 | "mountPath": "[format('/home/{0}/upload', parameters('sftpUser'))]", 125 | "name": "sftpvolume", 126 | "readOnly": false 127 | } 128 | ] 129 | } 130 | } 131 | ], 132 | "osType": "Linux", 133 | "ipAddress": { 134 | "type": "Public", 135 | "ports": [ 136 | { 137 | "port": 22, 138 | "protocol": "TCP" 139 | } 140 | ], 141 | "dnsNameLabel": "[parameters('containerGroupDNSLabel')]" 142 | }, 143 | "restartPolicy": "OnFailure", 144 | "volumes": [ 145 | { 146 | "name": "sftpvolume", 147 | "azureFile": { 148 | "readOnly": false, 149 | "shareName": "[parameters('fileShareName')]", 150 | "storageAccountName": "[variables('storageAccountName')]", 151 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]" 152 | } 153 | } 154 | ] 155 | }, 156 | "dependsOn": [ 157 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" 158 | ] 159 | } 160 | ], 161 | "outputs": { 162 | "containerDNSLabel": { 163 | "type": "string", 164 | "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)]" 165 | } 166 | } 167 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-and-azure-files/azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "sftpUser": { 6 | "value": "GEN-UNIQUE-6" 7 | }, 8 | "sftpPassword": { 9 | "value": "GEN-PASSWORD" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-and-azure-files/azuredeploy_cli_container.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "storageAccountType": { 6 | "type": "string", 7 | "defaultValue": "Standard_LRS", 8 | "allowedValues": [ 9 | "Standard_LRS", 10 | "Standard_GRS" 11 | ], 12 | "metadata": { 13 | "description": "Storage account type" 14 | } 15 | }, 16 | "fileShareName": { 17 | "type": "string", 18 | "defaultValue": "sftpfileshare", 19 | "metadata": { 20 | "description": "Name of file share to be created" 21 | } 22 | }, 23 | "sftpUser": { 24 | "type": "string", 25 | "metadata": { 26 | "description": "Username to use for SFTP access" 27 | } 28 | }, 29 | "sftpPassword": { 30 | "type": "securestring", 31 | "metadata": { 32 | "description": "Password to use for SFTP access" 33 | } 34 | }, 35 | "location": { 36 | "type": "string", 37 | "defaultValue": "[resourceGroup().location]", 38 | "metadata": { 39 | "description": "Primary location for resources" 40 | } 41 | }, 42 | "containerGroupDNSLabel": { 43 | "type": "string", 44 | "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]", 45 | "metadata" : { 46 | "description": "DNS label for container group" 47 | } 48 | } 49 | }, 50 | "variables": { 51 | "cliContainerName": "create-share", 52 | "cliContainerGroupName": "create-share-group", 53 | "cliContainerImage": "mcr.microsoft.com/azure-cli", 54 | "sftpContainerName": "sftp", 55 | "sftpContainerGroupName": "sftp-group", 56 | "sftpContainerImage": "atmoz/sftp:latest", 57 | "sftpEnvVariable": "[concat(parameters('sftpUser'), ':', parameters('sftpPassword'), ':1001')]", 58 | "storageAccountName": "[concat('sftpstg', uniqueString(resourceGroup().id))]" 59 | }, 60 | "resources": [ 61 | { 62 | "type": "Microsoft.Resources/deployments", 63 | "name": "pid-18f281fe-d1e1-502c-8b87-d945383dc75b", 64 | "apiVersion": "2015-01-01", 65 | "properties": { 66 | "mode": "Incremental", 67 | "template": { 68 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 69 | "contentVersion": "1.0.0.0", 70 | "resources": [] 71 | } 72 | } 73 | }, 74 | { 75 | "type": "Microsoft.Storage/storageAccounts", 76 | "name": "[variables('storageAccountName')]", 77 | "apiVersion": "2018-02-01", 78 | "location": "[parameters('location')]", 79 | "sku": { 80 | "name": "[parameters('storageAccountType')]" 81 | }, 82 | "kind": "Storage", 83 | "properties": {} 84 | }, 85 | { 86 | "type": "Microsoft.ContainerInstance/containerGroups", 87 | "name": "[variables('cliContainerGroupName')]", 88 | "apiVersion": "2018-04-01", 89 | "location": "[parameters('location')]", 90 | "dependsOn": [ 91 | "[variables('storageAccountName')]" 92 | ], 93 | "properties": { 94 | "containers": [ 95 | { 96 | "name": "[variables('cliContainerName')]", 97 | "properties": { 98 | "image": "[variables('cliContainerImage')]", 99 | "command": [ 100 | "az", 101 | "storage", 102 | "share", 103 | "create", 104 | "--name", 105 | "[parameters('fileShareName')]" 106 | ], 107 | "environmentVariables": [ 108 | { 109 | "name": "AZURE_STORAGE_KEY", 110 | "value": "[listKeys(variables('storageAccountName'),'2018-02-01').keys[0].value]" 111 | }, 112 | { 113 | "name": "AZURE_STORAGE_ACCOUNT", 114 | "value": "[variables('storageAccountName')]" 115 | } 116 | ], 117 | "resources": { 118 | "requests": { 119 | "cpu": 1, 120 | "memoryInGB": 1 121 | } 122 | } 123 | } 124 | } 125 | ], 126 | "restartPolicy": "OnFailure", 127 | "osType": "Linux" 128 | } 129 | }, 130 | { 131 | "type": "Microsoft.ContainerInstance/containerGroups", 132 | "name": "[variables('sftpContainerGroupName')]", 133 | "apiVersion": "2018-04-01", 134 | "location": "[parameters('location')]", 135 | "dependsOn": [ 136 | "[variables('cliContainerGroupName')]" 137 | ], 138 | "properties": { 139 | "containers": [ 140 | { 141 | "name": "[variables('sftpContainerName')]", 142 | "properties": { 143 | "image": "[variables('sftpContainerImage')]", 144 | "environmentVariables": [ 145 | { 146 | "name": "SFTP_USERS", 147 | "value": "[variables('sftpEnvVariable')]" 148 | } 149 | ], 150 | "resources": { 151 | "requests": { 152 | "cpu": 2, 153 | "memoryInGB": 1 154 | } 155 | }, 156 | "ports": [ 157 | { 158 | "port": 22 159 | } 160 | ], 161 | "volumeMounts": [ 162 | { 163 | "mountPath": "[concat('/home/', parameters('sftpUser'), '/upload')]", 164 | "name": "sftpvolume", 165 | "readOnly": false 166 | } 167 | ] 168 | } 169 | } 170 | ], 171 | "osType": "Linux", 172 | "ipAddress": { 173 | "type": "Public", 174 | "ports": [ 175 | { 176 | "protocol": "TCP", 177 | "port": 22 178 | } 179 | ], 180 | "dnsNameLabel": "[parameters('containerGroupDNSLabel')]" 181 | }, 182 | "restartPolicy": "OnFailure", 183 | "volumes": [ 184 | { 185 | "name": "sftpvolume", 186 | "azureFile": { 187 | "readOnly": false, 188 | "shareName": "[parameters('fileShareName')]", 189 | "storageAccountName": "[variables('storageAccountName')]", 190 | "storageAccountKey": "[listKeys(variables('storageAccountName'),'2018-02-01').keys[0].value]" 191 | } 192 | } 193 | ] 194 | } 195 | } 196 | ], 197 | "outputs": { 198 | "containerDNSLabel": { 199 | "type": "string", 200 | "value": "[concat(parameters('containerGroupDNSLabel'), '.', parameters('location'), '.azurecontainer.io')]" 201 | } 202 | } 203 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-and-azure-files/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/azure-quickstart-templates-metadata-schema#", 3 | "type": "QuickStart", 4 | "itemDisplayName": "Create an on-demand SFTP Server with persistent storage", 5 | "description": "This template demonstrates an on-demand SFTP server using an Azure Container Instance (ACI).", 6 | "summary": "Create an on-demand SFTP Server with persistent storage", 7 | "githubUsername": "bhummerstone", 8 | "dateUpdated": "2021-06-24" 9 | } 10 | 11 | -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/azuredeploy.bicep: -------------------------------------------------------------------------------- 1 | @description('Resource group for existing storage account') 2 | param existingStorageAccountResourceGroupName string 3 | 4 | @description('Name of existing storage account') 5 | param existingStorageAccountName string 6 | 7 | @description('Name of existing file share to be mounted') 8 | param existingFileShareName string 9 | 10 | @description('Username to use for SFTP access') 11 | param sftpUser string = 'sftp' 12 | 13 | @secure() 14 | @description('Password to use for SFTP access') 15 | param sftpPassword string 16 | 17 | @description('Primary location for resources') 18 | param location string = resourceGroup().location 19 | 20 | @description('DNS label for container group') 21 | param containerGroupDNSLabel string = uniqueString(resourceGroup().id, deployment().name) 22 | 23 | var sftpContainerName = 'sftp' 24 | var sftpContainerGroupName = 'sftp-group' 25 | var sftpContainerImage = 'atmoz/sftp:debian' 26 | var sftpEnvVariable = '${sftpUser}:${sftpPassword}:1001' 27 | 28 | resource stgacct 'Microsoft.Storage/storageAccounts@2019-06-01' existing = { 29 | name: existingStorageAccountName 30 | scope: resourceGroup(existingStorageAccountResourceGroupName) 31 | } 32 | 33 | resource containergroup 'Microsoft.ContainerInstance/containerGroups@2019-12-01' = { 34 | name: sftpContainerGroupName 35 | location: location 36 | properties: { 37 | containers: [ 38 | { 39 | name: sftpContainerName 40 | properties: { 41 | image: sftpContainerImage 42 | environmentVariables: [ 43 | { 44 | name: 'SFTP_USERS' 45 | secureValue: sftpEnvVariable 46 | } 47 | ] 48 | resources: { 49 | requests: { 50 | cpu: 1 51 | memoryInGB: 1 52 | } 53 | } 54 | ports:[ 55 | { 56 | port: 22 57 | protocol: 'TCP' 58 | } 59 | ] 60 | volumeMounts: [ 61 | { 62 | mountPath: '/home/${sftpUser}/upload' 63 | name: 'sftpvolume' 64 | readOnly: false 65 | } 66 | ] 67 | } 68 | } 69 | ] 70 | 71 | osType:'Linux' 72 | ipAddress: { 73 | type: 'Public' 74 | ports:[ 75 | { 76 | port: 22 77 | protocol:'TCP' 78 | } 79 | ] 80 | dnsNameLabel: containerGroupDNSLabel 81 | } 82 | restartPolicy: 'OnFailure' 83 | volumes: [ 84 | { 85 | name: 'sftpvolume' 86 | azureFile:{ 87 | readOnly: false 88 | shareName: existingFileShareName 89 | storageAccountName: stgacct.name 90 | storageAccountKey: listKeys(stgacct.id, '2019-06-01').keys[0].value 91 | } 92 | } 93 | ] 94 | } 95 | } 96 | 97 | output containerDNSLabel string = '${containergroup.properties.ipAddress.dnsNameLabel}.${containergroup.location}.azurecontainer.io' 98 | -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "metadata": { 5 | "_generator": { 6 | "name": "bicep", 7 | "version": "0.4.63.48766", 8 | "templateHash": "16190402726175806996" 9 | } 10 | }, 11 | "parameters": { 12 | "existingStorageAccountResourceGroupName": { 13 | "type": "string", 14 | "metadata": { 15 | "description": "Resource group for existing storage account" 16 | } 17 | }, 18 | "existingStorageAccountName": { 19 | "type": "string", 20 | "metadata": { 21 | "description": "Name of existing storage account" 22 | } 23 | }, 24 | "existingFileShareName": { 25 | "type": "string", 26 | "metadata": { 27 | "description": "Name of existing file share to be mounted" 28 | } 29 | }, 30 | "sftpUser": { 31 | "type": "string", 32 | "defaultValue": "sftp", 33 | "metadata": { 34 | "description": "Username to use for SFTP access" 35 | } 36 | }, 37 | "sftpPassword": { 38 | "type": "securestring", 39 | "metadata": { 40 | "description": "Password to use for SFTP access" 41 | } 42 | }, 43 | "location": { 44 | "type": "string", 45 | "defaultValue": "[resourceGroup().location]", 46 | "metadata": { 47 | "description": "Primary location for resources" 48 | } 49 | }, 50 | "containerGroupDNSLabel": { 51 | "type": "string", 52 | "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]", 53 | "metadata": { 54 | "description": "DNS label for container group" 55 | } 56 | } 57 | }, 58 | "functions": [], 59 | "variables": { 60 | "sftpContainerName": "sftp", 61 | "sftpContainerGroupName": "sftp-group", 62 | "sftpContainerImage": "atmoz/sftp:debian", 63 | "sftpEnvVariable": "[format('{0}:{1}:1001', parameters('sftpUser'), parameters('sftpPassword'))]" 64 | }, 65 | "resources": [ 66 | { 67 | "type": "Microsoft.ContainerInstance/containerGroups", 68 | "apiVersion": "2019-12-01", 69 | "name": "[variables('sftpContainerGroupName')]", 70 | "location": "[parameters('location')]", 71 | "properties": { 72 | "containers": [ 73 | { 74 | "name": "[variables('sftpContainerName')]", 75 | "properties": { 76 | "image": "[variables('sftpContainerImage')]", 77 | "environmentVariables": [ 78 | { 79 | "name": "SFTP_USERS", 80 | "secureValue": "[variables('sftpEnvVariable')]" 81 | } 82 | ], 83 | "resources": { 84 | "requests": { 85 | "cpu": 1, 86 | "memoryInGB": 1 87 | } 88 | }, 89 | "ports": [ 90 | { 91 | "port": 22, 92 | "protocol": "TCP" 93 | } 94 | ], 95 | "volumeMounts": [ 96 | { 97 | "mountPath": "[format('/home/{0}/upload', parameters('sftpUser'))]", 98 | "name": "sftpvolume", 99 | "readOnly": false 100 | } 101 | ] 102 | } 103 | } 104 | ], 105 | "osType": "Linux", 106 | "ipAddress": { 107 | "type": "Public", 108 | "ports": [ 109 | { 110 | "port": 22, 111 | "protocol": "TCP" 112 | } 113 | ], 114 | "dnsNameLabel": "[parameters('containerGroupDNSLabel')]" 115 | }, 116 | "restartPolicy": "OnFailure", 117 | "volumes": [ 118 | { 119 | "name": "sftpvolume", 120 | "azureFile": { 121 | "readOnly": false, 122 | "shareName": "[parameters('existingFileShareName')]", 123 | "storageAccountName": "[parameters('existingStorageAccountName')]", 124 | "storageAccountKey": "[listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('existingStorageAccountResourceGroupName')), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').keys[0].value]" 125 | } 126 | } 127 | ] 128 | } 129 | } 130 | ], 131 | "outputs": { 132 | "containerDNSLabel": { 133 | "type": "string", 134 | "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)]" 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "sftpUser": { 6 | "value": "GEN-UNIQUE-6" 7 | }, 8 | "sftpPassword": { 9 | "value": "GEN-PASSWORD" 10 | }, 11 | "existingStorageAccountResourceGroupName": { 12 | "value": "GET-PREREQ-existingStgAcctRGName" 13 | }, 14 | "existingStorageAccountName": { 15 | "value": "GET-PREREQ-existingStgAcctName" 16 | }, 17 | "existingFileShareName": { 18 | "value": "GET-PREREQ-existingFileShareName" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/azuredeploy_cli_container.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "existingStorageAccountResourceGroupName": { 6 | "type": "string", 7 | "metadata": { 8 | "description": "Resource group for existing storage account" 9 | } 10 | }, 11 | "existingStorageAccountName": { 12 | "type": "string", 13 | "metadata": { 14 | "description": " oNamef existing storage account" 15 | } 16 | }, 17 | "existingFileShareName": { 18 | "type": "string", 19 | "metadata": { 20 | "description": "Name of existing file share to be mounted" 21 | } 22 | }, 23 | "sftpUser": { 24 | "type": "string", 25 | "metadata": { 26 | "description": "Username to use for SFTP access" 27 | } 28 | }, 29 | "sftpPassword": { 30 | "type": "securestring", 31 | "metadata": { 32 | "description": "Password to use for SFTP access" 33 | } 34 | }, 35 | "location": { 36 | "type": "string", 37 | "defaultValue": "[resourceGroup().location]", 38 | "metadata": { 39 | "description": "Primary location for resources" 40 | } 41 | }, 42 | "containerGroupDNSLabel": { 43 | "type": "string", 44 | "defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]", 45 | "metadata" : { 46 | "description": "DNS label for container group" 47 | } 48 | } 49 | }, 50 | "variables": { 51 | "sftpContainerName": "sftp", 52 | "sftpContainerGroupName": "sftp-group", 53 | "sftpContainerImage": "atmoz/sftp:latest", 54 | "sftpEnvVariable": "[concat(parameters('sftpUser'), ':', parameters('sftpPassword'), ':1001')]", 55 | "storageAccountId": "[resourceId(parameters('existingStorageAccountResourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName'))]" 56 | }, 57 | "resources": [ 58 | { 59 | "type": "Microsoft.Resources/deployments", 60 | "name": "pid-18f281fe-d1e1-502c-8b87-d945383dc75b", 61 | "apiVersion": "2018-05-01", 62 | "properties": { 63 | "mode": "Incremental", 64 | "template": { 65 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 66 | "contentVersion": "1.0.0.0", 67 | "resources": [] 68 | } 69 | } 70 | }, 71 | { 72 | "type": "Microsoft.ContainerInstance/containerGroups", 73 | "name": "[variables('sftpContainerGroupName')]", 74 | "apiVersion": "2018-10-01", 75 | "location": "[parameters('location')]", 76 | "properties": { 77 | "containers": [ 78 | { 79 | "name": "[variables('sftpContainerName')]", 80 | "properties": { 81 | "image": "[variables('sftpContainerImage')]", 82 | "environmentVariables": [ 83 | { 84 | "name": "SFTP_USERS", 85 | "value": "[variables('sftpEnvVariable')]" 86 | } 87 | ], 88 | "resources": { 89 | "requests": { 90 | "cpu": 2, 91 | "memoryInGB": 1 92 | } 93 | }, 94 | "ports": [ 95 | { 96 | "port": 22 97 | } 98 | ], 99 | "volumeMounts": [ 100 | { 101 | "mountPath": "[concat('/home/', parameters('sftpUser'), '/upload')]", 102 | "name": "sftpvolume", 103 | "readOnly": false 104 | } 105 | ] 106 | } 107 | } 108 | ], 109 | "osType": "Linux", 110 | "ipAddress": { 111 | "type": "Public", 112 | "ports": [ 113 | { 114 | "protocol": "TCP", 115 | "port": 22 116 | } 117 | ], 118 | "dnsNameLabel": "[parameters('containerGroupDNSLabel')]" 119 | }, 120 | "restartPolicy": "OnFailure", 121 | "volumes": [ 122 | { 123 | "name": "sftpvolume", 124 | "azureFile": { 125 | "readOnly": false, 126 | "shareName": "[parameters('existingFileShareName')]", 127 | "storageAccountName": "[parameters('existingStorageAccountName')]", 128 | "storageAccountKey": "[listKeys(variables('storageAccountId'),'2018-02-01').keys[0].value]" 129 | } 130 | } 131 | ] 132 | } 133 | } 134 | ], 135 | "outputs": { 136 | "containerDNSLabel": { 137 | "type": "string", 138 | "value": "[concat(parameters('containerGroupDNSLabel'), '.', parameters('location'), '.azurecontainer.io')]" 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/azure-quickstart-templates-metadata-schema#", 3 | "type": "QuickStart", 4 | "itemDisplayName": "On-demand SFTP Server using an existing storage account", 5 | "description": "This template demonstrates an on-demand SFTP server using an Azure Container Instance (ACI).", 6 | "summary": "Create an on-demand SFTP Server with persistent storage using an existing storage account", 7 | "githubUsername": "bhummerstone", 8 | "dateUpdated": "2021-06-24" 9 | } 10 | -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/prereqs/prereq.azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | }, 6 | "variables": { 7 | "storageAccountName": "[concat(uniqueString(resourceGroup().id),'storage')]", 8 | "cliContainerName": "create-share", 9 | "cliContainerGroupName": "create-share-group", 10 | "cliContainerImage": "mcr.microsoft.com/azure-cli", 11 | "fileShareName": "sftpshare" 12 | }, 13 | "resources": [ 14 | { 15 | "type": "Microsoft.Storage/storageAccounts", 16 | "name": "[variables('storageAccountName')]", 17 | "apiVersion": "2018-02-01", 18 | "location": "[resourceGroup().location]", 19 | "sku": { 20 | "name": "Standard_LRS" 21 | }, 22 | "kind": "Storage", 23 | "properties": {} 24 | }, 25 | { 26 | "type": "Microsoft.ContainerInstance/containerGroups", 27 | "name": "[variables('cliContainerGroupName')]", 28 | "apiVersion": "2018-04-01", 29 | "location": "[resourceGroup().location]", 30 | "dependsOn": [ 31 | "[variables('storageAccountName')]" 32 | ], 33 | "properties": { 34 | "containers": [ 35 | { 36 | "name": "[variables('cliContainerName')]", 37 | "properties": { 38 | "image": "[variables('cliContainerImage')]", 39 | "command": [ 40 | "az", 41 | "storage", 42 | "share", 43 | "create", 44 | "--name", 45 | "[variables('fileShareName')]" 46 | ], 47 | "environmentVariables": [ 48 | { 49 | "name": "AZURE_STORAGE_KEY", 50 | "value": "[listKeys(variables('storageAccountName'),'2018-02-01').keys[0].value]" 51 | }, 52 | { 53 | "name": "AZURE_STORAGE_ACCOUNT", 54 | "value": "[variables('storageAccountName')]" 55 | } 56 | ], 57 | "resources": { 58 | "requests": { 59 | "cpu": 1, 60 | "memoryInGB": 1 61 | } 62 | } 63 | } 64 | } 65 | ], 66 | "restartPolicy": "OnFailure", 67 | "osType": "Linux" 68 | } 69 | } 70 | ], 71 | "outputs": { 72 | "existingStgAcctName": { 73 | "type": "string", 74 | "value": "[variables('storageAccountName')]" 75 | }, 76 | "existingStgAcctRGName": { 77 | "type": "string", 78 | "value": "[resourceGroup().name]" 79 | }, 80 | "existingFileShareName": { 81 | "type": "string", 82 | "value": "[variables('fileShareName')]" 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /create-aci-sftp-server-with-existing-azure-file-share/prereqs/prereq.azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | } 6 | } -------------------------------------------------------------------------------- /media/07d51c6830a6975b0fe1869f08378c35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/07d51c6830a6975b0fe1869f08378c35.png -------------------------------------------------------------------------------- /media/0f9a21b676c64a6de53bff3a317977f9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/0f9a21b676c64a6de53bff3a317977f9.png -------------------------------------------------------------------------------- /media/1-changepassword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/1-changepassword.png -------------------------------------------------------------------------------- /media/2-changepassword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/2-changepassword.png -------------------------------------------------------------------------------- /media/27eb882cc865681917477f753c7361aa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/27eb882cc865681917477f753c7361aa.png -------------------------------------------------------------------------------- /media/3-changepassword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/3-changepassword.png -------------------------------------------------------------------------------- /media/4-changepassword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/4-changepassword.png -------------------------------------------------------------------------------- /media/45f6559a0fdcd3f6e300153d13eb3fde.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/45f6559a0fdcd3f6e300153d13eb3fde.jpg -------------------------------------------------------------------------------- /media/490ad362e0903ed66eefeb06fc9b0264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/490ad362e0903ed66eefeb06fc9b0264.png -------------------------------------------------------------------------------- /media/5-changepassword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/5-changepassword.png -------------------------------------------------------------------------------- /media/b78de12062ed4a83bbe8fc3a1e916dc9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/b78de12062ed4a83bbe8fc3a1e916dc9.png -------------------------------------------------------------------------------- /media/f851279263a95b834f590158154fa7db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/f851279263a95b834f590158154fa7db.png -------------------------------------------------------------------------------- /media/fqdn_image.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/sftp-creation-template/835d92e05c70b9abe1912dbe4d2b3ab954980b04/media/fqdn_image.PNG --------------------------------------------------------------------------------