|
1 | 1 | ---
|
2 |
| -title: Deploy content using FTP/S |
3 |
| -description: Learn how to deploy your app to Azure App Service using FTP or FTPS. Improve website security by disabling unencrypted FTP. |
| 2 | +title: Deploy content using FTP |
| 3 | +description: Learn how to deploy your app to Azure App Service using FTP or FTPS, and improve website security by disabling unencrypted FTP. |
4 | 4 |
|
5 | 5 | ms.assetid: ae78b410-1bc0-4d72-8fc4-ac69801247ae
|
6 | 6 | ms.topic: article
|
7 |
| -ms.date: 02/29/2024 |
| 7 | +ms.date: 06/09/2025 |
8 | 8 | author: cephalin
|
9 | 9 | ms.author: cephalin
|
10 | 10 | ---
|
11 | 11 |
|
12 |
| -# Deploy your app to Azure App Service using FTP/S |
| 12 | +# Deploy your app to Azure App Service using FTP |
13 | 13 |
|
14 |
| -This article shows you how to use FTP or FTPS to deploy your web app, mobile app backend, |
15 |
| -or API app to [Azure App Service](./overview.md). |
| 14 | +This article shows you how to use File Transfer Protocol (FTP) or File Transfer Protocol Secure (FTPS) to deploy your web app, mobile app backend, or API app to [Azure App Service](overview.md). |
16 | 15 |
|
17 |
| -The FTP/S endpoint for your app is already active. No configuration is necessary to enable FTP/S deployment. |
| 16 | +FTPS is a more secure form of FTP that uses Transport Layer Security (TLS) and Secure Sockets Layer (SSL). For more information, see [Enforce FTPS](#enforce-ftps). In this article, the terms are interchangeable unless otherwise specified. |
| 17 | + |
| 18 | +The FTP endpoint for your app is already active. No configuration is necessary to enable FTP or FTPS deployment. |
18 | 19 |
|
19 | 20 | > [!NOTE]
|
20 |
| -> When [FTP basic authentication is disabled](configure-basic-auth-disable.md), FTP/S deployment doesn't work, and you can't view or configure FTP credentials in the app's Deployment Center. |
| 21 | +> Both SCM Basic Auth Publishing Credentials and FTP Basic Auth Publishing Credentials must be enabled for FTP deployment to work. When [basic authentication is disabled](configure-basic-auth-disable.md), FTP deployment doesn't work, and you can't view or configure FTP credentials in the app's **Deployment Center**. |
21 | 22 |
|
22 | 23 | ## Get deployment credentials
|
23 | 24 |
|
24 |
| -1. Follow the instructions at [Configure deployment credentials for Azure App Service](deploy-configure-credentials.md) to copy the application-scope credentials or set the user-scope credentials. You can connect to the FTP/S endpoint of your app using either credentials. |
25 |
| - |
26 |
| -1. Craft the FTP username in the following format, depending on your choice of credential scope: |
| 25 | +To get credentials for deployment, follow the instructions at [Configure deployment credentials for Azure App Service](deploy-configure-credentials.md). Copy the application-scope credentials for your app, or set and copy user-scope credentials. You can connect to your app's FTP endpoint by using either set of credentials. |
27 | 26 |
|
28 |
| - | Application-scope | User-scope | |
29 |
| - | - | - | |
30 |
| - |`<app-name>\$<app-name>`|`<app-name>\<deployment-user>`| |
| 27 | +For application-scope credentials, the FTP username format is `<app-name>\$<app-name>`. For user-scope credentials, the FTP username format is `<app-name>\<username>`. The App Service FTP endpoint is shared among apps, so because user-scope credentials aren't linked to a specific resource, you must prepend the username with the app name. |
31 | 28 |
|
32 |
| - --- |
| 29 | +## Get FTP endpoint |
33 | 30 |
|
34 |
| - In App Service, the FTP/S endpoint is shared among apps. Because the user-scope credentials aren't linked to a specific resource, you need to prepend the user-scope username with the app name as shown above. |
| 31 | +To get the FTP endpoint: |
35 | 32 |
|
36 |
| -## Get FTP/S endpoint |
37 |
| - |
38 | 33 | # [Azure portal](#tab/portal)
|
39 | 34 |
|
40 |
| -In the same management page for your app where you copied the deployment credentials (**Deployment Center** > **FTP Credentials**), copy the **FTPS endpoint**. |
| 35 | +On the [Azure portal](https://portal.azure.com) page for your app, select **Deployment Center** under **Deployment** in the left navigation menu. On the **FTPS Credentials** tab, copy the **FTPS Endpoint** URL. |
41 | 36 |
|
42 | 37 | # [Azure CLI](#tab/cli)
|
43 | 38 |
|
44 |
| -Run the [az webapp deployment list-publishing-profiles](/cli/azure/webapp/deployment#az-webapp-deployment-list-publishing-profiles) command. The following example uses a [JMESPath query](/cli/azure/query-azure-cli) to extract the FTP/S endpoints from the output. |
| 39 | +Run the following [az webapp deployment list-publishing-profiles](/cli/azure/webapp/deployment#az-webapp-deployment-list-publishing-profiles) command, replacing the `<app-name>` and `<resource-group-name>` with your values. The following example uses a [JMESPath query](/cli/azure/query-azure-cli) to extract the FTP endpoints from the output. |
45 | 40 |
|
46 | 41 | ```azurecli-interactive
|
47 |
| -az webapp deployment list-publishing-profiles --name <app-name> --resource-group <group-name> --query "[?ends_with(profileName, 'FTP')].{profileName: profileName, publishUrl: publishUrl}" |
| 42 | +az webapp deployment list-publishing-profiles --name <app-name> --resource-group <resource-group-name> --query "[?ends_with(profileName, 'FTP')].{profileName: profileName, publishUrl: publishUrl}" |
48 | 43 | ```
|
49 | 44 |
|
50 |
| -Each app has two FTP/S endpoints, one is read-write, while the other is read-only (`profileName` contains `ReadOnly`) and is for data recovery scenarios. To deploy files with FTP, copy the URL of the read-write endpoint. |
| 45 | +Each app has two FTP endpoints, read-write and read-only, where `profileName` contains `ReadOnly` and is for data-recovery scenarios. For FTP deployment, copy the read-write URL. |
51 | 46 |
|
52 | 47 | # [Azure PowerShell](#tab/powershell)
|
53 | 48 |
|
54 |
| -Run the [Get-AzWebAppPublishingProfile](/powershell/module/az.websites/get-azwebapppublishingprofile) command. The following example extracts the FTP/S endpoint from the XML output. |
| 49 | +Run the following [Get-AzWebAppPublishingProfile](/powershell/module/az.websites/get-azwebapppublishingprofile) command, replacing the `<app-name>` and `<resource-group-name>` with your values. The following example extracts the FTP endpoint from the XML output. |
55 | 50 |
|
56 | 51 | ```azurepowershell-interactive
|
57 |
| -$xml = [xml](Get-AzWebAppPublishingProfile -Name <app-name> -ResourceGroupName <group-name> -OutputFile null) |
| 52 | +$xml = [xml](Get-AzWebAppPublishingProfile -Name <app-name> -ResourceGroupName <resource-group-name> -OutputFile null) |
58 | 53 | $xml.SelectNodes("//publishProfile[@publishMethod=`"FTP`"]/@publishUrl").value
|
59 | 54 | ```
|
60 | 55 |
|
61 | 56 | -----
|
62 | 57 |
|
63 | 58 | ## Deploy files to Azure
|
64 | 59 |
|
65 |
| -1. From your FTP client (for example, [Visual Studio](https://www.visualstudio.com/vs/community/), [Cyberduck](https://cyberduck.io/), or [WinSCP](https://winscp.net/index.php)), use the connection information you gathered to connect to your app. |
66 |
| -2. Copy your files and their respective directory structure to the [**/site/wwwroot** directory](https://github.com/projectkudu/kudu/wiki/File-structure-on-azure) in Azure (or the **/site/wwwroot/App_Data/Jobs/** directory for WebJobs). |
67 |
| -3. Browse to your app's URL to verify the app is running properly. |
| 60 | +To deploy files to Azure with FTP: |
| 61 | + |
| 62 | +1. From your FTP client such as [Visual Studio](https://www.visualstudio.com/vs/community/), [Cyberduck](https://cyberduck.io/), or [WinSCP](https://winscp.net/index.php)), use your connection information to connect to your app. |
| 63 | +1. Copy your files and their directory structure to the [/site/wwwroot](https://github.com/projectkudu/kudu/wiki/File-structure-on-azure) directory in Azure or the */site/wwwroot/App_Data/Jobs/* directory for WebJobs. |
| 64 | +1. Browse to your app's URL to verify the app is running properly. |
68 | 65 |
|
69 | 66 | > [!NOTE]
|
70 |
| -> Unlike [Git-based deployments](deploy-local-git.md) and [Zip deployment](deploy-zip.md), FTP deployment doesn't support build automation, such as: |
71 |
| -> |
72 |
| -> - dependency restores (such as NuGet, NPM, PIP, and Composer automations) |
73 |
| -> - compilation of .NET binaries |
74 |
| -> - generation of web.config (here is a [Node.js example](https://github.com/projectkudu/kudu/wiki/Using-a-custom-web.config-for-Node-apps)) |
75 |
| -> |
76 |
| -> Generate these necessary files manually on your local machine, and then deploy them together with your app. |
77 |
| -> |
| 67 | +> Unlike [local Git deployment](deploy-local-git.md) and [ZIP deployment](deploy-zip.md), FTP deployment doesn't support build automation such as: |
| 68 | +> - Restoring dependencies like NuGet, NPM, PIP, and Composer automation. |
| 69 | +> - Compiling .NET binaries. |
| 70 | +> - Generating a *web.config* file. |
| 71 | +> You must generate these necessary files manually on your local machine and then deploy them with your app. For a Node.js *web.config* example, see [Using a custom web.config for Node apps](https://github.com/projectkudu/kudu/wiki/Using-a-custom-web.config-for-Node-apps). |
78 | 72 |
|
79 | 73 | ## Enforce FTPS
|
80 | 74 |
|
81 |
| -For enhanced security, you should allow FTP over TLS/SSL only. You can also disable both FTP and FTPS if you don't use FTP deployment. |
| 75 | +For enhanced security, you should allow FTPS over TLS/SSL only. You can also disable both FTP and FTPS if you don't use FTP deployment. |
| 76 | + |
| 77 | +To disable unencrypted FTP: |
82 | 78 |
|
83 | 79 | # [Azure portal](#tab/portal)
|
84 | 80 |
|
85 |
| -1. In your app's resource page in [Azure portal](https://portal.azure.com), select **Configuration** > **General settings** from the left navigation. |
| 81 | +1. On the Azure portal page for your app, select **Configuration** under **Settings** in the left navigation menu. |
| 82 | + |
| 83 | +1. On the **General settings** tab of the **Configuration** page, under **Platform settings**, select **FTPS only** for **FTP state**. Or to disable both FTP and FTPS entirely, select **Disabled**. |
86 | 84 |
|
87 |
| -2. To disable unencrypted FTP, select **FTPS Only** in **FTP state**. To disable both FTP and FTPS entirely, select **Disabled**. When finished, select **Save**. If using **FTPS Only**, you must enforce TLS 1.2 or higher by navigating to the **TLS/SSL settings** page of your web app. TLS 1.0 and 1.1 aren't supported with **FTPS Only**. |
| 85 | +  |
88 | 86 |
|
89 |
| -  |
| 87 | +1. If you select **FTPS only**, be sure TLS 1.2 or higher is enforced for **Minimum Inbound TLS Settings**. TLS 1.0 and 1.1 aren't supported for **FTPS only**. |
| 88 | + |
| 89 | +1. Select **Save**. |
90 | 90 |
|
91 | 91 | # [Azure CLI](#tab/cli)
|
92 | 92 |
|
93 |
| -Run the [az webapp config set](/cli/azure/webapp/deployment#az-webapp-deployment-list-publishing-profiles) command with the `--ftps-state` argument. |
| 93 | +Run the following [az webapp config set](/cli/azure/webapp/deployment#az-webapp-deployment-list-publishing-profiles) command, replacing the `<app-name>` and `<resource-group-name>` with your values. Use the `--ftps-state` argument set to `FtpsOnly` to enforce FTPS, or `Disabled` to disable both FTP and FTPS. |
94 | 94 |
|
95 | 95 | ```azurecli-interactive
|
96 |
| -az webapp config set --name <app-name> --resource-group <group-name> --ftps-state FtpsOnly |
| 96 | +az webapp config set --name <app-name> --resource-group <resource-group-name> --ftps-state FtpsOnly |
97 | 97 | ```
|
98 | 98 |
|
99 |
| -Possible values for `--ftps-state` are `AllAllowed` (FTP and FTPS enabled), `Disabled` (FTP and FTPS disabled), and `FtpsOnly` (FTPS only). |
100 |
| - |
101 | 99 | # [Azure PowerShell](#tab/powershell)
|
102 | 100 |
|
103 |
| -Run the [Set-AzWebApp](/powershell/module/az.websites/set-azwebapp) command with the `-FtpsState` parameter. |
| 101 | +Run the following [Set-AzWebApp](/powershell/module/az.websites/set-azwebapp) command, replacing the `<app-name>` and `<resource-group-name>` with your values. Use the `-FtpsState` parameter set to `FtpsOnly` to enforce FTPS, or `Disabled` to disable both FTP and FTPS.. |
104 | 102 |
|
105 | 103 | ```azurepowershell-interactive
|
106 |
| -Set-AzWebApp -Name <app-name> -ResourceGroupName <group-name> -FtpsState FtpsOnly |
| 104 | +Set-AzWebApp -Name <app-name> -ResourceGroupName <-resource-group-name> -FtpsState FtpsOnly |
107 | 105 | ```
|
108 | 106 |
|
109 |
| -Possible values for `--ftps-state` are `AllAllowed` (FTP and FTPS enabled), `Disabled` (FTP and FTPS disabled), and `FtpsOnly` (FTPS only). |
110 |
| - |
111 | 107 | -----
|
112 | 108 |
|
113 |
| -[!INCLUDE [What happens to my app during deployment?](../../includes/app-service-deploy-atomicity.md)] |
114 |
| - |
115 | 109 | ## Troubleshoot FTP deployment
|
116 | 110 |
|
117 |
| - - [How can I troubleshoot FTP deployment?](#how-can-i-troubleshoot-ftp-deployment) |
118 |
| - - [I'm not able to FTP and publish my code. How can I resolve the issue?](#im-not-able-to-ftp-and-publish-my-code-how-can-i-resolve-the-issue) |
119 |
| - - [How can I connect to FTP in Azure App Service via passive mode?](#how-can-i-connect-to-ftp-in-azure-app-service-via-passive-mode) |
120 |
| - - [Why is my connection failing when attempting to connect over FTPS using explicit encryption?](#why-is-my-connection-failing-when-attempting-to-connect-over-ftps-using-explicit-encryption) |
121 |
| - - [How can I determine the method that was used to deploy my Azure App Service?](#how-can-i-determine-the-method-that-was-used-to-deploy-my-azure-app-service) |
| 111 | +- [How can I connect to FTP in App Service via passive mode?](#how-can-i-connect-to-ftp-in-azure-app-service-via-passive-mode) |
| 112 | +- [How can I determine what method was used to deploy my app?](#how-can-i-determine-what-method-was-used-to-deploy-my-app) |
| 113 | +- [What can happen to my app during deployment?](#what-can-happen-to-my-app-during-deployment) |
| 114 | +- [What's the first step in troubleshooting FTP deployment?](#whats-the-first-step-in-troubleshooting-ftp-deployment) |
| 115 | +- [Why can't I FTP and publish my code?](#why-cant-i-ftp-and-publish-my-code) |
| 116 | +- [Why does my connection fail when attempting to connect over FTPS using explicit encryption?](#why-does-my-connection-fail-when-attempting-to-connect-over-ftps-using-explicit-encryption) |
| 117 | + |
| 118 | +### How can I connect to FTP in Azure App Service via passive mode? |
122 | 119 |
|
123 |
| -#### How can I troubleshoot FTP deployment? |
| 120 | +Azure App Service supports connecting via both active and passive modes. Passive mode is preferred because deployment machines are usually behind a firewall in the operating system or as part of a home or business network. For an example of a passive mode connection, see [The Connection Page (Advanced Site Settings dialog)](https://winscp.net/docs/ui_login_connection). |
124 | 121 |
|
125 |
| -The first step for troubleshooting FTP deployment is isolating a deployment issue from a runtime application issue. |
| 122 | +### How can I determine what method was used to deploy my app? |
126 | 123 |
|
127 |
| -A deployment issue typically results in no files or wrong files deployed to your app. You can troubleshoot by investigating your FTP deployment or selecting an alternate deployment path (such as source control). |
| 124 | +You can find out how an app was deployed by checking the application settings under **Settings** > **Environmental variables** in the Azure portal. Select the **App settings** tab. |
128 | 125 |
|
129 |
| -A runtime application issue typically results in the right set of files deployed to your app but incorrect app behavior. You can troubleshoot by focusing on code behavior at runtime and investigating specific failure paths. |
| 126 | +- If the app was deployed using an external package URL, you see the `WEBSITE_RUN_FROM_PACKAGE` setting in the application settings with a URL value. |
| 127 | +- If the app was deployed using ZIP deploy, you see the `WEBSITE_RUN_FROM_PACKAGE` setting with a value of `1`. |
130 | 128 |
|
131 |
| -To determine a deployment or runtime issue, see [Deployment vs. runtime issues](https://github.com/projectkudu/kudu/wiki/Deployment-vs-runtime-issues). |
| 129 | +If the app was deployed using Azure DevOps, you can see the deployment history in the Azure DevOps portal. If Azure Functions Core Tools was used, you can see the deployment history in the Azure portal. |
132 | 130 |
|
133 |
| -#### I'm not able to FTP and publish my code. How can I resolve the issue? |
134 |
| -Check that you entered the correct [hostname](#get-ftps-endpoint) and [credentials](#get-deployment-credentials). Check also that the following FTP ports on your machine aren't blocked by a firewall: |
| 131 | +<a name="what-can-happen-to-my-app-during-deployment"></a> |
| 132 | +[!INCLUDE [What can happen to my app during deployment?](../../includes/app-service-deploy-atomicity.md)] |
| 133 | + |
| 134 | +### What's the first step in troubleshooting FTP deployment? |
| 135 | + |
| 136 | +The first step for troubleshooting FTP deployment is distinguishing between deployment issues and runtime application issues. |
| 137 | + |
| 138 | +- A deployment issue typically results in no files or wrong files deployed to your app. You can troubleshoot by investigating your FTP deployment or selecting an alternate deployment path, such as source control. |
| 139 | +- A runtime application issue typically results in the right set of files deployed to your app but incorrect app behavior. You can troubleshoot by focusing on code behavior at runtime and investigating specific failure paths. |
| 140 | + |
| 141 | +For more information, see [Deployment vs. runtime issues](https://github.com/projectkudu/kudu/wiki/Deployment-vs-runtime-issues). |
| 142 | + |
| 143 | +### Why can't I FTP and publish my code? |
| 144 | + |
| 145 | +Check that you entered the correct [hostname](#get-ftp-endpoint) and [credentials](#get-deployment-credentials). Check also that the following FTP ports on your machine aren't blocked by a firewall: |
135 | 146 |
|
136 | 147 | - FTP control connection port: 21, 990
|
137 | 148 | - FTP data connection port: 989, 10001-10300
|
138 | 149 |
|
139 |
| -#### How can I connect to FTP in Azure App Service via passive mode? |
140 |
| -Azure App Service supports connecting via both Active and Passive mode. Passive mode is preferred because your deployment machines are usually behind a firewall (in the operating system or as part of a home or business network). See an [example from the WinSCP documentation](https://winscp.net/docs/ui_login_connection). |
| 150 | +### Why does my connection fail when attempting to connect over FTPS using explicit encryption? |
141 | 151 |
|
142 |
| -#### Why is my connection failing when attempting to connect over FTPS using explicit encryption? |
143 |
| -FTPS allows establishing the TLS secure connection in either an Explicit or Implicit way. |
| 152 | +FTPS allows establishing an Explicit or Implicit TLS secure connection. |
144 | 153 |
|
145 |
| - - If you connect with Implicit encryption, the connection is established via port 990. |
146 | 154 | - If you connect with Explicit encryption, the connection is established via port 21.
|
| 155 | + - If you connect with Implicit encryption, the connection is established via port 990. |
147 | 156 |
|
148 |
| -The URL format you use can affect your connection success, and it also depends on the client application you use. The portal shows the URL as `ftps://`, but note: |
149 |
| - |
150 |
| - - If the URL you connect with starts with `ftp://`, the connection is implied to be on port 21. |
151 |
| - - If it starts with `ftps://`, the connection is implied to be Implicit and on port 990. |
152 |
| - |
153 |
| - Make sure not to mix both, such as attempting to connect to `ftps://` and using port 21, as it will fail to connect, even if you wish to do Explicit encryption. This is due to an Explicit connection starting as a plain FTP connection before the AUTH method. |
| 157 | +The URL format you use can affect your connection success, depending on your client application. The portal might show the URL as `ftps://`, but if the URL you connect with starts with `ftp://`, the connection is implied to be on port 21. If the URL starts with `ftps://`, the connection is implied to be Implicit and on port 990. |
154 | 158 |
|
155 |
| -#### How can I determine the method that was used to deploy my Azure App Service? |
156 |
| -You can find out how an app was deployed by checking the application settings. If the app was deployed using an external package URL, you should see the `WEBSITE_RUN_FROM_PACKAGE` setting in the application settings with a URL value. Or if it was deployed using zip deploy, you should see the `WEBSITE_RUN_FROM_PACKAGE` setting with a value of `1`. If the app was deployed using Azure DevOps, you should see the deployment history in the Azure DevOps portal. If Azure Functions Core Tools is used, you should see the deployment history in the Azure portal. |
| 159 | +Make sure not to mix the settings, such as attempting to connect to `ftps://` by using port 21. This setting fails to connect even by using Explicit encryption, because an Explicit connection starts as a plain FTP connection before the AUTH method. |
157 | 160 |
|
158 |
| -## More resources |
| 161 | +## Related resources |
159 | 162 |
|
160 |
| -* [Local Git deployment to Azure App Service](deploy-local-git.md) |
161 |
| -* [Azure App Service Deployment Credentials](deploy-configure-credentials.md) |
162 |
| -* [Sample: Create a web app and deploy files with FTP (Azure CLI)](./scripts/cli-deploy-ftp.md). |
163 |
| -* [Sample: Upload files to a web app using FTP (PowerShell)](./scripts/powershell-deploy-ftp.md). |
| 163 | +- [Local Git deployment to Azure App Service](deploy-local-git.md) |
| 164 | +- [Azure App Service deployment credentials](deploy-configure-credentials.md) |
| 165 | +- [Sample: Create a web app and deploy files with FTP (Azure CLI)](./scripts/cli-deploy-ftp.md). |
| 166 | +- [Sample: Upload files to a web app using FTP (PowerShell)](./scripts/powershell-deploy-ftp.md). |
0 commit comments