How To Deploy SFTP Service On Azure Container Apps – Comprehensive Guide

15 Min. Read

In today’s digital world, the transfer of data between clients and servers has become a common practice. However, traditional FTP services are no longer considered safe to use for security reasons. Therefore, a more secure protocol, SFTP (Secure File Transfer Protocol), has become the preferred choice.

In this article, we will guide you through deploying an SFTP service on Azure Container Apps, ensuring it is both secure and easily accessible.

Introduction

A while ago, we wrote a couple of articles on how to deploy a Secure FTP (SFTP) Service on Microsoft Azure using Container Instances. This solution will be a good workaround for a cost-effective SFTP solution in Azure, which is backed by durable persistent storage. ACI service is inexpensive and requires very little maintenance, while data is stored in Azure Files which is a fully managed SMB service in the cloud and can be protected using Azure Backup.

Fast forward, after more than two years of waiting, Microsoft finally released a fully managed SFTP (PaaS) service based on Microsoft Azure Blob Storage. The (SFTP) support for Azure Blob Storage is now generally available and Microsoft starts applying hourly costs on or after January 1, 2023.

However, based on the higher pricing that currently (SFTP) for Azure Blob Storage has, this includes the cost of storage and the SFTP transfer. The SFTP charges in increments of $0.30 per hour, which means around $220 per month on top of your storage costs as documented in the pricing page for SSH File Transfer Protocol.

To optimize hourly usage charges, Microsoft recommends disabling the SFTP service option in your storage accounts if you don’t intend to use Azure Blobs via SFTP. Learn more about SFTP pricing for Azure Blob Storage. The funny part is that on May 2nd, we received the following notification message from Microsoft: [You may have been undercharged for Azure Blob Storage usage via SFTP].

Let’s find an alternative and cheaper SFTP solution!

Azure Blob Storage usage via SFTP
Azure Blob Storage usage via SFTP

As an alternative option, we’ve been using Azure Container Instances (ACI) SFTP solution to achieve a similar capability with Azure Files to lower costs, and it’s working great for more than four years now.

However, one of the limitations that Azure Container Instances (ACI) has, we cannot easily control the inbound traffic to restrict network public access. We need to use other services such as Azure Application Gateway or Azure Firewall to do so, which means that the ACI-based solution would become expensive.

> You can read more about how to restrict public IP access for ACI container-based SFTP solutions.

Now, if you are already using Azure Application Gateway or Azure Firewall as part of a wider large Azure deployment, then you could integrate SFTP based on ACI and enable whitelisting, but we don’t recommend using these services natively to only control SFTP access, because these services cost additional money and they are not cheap.

The good news is, that Microsoft just announced in Generally Available (GA) that Azure Container Apps now supports using TCP-based protocols other than HTTP or HTTPS for ingress, as well as you can mount Azure Files and ephemeral storage in Azure Container Apps.

With these new features in GA, you can now deploy Container Apps that communicate using TCP-based protocols on a specific port you set within the environment (i.e. TCP Port 22 for SFTP). Additionally, a container app can expose a TCP port externally for ingress when using a custom virtual network, this means you can restrict inbound public access using a Network Security Group (NSG), and then you can use Azure Files for persistent data, and protect your SFTP data using Azure Backup for either short-term or long-term retention.

So as you can see, we have now a complete SFTP container-based solution where you can have more control technically and be cost-efficient.

In this article, we will show you step-by-step how to deploy an SFTP service in Azure based on Azure Container Apps (ACA) instead of Azure Container Instances (ACI), making it secure and easily accessible.

Before we dive into the ACA-based SFTP solution,  I want to shout a big thanks to my dear friend Ben Hummerstone (Producer of Concepts at Microsoft) for his guidance and support.

Containerization Services in Azure

If you are familiar with Azure, you have probably noticed that there are multiple containerization services available.

Azure Container Instances (ACI) is a service that allows you to execute a single container in an isolated environment. ACI supports both Windows and Linux containers and can start within seconds. It is useful for running a build server or bursting in the context of an AKS cluster. However, ACI does not provide scaling or load-balancing functionalities.

