Automated Deployment of FastAPI Applications With Azure Pipelines

Automated Deployment of FastAPI Applications With Azure Pipelines

In today's fast-paced development world, keeping your application up to date manually is crucial. However, manual updates can be time-consuming and error-prone. That's where Azure Pipelines comes to the rescue. In this article, I will explore how to set up an automated deployment pipeline that makes updating your FastAPI app as simple as a few clicks.

Prerequisites: Before diving into the nitty-gritty, here's what you'll need:

  • An Azure account (if you don't have one, sign up for a free one).

  • Your source code is hosted on Azure repos.

  • A secure shell (SSH) key to access your server.

  • A target server (in our case, an Ubuntu VM).

I am assuming that you can deploy the FastAPI application in the Ubuntu server with Nginx. If you are not able to do this, no worries. Just follow the article here.

Firstly, let’s create a file named azure-pipelines.yml and follow the below instructions.

trigger:
- main
pool:
  vmImage: 'ubuntu-latest'
steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '3.x'
      addToPath: true
      architecture: 'x64'
  • The trigger section specifies when the pipeline should run. In this case, it triggers when there are changes to the main branch.

  • The pool section specifies the agent and environment for the pipeline. It uses the ubuntu-latest image.

  • This step sets up the Python environment for the pipeline. It specifies to use Python 3. x, adding Python to the PATH, and using the x64 architecture.

The next steps focus on downloading the SSH key, preparing it, and using it for secure server access. It is important that I have stored the ubuntu-vm.pem file in the Secure files of the Azure Pipelines library for security reasons.

  - task: DownloadSecureFile@1
    displayName: 'Download SSH Key'
    inputs:
      secureFile: ubuntu-vm.pem'
  - script: |
      echo 'The PEM file has been downloaded to $(Agent.TempDirectory)'
      chmod 600 $(Agent.TempDirectory)/ubuntu-vm.pem
    displayName: 'Prepare SSH Key'
  • The DownloadSecureFile task fetches the SSH key (ubuntu-vm.pem) securely.

  • The subsequent script task prepares the key by ensuring it has the appropriate permissions.

Now, the script starts the server-related actions, such as updating the application and installing requirements:

- script: |
      ssh -i $(Agent.TempDirectory)/ubuntu-vm.pem -o StrictHostKeyChecking=no root@20.30.40.50 "cd /home/root/backend/fastcraft && git checkout main && git pull && exit"
    displayName: 'Update from Git'
  - script: |
      ssh -i $(Agent.TempDirectory)/ubuntu-vm.pem -o StrictHostKeyChecking=no root@20.30.40.50 "cd /home/root/backend/fastcraft && source venv/bin/activate && pip install -r requirements.txt  && exit"
    displayName: 'Install Requirements'
  • The first script updates the application by logging into the server, navigating to the project directory, checking out the main branch, and pulling the latest code from Git.

  • The second script activates a virtual environment and installs Python package requirements from requirements.txt.

After that, I move on to installing custom packages from Azure Repos. One of these packages I have installed and are using is called luminous which is a custom package and it's private. It's like adding an extra layer of security and a better logging facility.

- script: |
   # Install the 'luminous' package from the azure repos
   ssh -i $(Agent.TempDirectory)/ubuntu-vm.pem -o StrictHostKeyChecking=no root@20.30.40.50 "cd /home/root/backend/fastcraft && source venv/bin/activate && pip uninstall -y luminous && pip install --no-cache-dir git+https://$(AZURE_DEVOPS_USERNAME):$(AZURE_DEVOPS_PAT)@dev.roni.com/Software-Porjects/Security%20Research/_git/luminous@main#egg=luminous"
 displayName: 'Install luminous package'
  • These scripts install custom Python packages (luminous) from Azure Repos.

  • To add the AZURE_DEVOPS_USERNAME and AZURE_DEVOPS_PAT variables in Azure Pipelines, navigate to your pipeline settings, and you can easily configure these variables as shown in the attached screenshot. This ensures secure access to your repository within your pipeline.

The final step restarts the backend service to apply the updates:

  - script: |
      ssh -i $(Agent.TempDirectory)/ubuntu-vm.pem -o StrictHostKeyChecking=no root@20.30.40.50 "cd /home/root/backend/fastcraft && sudo systemctl restart backend && exit"
    displayName: 'Deploy 🤘'
  • This script restarts the backend service using systemctl to ensure the updates take effect.

I think you already pushed this .yml file in Azure Repos main branch. So let’s do the rest of the things in the Azure DevOpsportal. Now Just follow the blew instructions:

  • Navigate to Pipelines: Inside your project, go to Pipelines. You should see options for Pipelines and Releases. Click on Pipelines.

  • Create a New Pipeline: Click the New Pipeline button to start creating a new pipeline.

  • Connect to Your Repository: Azure DevOps will guide you to connect to your repository. Select the repository you want to build a pipeline for.

  • Configure Your Pipeline: You will be prompted to choose how you want to set up your pipeline. Select "YAML" since you have a YAML script.

  • YAML Configuration: Copy and paste your provided YAML script into the YAML editor.

  • Variable Substitution (Optional): If your YAML script contains variables like $(AZURE_DEVOPS_USERNAME) and $(AZURE_DEVOPS_PAT), you need to define these variables in the pipeline settings. Click on "Variables" to define them. I have already included a screenshot a little earlier, which demonstrates the process.

  • Save and Run: Once you have pasted the script and defined any necessary variables, save the pipeline configuration. You can also set up triggers (e.g., branch triggers) as per your project's needs.

By following these steps, you can configure and run your pipeline for your repository. The pipeline will execute the tasks specified in your YAML script, automating the deployment of your FastAPI application on the Ubuntu server.