Deploy to a Linux Virtual Machine


If you want to deploy your application to a Linux virtual machine using the classic editor, see Deploy web apps to Linux VMs.

Azure Pipelines provides a complete, fully featured set of CI/CD automation tools for deployments to virtual machines.

You can use continuous integration (CI) and continuous deployment (CD) to build, release, and deploy your code. Learn how to set up a CI/CD pipeline for multi-machine deployments.

This article covers how to set up continuous deployment of your app to a web server running on Ubuntu. You can use these steps for any app that publishes a web deployment package.

Get your sample code

If you already have an app in GitHub that you want to deploy, you can create a pipeline for that code.

If you are a new user, fork this repo in GitHub:


Petclinic is a Spring Boot application built using Maven.

Prerequisites for the Linux VM

Use Ubuntu 16.04 for this quickstart. Follow additional steps for Java or JavaScript.

Create an environment with virtual machines

Virtual machines can be added as resources within environments and can be targeted for multi-VM deployments. The deployment history view provides traceability from the VM to the commit.

You can create an environment in Environments within Pipelines.

  1. Sign into your Azure DevOps organization and navigate to your project.

  2. Navigate to the Pipelines page. Select Environments and click Create Environment. Specify a Name (required) for the environment and a Description.

  3. Choose Virtual Machines as a Resource to be added to the environment. Click Next.

  4. Choose the Windows or Linux for the Operating System and copy PS registration script.

  5. Run the copied script from an administrator PowerShell command prompt on each of the target VMs registered with this environment.


    • The Personal Access Token (PAT) of the logged in user is pre-inserted in the script and expires after three hours.
    • If your VM already has any agent running on it, provide a unique name to register with environment.
  6. Once VM is registered, it will start appearing as an environment resource under Resources.


  7. To add more VMs, copy the script again. Click Add resource and choose Virtual Machines. This script is the same for all the VMs you want to add to the same environment.

  8. Each machine interacts with Azure Pipelines to coordinate deployment of your app.


  9. You can add or remove tags for the VM. Click on the dots at the end of each VM resource in Resources. The tags you assign allow you to limit deployment to specific VMs when the environment is used in a deployment job. Tags are each limited to 256 characters, but there is no limit to the number of tags you can create.


Define your CI build pipeline

You'll need a continuous integration (CI) build pipeline that publishes your web application and a deployment script that can be run locally on the Ubuntu server. Set up a CI build pipeline based on the runtime you want to use.

  1. Sign in to your Azure DevOps organization and navigate to your project.

  2. In your project, navigate to the Pipelines page. Then choose the action to create a new pipeline.

  3. Walk through the steps of the wizard by first selecting GitHub as the location of your source code.

  4. You may be redirected to GitHub to sign in. If so, enter your GitHub credentials.

  5. When the list of repositories appears, select your desired sample app repository.

  6. Azure Pipelines will analyze your repository and recommend a suitable pipeline template.

Select the starter template and copy this YAML snippet to build your Java project and runs tests with Apache Maven:

- job: Build
    displayName: Build Maven Project
    - task: Maven@3
      displayName: 'Maven Package'
        mavenPomFile: 'pom.xml'
    - task: CopyFiles@2
      displayName: 'Copy Files to artifact staging directory'
        SourceFolder: '$(System.DefaultWorkingDirectory)'
        Contents: '**/target/*.?(war|jar)'
        TargetFolder: $(Build.ArtifactStagingDirectory)
    - upload: $(Build.ArtifactStagingDirectory)
      artifact: drop

For more guidance, follow the steps mentioned in Build your Java app with Maven for creating a build.

Define CD steps to deploy to the Linux VM

  1. Edit your pipeline and include a deployment job by referencing the environment and the VM resources you created earlier:

    - deployment: VMDeploy
      displayName: web
        name:  <environment name>
        resourceType: VirtualMachine
        tags: web1
  2. You can select specific sets of virtual machines from the environment to receive the deployment by specifying the tags that you have defined for each virtual machine in the environment. Here is the complete YAML schema for Deployment job.

  3. You can specify either runOnce or rolling as a deployment strategy.

    runOnce is the simplest deployment strategy. All the life-cycle hooks, namely preDeploy deploy, routeTraffic, and postRouteTraffic, are executed once. Then, either on: success or on: failure is executed.

    Below is an example YAML snippet for runOnce :

    - deployment: VMDeploy
      displayName: web
        vmImage: 'Ubuntu-16.04'
        name: <environment name>
        resourceType: VirtualMachine
            - script: echo my first deployment
  4. Below is an example YAML snippet for the rolling strategy. You can update up to 5 targets gets in each iteration. maxParallel will determine the number of targets that can be deployed to, in parallel. The selection accounts for absolute number or percentage of targets that must remain available at any time excluding the targets that are being deployed to. It is also used to determine the success and failure conditions during deployment.

    - deployment: VMDeploy
      displayName: web
        name: <environment name>
        resourceType: VirtualMachine
            maxParallel: 2  #for percentages, mention as x%
              - download: current
                artifact: drop
              - script: echo initialize, cleanup, backup, install certs
              - task: Bash@3
                  targetType: 'inline'
                  script: |
                    # Modify deployment script based on the app type
                    echo "Starting deployment script run"
                    sudo java -jar '$(Pipeline.Workspace)/drop/**/target/*.jar'
              - script: echo routing traffic
              - script: echo health check post-route traffic
                - script: echo Restore from backup! This is on failure
                - script: echo Notify! This is on success

    With each run of this job, deployment history is recorded against the <environment name> environment that you have created and registered the VMs.

Pipeline traceability views in environment

The Deployments view provides complete traceability of commits and work items, and a cross-pipeline deployment history per environment.



Next Steps

To learn more about the topics in this guide see Jobs, Tasks, Catalog of Tasks, Variables, Triggers, or Troubleshooting.

To learn what else you can do in YAML pipelines, see YAML schema reference.