If you need scaling and load-balancing capabilities, Azure Kubernetes Service (AKS) is a better option. With AKS, you get a managed Kubernetes cluster in Azure, which can be accessed and controlled through standard Kubernetes CLI commands.

Azure Container Registry (ACR) allows you to create a private registry for your container images and restrict access to select users and groups within your organization. ACR also offers a feature called “tasks” that can be used for image scanning and hardening.

Azure Service Fabric is similar to AKS, but the underlying orchestrator is proprietary to Microsoft.

With multiple containerization services already available in Azure, why did Microsoft introduce another one?

Although Azure Kubernetes Service (AKS) is a powerful option, managing the cluster is the user’s responsibility. Moreover, AKS does not support scaling based on events other than CPU/RAM utilization. This is where Azure Container Apps (ACA) comes in, providing a solution for event-based scaling and management of containerized applications.

Additionally, the Azure Container Instances (ACI) solution is a bit more expensive compared to Azure Container Apps (ACA), and with added security in ACA, we can secure our custom VNET with Network Security Groups, and we can secure outbound traffic using user-defined routes (UDR) with Azure Firewall or NAT gateway integration.

So, why not use ACA to build and deploy SFTP service in Microsoft Azure, cost and security are key, right?

Azure Container Apps Overview

Azure Container Apps is a new service from Microsoft Azure that allows developers to deploy and manage containerized applications with ease. It is a fully managed service that abstracts away the underlying infrastructure and provides a streamlined experience for deploying and managing container-based applications.

With Azure Container Apps, you can deploy applications as containers, which are self-contained units of software that contain all the necessary dependencies and configurations to run the application. The service is built on top of Azure Kubernetes Service (AKS), which provides a scalable and highly available container orchestration platform.

Azure Container Apps provides a simple and intuitive user interface that allows you to easily create and manage containerized applications. The service provides several built-in templates for popular container images, such as Node.js, .NET, and Python, which you can use as a starting point for your applications.

You can also customize the application deployment by specifying your own container images, resource requirements, and environment variables. Once the application is deployed, Azure Container Apps automatically manages the scaling and availability of the application, ensuring that it stays up and running even in the face of traffic spikes or hardware failures.

Azure Container Apps also provides tight integration with Azure services such as Azure Event Grid, Log Analytics, and Azure Functions, allowing you easily to build event-driven architectures and serverless workflows using containers. Additionally, the service integrates with Azure DevOps and other popular CI/CD tools, making it easy to integrate container-based applications into existing development workflows.

For this article, we will be using the following architecture to deploy our Azure SFTP service based on Azure Container Apps (ACA).

Azure SFTP Service based on Azure Container Apps
Azure SFTP Service based on Azure Container Apps

Deploy SFTP Service On Azure Container Apps

Let’s see in action how to deploy SFTP service on Azure Container Apps using Azure ARM Template.

Click on the “Deploy to Azure” button and follow the steps as shown in the video below, to deploy SFTP service on Azure Container Apps using the (consumption plan) for multi-users with a new storage account, two Azure file shares, and two access rules for IP restrictions. The deployment will take around 10 minutes to complete.

Deploy To Azure
Please take note of the username and password during the deployment since you will need to use them to access the SFTP service later.

Last but not least, copy the static public IP address from the Container Apps Environment (sftp-aca-env), or copy the Endpoint(s) FQDN from the Container Apps under the Ingress blade as shown in the figure below, and then connect securely to the SFTP service with your desired FTP client such as (FileZilla).

Azure SFTP running on ACA
Azure SFTP running on ACA

Enjoy :)

Restrict SFTP Public IP Access

Now the SFTP service is publicly accessible from anywhere over a secure shell. You have a new requirement to whitelist specific IPs to connect to the SFTP service. In other words, you want to restrict access to the SFTP service in Azure and allow only a certain set of IP ranges.

Configure IP Restrictions (New)

