FTP deploy from Azure DevOps

FTP deploy from Azure DevOps article image

Here follows a guide of how to setup Azure DevOps (former VSTS) to deploy from a Git repository to a web server via FTP.

Demo Project Prep

I´ve prepared a Git demo project in ADO containing HTML and CSS that we are going to deploy.


Head over to the Build and release section to create a new pipeline. We will use this to deploy the demo project.


In the visual designer for your new pipeline, select where to find the project to be deployed and click the continue button. I think mostly of these settings are pretty self-explanatory.


We will not using any preconfigured templates in this guide so click the Empty job link to start on a fresh pipe. You should now get some defaults: Pipeline, Get sources and Agent Job.

Setting up a new deploy


In the build pipeline section, give the build a name. I will call this Demo Project Release.

When queue a build, it executes on an agent from a selected pool. In this case we will use a Microsoft-hosted pool.

Get sources

The Get sources section should have the settings needed already. Most of the job was done in the first step – when defining our repository. Just give it a decent name.

Agent job

Give your agent a name. I will use Deploy agent. Leave the rest of the settings as-is.

Add Copy Files task

Now we will start adding tasks to our new agent. Click the plus icon and find the Copy Files task. Click Add to add task to the agent.

The Copy Files task will be used to copy files from source folder to target folder using a match pattern. It allows us to control which files to copy and which files to exclude. Use the screenshot below to define your settings.

For the source folder we will use a predefined build variable: $(Build.SourcesDirectory). This represents the local path on the agent where the source code files are downloaded.

In Contents setting we define the file paths to include as part of the copy. This pattern will match all files on the first line. On the second and third line we will omit the .git folder and the README.md file using the !-character. So in short: Take all files but ignore .git and README.md.

As the target folder we will use $(Build.ArtifactStagingDirectory) build variable followed by the  \deploy path. The variable represents the local path on the agent where any artifacts are copied to before being pushed to their destination.

Add FTP Upload task

Add a new task and select the FTP Upload agent task. It allows us to upload files to a remote machine using the File Transfer Protocol (FTP), or securely with FTPS.

Important: To preserve file paths, make sure this is checked!

Put your FTP settings into the FTP Upload task configuration fields. As root folder we will use the same value as for the target folder in the Copy Files task. The file pattern will be ** as for all files. No need for filtering as it was done in the previous task. The remote directory needs to match the correct path on your remote server.

Now it´s time to save your work and queue up a new build and release.

Save & queue

Press the Save & queue button and give your save a name. Press the blue Save & queue to save your new build definition and to queue up a new build. You should see a message at top of the screen saying something like: Build #108 has been queued. Click on the build number to see and follow the build and release process. When done you should see the following status in the logs section.

And if logging into the server using a FTP client you should see the files deployed into the specified folder.

And the final result visiting the index.htm in a browser. Yey!

Wrapping up

The reason writing this guide was that I had some struggling setting up a release flow via FTP for a web application project. Although it result in quite a small pipeline flow (with no separate release pipe), it took some time getting things correctly configured. Hope it helps someone out.

Really love the possibilites to automate the release management. It lets us focus on the things we love – developing – minimizing the risks associated with manual deployments.