The Azure Container Apps (ACA) allows you to limit inbound traffic to your container app (SFTP) by configuring IP ingress restrictions via ingress configuration. This method was not working before and we used to manually update the Network Security Group (NSG) as described in the Configure IP Restrictions (Old).

There are three types of IP Security Restrictions Modes:

  1. Allow all traffic (default).
  2. Allow inbound traffic only from address ranges you specify in allow rules.
  3. Deny all inbound traffic only from address ranges you specify in deny rules.

You can manage IP access restriction rules through the Azure portal or Azure CLI. We have also updated the ARM template above to add and configure IP Security Restrictions during the deployment of SFTP on ACA.

In this section, we will show you how to manage IP access restrictions through the Azure portal and Azure CLI.

Manage IP Restrictions through Azure Portal

1) Go to your SFTP container app in the Azure portal, and then select Ingress from the left side menu.

2) Select the IP Security Restrictions Mode toggle to enable IP restrictions. You can choose to allow or deny traffic from the specified IP address ranges.

Configure IP Security Restrictions in ACA
Configure IP Security Restrictions in ACA

3) Select Add to create the rule and then enter values in the following format:

  • IPv4 address or range: Enter the IP address or range of IP addresses in CIDR notation. For example, to allow access from a single IP address, you can use the following format:  10.200.10.2 or with CIDR notation 10.200.10.2/32.
  • Name: Enter a name for the rule.
  • Description: Enter a description for the rule.
Add Allow Rule in ACA
Add Allow Rule in ACA

4) Next, select Add. You can repeat step 3 to add more rules.

5) Last, when you have finished adding rules, click Save.

Manage IP ingress restrictions in ACA
Manage IP ingress restrictions in ACA

You can also update and delete existing IP access rules as needed.

// As a side note, the public IP address for the Azure Container App (ACA) SFTP solution is Static and NOT Dynamic.

Manage IP Restrictions through Azure CLI

You can also manage IP Access Restrictions for SFTP using the az containerapp ingress access-restriction command group. This command group has the following three options:

  • set: Create or update a rule.
  • remove: Delete a rule.
  • list: List all rules.

To create or update rules, you can use the az containerapp access-restriction set command to restrict inbound access to an IP address range only.

The following example creates a rule to restrict inbound access to a single IP address only. Please note that you must delete any existing deny rules before you can add any allow rules.

Replace the values in the following example with your values:

az containerapp ingress access-restriction set \
   --name "sftp-aca-app" \
   --resource-group "RESOURCE_GROUP_NAME" \
   --rule-name "Allow-Rule-1" \
   --description "Rule allowing access" \
   --ip-address 10.200.10.2/32 \
   --action Allow

You can add to the allow rules by repeating the same command but with different –ip-address and –rule-name values. If you use a rule name that already exists, the existing rule is updated.

The following example creates a rule to deny inbound traffic from a specified IP range. Please note that you must delete any existing allow rules before you can add deny rules.

Replace the values in the following example with your values:

az containerapp ingress access-restriction set \
  --name "sftp-aca-app" \
  --resource-group "RESOURCE_GROUP_NAME" \
  --rule-name "Deny-Rule-1" \
  --description "Rule denying access" \
  --ip-address 10.200.0.100/28 \
  --action Deny

You can add to the deny rules by repeating the same command with different –ip-address and –rule-name values. If you use a rule name that already exists, the existing rule is updated.

To remove IP access restrictions, you can use the az containerapp ingress access-restriction remove command to remove a single rule for the SFTP container app.

Replace the values in the following example with your values:

az containerapp ingress access-restriction remove
  --name "sftp-aca-app" \
  --resource-group "RESOURCE_GROUP_NAME" \
  --rule-name "Deny-Rule-1"

And to list IP access restrictions, you can use the az containerapp ingress access-restriction list command to list all IP access restrictions for the SFTP container app.

Replace the values in the following example with your values:

az containerapp ingress access-restriction list
  --name "sftp-aca-app" \
  --resource-group "RESOURCE_GROUP_NAME"

// As a side note, the public IP address for the Azure Container App (ACA) SFTP solution is Static and NOT Dynamic.

Configure IP Restrictions (Old)

You can disregard the old method below and use the new IP restriction configuration as described above.

Now, when you deploy an internal or an external Azure Container Apps environment into your network using the consumption plan, you will see a new Resource Group with the “MC_” prefix created in the Azure subscription where the ACA environment is hosted. This resource group contains infrastructure components managed by the Azure Container Apps platform. Please note that this resource group should not be modified.

What you could do is the following, you can use the default Network Security Group (NSG) that was deployed as part of the Azure Container Apps infrastructure components under the consumption plan, and then only allow Inbound communications from specific public IP ranges.

Azure Container Apps - AKS (Network Security Group)
Azure Container Apps – AKS (Network Security Group)

As mentioned above, the ACA service is built on top of Azure Kubernetes Service (AKS), which provides a scalable and highly available container orchestration platform. As you can see in the figure below, you need to modify the Inbound Security Rule number (502) and adjust the Source and Action based on your SFTP access needs.

Update ACA Network Security Group for SFTP
Update ACA Network Security Group for SFTP

If you have a Site-to-Site VPN connection or ExpressRoute in place, then you can limit the connection to your VNet and connect to the SFTP service internally only.

Prevent SSH Key from Getting Changed

If you have deployed SFTP on Microsoft Azure using Azure Container Apps (ACA), then you probably come across the scenario when the container does an automatic pull of a new image, it restarts the container, and the SSH key pairs are getting regenerated. Thus, this causes problems for clients who have the famous trust prompt below and breaks your automation SFTP transfer.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

Now, there are two possible solutions that you can deploy to solve this issue:

1) The first option is to build a new custom SFTP image by cloning the GitHub repo for the current SFTP container image, then edit the “Dockerfile” to remove the line that removes the host keys.

You can follow the step-by-step guide described here. This option is quite complex and requires deploying a Docker Hub or Azure Container Registry (ACR).

2) Or, you can use the existing SSH key of the image in an Azure file share, mount it to the SFTP image, and then copy it using a bash script to the container. This will keep the SSH keys intact inside the container even after restart. This option will avoid having to build your fork of the SFTP image as described in option 1 above.

For the remainder of this section, we will describe in detail how to deploy option 2.

Step 1) You need to create two additional file shares in the same storage account that you use for Azure Container Apps. One file share will be used to store the keys, and the second one is to store a bash script.

In this example, we have called the additional file shares: [scripts] and [sshkeys] as shown in the figure below:

File share settings
File share settings

Step 2) Now in the scripts file share that we created above, we need to put the following bash script in a file called [copykeys.sh] and then upload it to the file share.

cp /etc/sftpkeys/ssh_host_* /etc/ssh

This bash script just needs to do a copy from the [sftpkeys] folder to ssh.

Bash script to copy [sftpkeys]
Bash script to copy [sftpkeys]
Step 3) Next, we need to connect to the running SFTP container image, and then copy all the below four host (private/public) keys from the following path: “/etc/ssh” and then upload them to the file share called [sshkeys].

Connect to the SFTP container image
Connect to the SFTP container image

We can copy them temporarily using the following command to an existing writable file share and then delete them from that share afterward.

cp /etc/ssh/ssh_host_* /home/[SftpUsername]/sftpfileshare01
Copy ssh_host keys from /etc/ssh
Copy ssh_host keys from /etc/ssh

Step 4) Next, we can connect to the writable SFTP file share using an SFTP client, and download those four host SSH keys. Alternatively, we can browse the writable (file share) directly in the Azure portal and download them as shown in the figure below.

Download SSH host keys
Download SSH host keys

Then we upload them to the new file share called [sshkeys].

Upload SSH host keys to the new file share
Upload SSH host keys to the new file share

Very Important! Don’t forget to delete the host (private/public) keys from the writable file share and your local system for security reasons. Only the admin must have access to the new file share [sshkeys].

Step 5) Last but not least, we need to mount the new [sshkeys] file share to the container volume path /etc/sftpkeys.

We also need to mount the new [scripts] file share with the bash script to /etc/sftp.d, which is a folder where the atmoz/sftp image will run any script after startup (you can see SFTP atmoz documentation here). The bash script just needs to copy from the /sftpkeys mount folder to the /ssh folder.

So, we need to mount both file shares [sshkeys] and [scripts] in Read-Only mode. To do that, take the following steps:

1) Go the the Container Apps Environment > Azure Files (+ Add). Make sure to provide the appropriate values for the Storage account name, the storage account key, the new File shares [sshkeys] and [scripts], and set the Access mode to “Read-only” as shown in the figure below. Then click Save.

Mounting the new Azure file shares in Read-Only mode
Mounting the new Azure file shares in Read-Only mode

2) Next, go to the Container App (sftp-aca-app) > Containers > Edit and Deploy. Select the existing Container image and then click Edit.

Edit Container App image
Edit Container App image

3) Then, under the Volume mounts tab, select the new File share name and then set the Mount path as follows:

  • File share name: “sshkeys” Mount path (folder) “/etc/sftpkeys
  • File share name: “scripts” Mount path (folder) “/etc/sftp.d
Edit and deploy a new Container App revision
Edit and deploy a new Container App revision

4) Last, Click Save and then deploy (Create) the new revision.

Step 6) Finally, you can test by restarting the SFTP Container App revision multiple times and checking that the SSH keys won’t be changed anymore. Enjoy :)

Restarting SFTP Container App revision
Restarting SFTP Container App revision

SFTP Azure Container Apps Pricing

Let’s look at the entire SFTP solution costs based on Azure Container Apps (ACA) and Azure File Shares with the following real-world example based on the (West Europe) region.

As mentioned above, when you deploy an internal or an external ACA environment into your network using the consumption plan, you will see a new Resource Group with the “MC_” prefix created in your subscription where the ACA environment is hosted.

As shown in the figure below, you will see Public IP addresses that are used specifically for outbound connectivity from your SFTP ACA environment, as well as an internal or external load balancer depending on your ACA environment deployment, in this example, we deployed a public load balancing for the external SFTP solution, and because the load balancer is created in your subscription, there are additional costs associated with deploying the service to a custom virtual network.

Azure Container Apps infrastructure components RG
Azure Container Apps infrastructure components RG

Now for ACA, the price depends on whether you are using the Azure Container Apps consumption plan (GA) or the consumption + dedicated plan (Preview) – more on this in the section below.

To make the SFTP-based-container solution more cost-effective, we used the Azure Container Apps consumption plan with 0.5 vCPU core and 1.0 Gi of memory, and with a minimum replica of 1 and 2 maximum replicas. You can set the range of application replicas that get created in response to a scale rule from any range within the minimum of 0 and the maximum of 30 replicas.

> For more information about Azure Container Apps pricing, please check the official pricing page.

Using the consumption plan model will allow the SFTP application to scale in and out on demand. The application can also scale to zero, and you only pay when SFTP is running.

In our scenario, we use SFTP to back up our legacy system on-premises; hence, the upload is more than the download based on our use case.

> Monthly upload (write) of 1000 GiB.

> Monthly download (read) 100 GiB.

The price calculations noted below are based on the West Europe region following the pay-as-you-go model. Please note that you can further lower your data storage cost by committing to one year or three years of Azure Files. Reserve capacity can be purchased in increments of 10 TiB and 100 TiB for 1-year and 3-year commitment durations.

Description Price in US Dollar
ACA Consumption Plan (First 2 million requests each month are free), then $0.40 per million. $0
ACA CPU - First 180,000 vCPU-seconds each month are free. $0
ACA Memory - First 360,000 GiB-seconds each month are free. $0
Public Load Balancer Standard SKU $18.25
Public Load Balancer Data processed 1 TiB ($0.005 per GB) $5
2 x Public IP Addresses Standard SKU ($3.65 per Static IP) $7.30
Azure file share storage cost 1 TiB ($0.0271 per GB) - Hot Tier $27.1
Azure file share metadata cost at-rest for 1 TiB ($0.028 per GiB) - Hot Tier $28
Upload 1000 GiB Write transactions ($0.065 per 10,000) - Hot Tier $65
List transactions ($0.065 per 10,000) - Hot Tier $0.065
Download 100 GiB Read transactions ($0.0052 per 10,000) - Hot Tier $0.52
All other operations ($0.0052 per 10,000) - Hot Tier $0.0052
(Optional) Azure Backup - 1 TiB @ 30 days retention $21.26
Total cost per month $172.50

The Network Ingress cost is free. However, the upload translated to a transaction on Azure Files service – each upload translates to multiple API calls. So, the file transaction prices apply, which are calculated in the above table.

To learn more, please refer to the pricing page under the Transactions and Data Transfer section.

Please note that the price example above is approximate and will vary based on your environment and use case.

ACA Consumption VS Consumption + Dedicated Plans

So, what is the difference between Azure Container Apps (ACA) Consumption versus Consumption + Dedicated plans?

The ACA consumption plan charges you based on the number of resources allocated and the number of requests made, with billing being done on a per-second basis. For the first 180,000 vCPU-seconds, 360,000 GiB-seconds, and 2 million requests each month, there is NO charge. If you go beyond these limits, you will be charged for the additional usage based on the number of vCPU-s and GiB-s allocated to your SFTP applications, also on a per-second basis.

It’s possible to set a minimum number of replicas in an idle mode that should always be running when configuring Container Apps. If your application (SFTP app) scales down to this minimum number of replicas, you’ll be charged at a lower idle rate while the replica is inactive. However, when a replica starts up, processes requests, or exceeds the active billing thresholds for vCPU or bandwidth usage, it enters active mode and is charged at the active rate.

Container Apps replicas are billed for active usage when they are running. You can configure the SFTP application to scale to zero replicas when there are no requests or events to process. No usage charges apply when an application is scaled to zero.

On the other hand, for the ACA dedicated plan which was announced in public preview by the Azure Container Apps team around mid-April 2023, you’ll have the option to select from various workload profiles that offer different quantities of vCPUs and memory in GiBs. Your billing will be based on the total number of vCPUs and memory allocated in the selected workload profile, with charges being calculated per second for each instance that’s actively running.

Now by default when you use a dedicated plan, the consumption workload profile is automatically added to all Consumption + Dedicated plan environments that we create. We can choose to add dedicated workload profiles as part of the ACA environment, and when we need to after our environment is created, which gives us some flexibility when it comes to provisioning our environments.

As of today, the dedicated plan is only available in the following 4 Azure regions: North Central US, North Europe, West Europe, and East US. Read more about Azure Container Apps plan types.

Please note that using the consumption plan, you can choose between 0.25 – 2 CPU cores and 0.1 – 4 GiB of memory. This will determine the CPU cores that will be allocated to your container instance. The valid CPU start at 0.25 cores and can be incremented to a maximum of 2 cores. Similarly, the memory capacity that will be allocated to your container instance. The valid values start at 0.1 Gi and can be presented by 0.1 up to a maximum of 4 Gi.

Furthermore, the SFTP app does NOT require specific hardware requirements like the Consumption + Dedicated plan structure, hence the consumption plan is more appealing for low SFTP requests. However, the combination of Consumption and Dedicated plan structures enables you to run apps that scale to zero that don’t need to be run on specific hardware.

Dedicated workload profiles can help finance professionals and software architects manage costs by enabling them to establish minimum and maximum scaling limits. This allows for cost controls to be put in place. However, when using Serverless computing options, scaling is based on events, and costs may surpass your anticipated limits if your application processes more events than originally planned.

Suppose you have a lot of container apps running on the same workload profile then it makes more financial sense to use a dedicated plan; similar to Azure Functions, for example.

Are you interested in using Consumption + Dedicated workload profiles for SFTP on  ACA? Please share your feedback in the comment section below.

Conclusion

In this article, we showed you how to deploy SFTP service on Azure Container Apps (ACA) and Azure Files for multi-user access with restricted public access.

If you want a fully manageable SFTP solution in Azure, you can deploy SFTP service on Azure Container Apps solution where you can have more technical control and be cost-efficient, making it secure and easily accessible.

In summary, Azure Container Apps (ACA) provides a powerful and easy-to-use platform for deploying and managing containerized applications. With its built-in templates, tight integration with Azure services, and seamless integration with CI/CD tools, you can quickly build and deploy container-based applications, including SFTP at scale, without having to worry about the underlying infrastructure.

__
Thank you for reading my blog.

If you have any questions or feedback, please leave a comment.

-Charbel Nemnom-

Previous

5 Simple Steps – Move Azure VMs with Azure Resource Mover

The Importance of IT Compliance In Modern Business

Next

36 thoughts on “How To Deploy SFTP Service On Azure Container Apps – Comprehensive Guide”

Leave a comment...

  1. Hello Bert, thanks for the comment and feedback!
    Yes, you can create more SFTP users after the deployment.
    The question is, do you want the new users to access and share the same file share, or do you want to provide new file storage for the new users?
    If you just want to add new SFTP users to the existing file share(s), take the following steps:
    1) Browse to the Container APP (sftp-aca-app), then go to “Secrets” under “Settings”. Click on the “sftpenvvariableusers”, and then click show Value to view the usernames and passwords.
    2) Add new SFTP usernames and passwords by following the same syntax as follows “username1:password1 username2:password1 username3:password3 username4:password4”.
    3) Then select the checkbox at the bottom of the page and click Save.
    4) Next, go to “Containers” under “Application”, and then click on “Edit and deploy” at the top.
    5) Under Container click on “sftp-aca”, then go the “Volume mounts” tab.
    6) Next, expand “File shares” and then make sure to set the File share name appropriately to the Mount path folder. You might see that the File share name are empty at the beginning. Do NOT add a third or fourth Mount path (folder) yet until you click Save and Create and deploy new revision.
    7) Then repeat Step 4 to 6 again, but this time on the “Volume mounts” tab, select the desired (existing) File share name that you want to associate to the new SFTP users as shown in the image below. For the Mount path (folder), you need to type the path as follows: “/home/newusername/filesharename” which is the file share name that you want to give to the new users.
    Add new SFTP users to Azure Container Apps (ACA)
    8) Last, click Save and Create and deploy new revision.
    Hope it helps!

  2. Hi Charbel,

    Thank you for making this informative and helpful SFTP solution! I have been trying it out and it looks like the SSH key gets changed. I am not sure how, as I set this up sometime ago and did not modify it. I get the following error when trying to connect from a command line:

    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the ED25519 key sent by the remote host is ….[error continues]

    Any suggestions for how to keep the same SSH key?

  3. I still have an additional question. I’m trying to mount a new file share for a new user. I created the file share in the Storage Account, configured the file share in the Container App Environment, and in the deployment of a new revision of the Container App within the App container, I mounted the Fileshare to the user’s path. However, when I try to deploy the Container App revision, activating the replica fails. What am I overlooking?

  4. Hello Bert, I am happy to hear that creating more SFTP users is working for you.
    Now if you want to mount a new file share for a new user, you need to follow the steps below which are similar to what you have described in your comment:
    1) Create a new File Share in the Storage Account.
    2) Add the new Azure File Share under the Container Apps Environment > Azure Files (+ Add). Make sure to provide the appropriate values for the Storage account name, the storage account key, the new File share name, and set the Access mode to “Read/Write”.
    3) Assuming that you’ve already added the new user credentials under Secrets. Next, go to the Container App (sftp-aca-app) > Containers > Edit and deploy.
    4) Select the existing Container image and then click Edit.
    5) Then, under the Volume mounts tab, select the new File share name and then set the Mount path as follows (/home/NewUserName/NewFileShareName).
    6) Last, Click Save and deploy the new revision.
    I’ve just tried that on my side and it’s working without any issue.
    Hope it helps!

  5. Hi Charbel,

    I have just setup an SFTP using the method above and while the key does not change on restart of the replica, it has changed since yesterday.

    Any pointers would be appreciated?

    Geoff

  6. Hello Geoff, thanks for your comment!

    I’m sorry to hear that you’re experiencing issues with your SFTP host key changing unexpectedly. I haven’t encountered this behavior in my environment.

    In the context of Azure services, such as Azure Container Apps (ACA) and Azure Container Instances (ACI), host keys can change due to various reasons, including internal maintenance activities.
    Have you checked the logs to determine what might have caused the key to change?

    You mentioned that the key does not change on a replica restart. Did you follow the exact steps outlined in this section: Prevent SSH Key from Getting Changed?

    Does the issue persist if you manually restart the replica today?

    Additionally, please check your SFTP configuration file (/etc/ssh/sshd_config) to confirm which key file is being used. The HostKey directive should point to a persistent key file to prevent unexpected changes.

    Hope this helps!

  7. Hi Charbel,

    I’m wondering if it would be possible to mount Azure File shares from a firewall-enabled Storage Account (joined VNET already). Did you have a chance to test this case?

    Best regards,
    Vien

  8. Hello Vien, thank you for your question!
    Yes, it is possible to mount Azure File Shares from a firewall-enabled Storage Account in Azure Container Apps, as long as the environment is deployed with VNet integration.

    In practice, you need the following:

    1. Deploy the Azure Container App Environment into a VNet: Either Internal Environment (preferred) or Consumption with VNet injection.
    2. Create a Private Endpoint for the Storage Account inside the same VNet/subnet: This ensures the Azure Files endpoint is reachable privately even when the storage firewall is restricted.
    3. Configure Private DNS: Link the privatelink.file.core.windows.net zone to the VNet. This allows ACA to resolve the file share using its private IP.
    4. Mount the Azure File Share in the Container App using the standard storage binding.

    With this setup, the Container App can successfully mount Azure Files while keeping the Storage Account locked down behind the firewall.
    Yes, I have tested this scenario and it works reliably with Private Endpoints + VNet-integrated ACA.
    Hope this helps!

  9. Hi Charbel,

    Thanks a lot for your swift answer! About activating Private Endpoint for Storage Account, I have one more concern, because the existing Storage Account has VNET integration enabled with VNET/subnet joined and whitelisted public IP addresses to that Storage Account, would it be a connection issue on the current setup when an App Service connects to that Storage Account through a regional VNET connection? Thank you so much for your explanation!

  10. Hi Vien, great question!

    Enabling a Private Endpoint on the existing Storage Account won’t break your current setup. Public network access and IP restrictions can continue to work alongside the Private Endpoint as long as you don’t disable public access.
    Your App Service using regional VNet integration will keep connecting through the public endpoint unless you update its DNS to route through the Private Endpoint, so no connectivity issue should occur.
    Hope that helps!

  11. Hi Charbel,
    I really appreciate your helpful answers and explanation. With that setup (Container App Environment is deployed into an internal VNET and the existing Storage Account should enable a Private Endpoint), I have one more concern that is how SFTP Container App could be accessed from the Internet via public endpoint. Thanks so much for your time to think along.

  12. Hi Vien, thanks for the feedback and the great question!
    To confirm: with Azure Container Apps on the Consumption plan with VNet integration, the SFTP container can still be exposed publicly using ACA’s built-in external ingress, even though it has private access to resources (like Storage via Private Endpoint).
    An Application Gateway, Front Door, or Load Balancer is not required in this model unless you intentionally deploy an internal-only environment (public access disabled).
    So the following setup is valid:
    > Public SFTP ingress to the container app.
    > Private access to Azure Files via Private Endpoint.
    Hope that helps!

Let us know what you think, or ask a question...