SonarQube Hosted On Azure App Service

Developer Support

This post is provided by Premier Field Engineer, Nathan Vanderby, who simplifies the setup of a SonarQube server with one step using Azure App Services.


SonarQube is tool that centralizes static code analysis and unit test coverage. It can be used across multiple languages and for a single project up to enterprise scale.

SQProject

There are various guides on how to setup SonarQube hosted in Azure. From hosting it on a virtual machine (here and here) to a docker image or a Linux container in an Azure App Service. There are also instructions for using IIS as a reverse proxy to allow SSL traffic for additional security.

There is another project out there to try and simplify setting up a SonarQube server that is publicly accessible. The project is SonarQube-AzureAppService. It use the HttpPlatformHandler extension from IIS which can similarly be used to host SonarQube on-prem with IIS directly.

SonarQube-AzureAppService

Project URL: https://github.com/vanderby/SonarQube-AzureAppService

This project simplifies the setup of a SonarQube server to one step. Simply click the Deploy to Azure link on the project homepage and follow the simple walkthrough to have resources deployed out and configured. The initial start time for SonarQube may take up to 10 minutes on slower resources. That’s all! Read below for more in depth details on what’s going on behind the scenes.

Deploying Azure Resources

The Deploy To Azure button on the GitHub repository uses the azuredeploy.json project file to deploy an ARM template. The ARM template defines a simple App Service Plan, Web App and the code from the GitHub repository. The code is pushed to the repository folder in the web app. Within the project a .deployment file defines a deployment script to execute.

DeployToAzure

On a side note, at the time of writing the minimum App Service Plan tier is Basic. The Free and Shared tiers throw an error on startup related to Java memory restrictions with the default SonarQube settings.

Deployment Script

The deployment script is Deploy-SonarQuveAzureAppService.ps1. This script copies the wwwroot folder from the repo, which contains the web.config and HttpPlatformHandlerStartup.ps1 files, to the web app wwwroot folder. I’ll walk through these files later. It also downloads and extracts the latest SonarQube binaries. I’ve removed the logging and error handling lines for brevity in the code block below.

xcopy wwwroot ..\wwwroot /Y    
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$global:progressPreference = 'SilentlyContinue'
$downloadSource = 'https://binaries.sonarsource.com/Distribution/sonarqube/'
$allDownloads = Invoke-WebRequest -Uri $downloadSource -UseBasicParsing
$zipFiles = $allDownloads[0].Links | Where-Object { $_.href.EndsWith('.zip') -and !($_.href.contains('alpha') -or $_.href.contains('RC')) }
$latestFile = $zipFiles[-1]
$downloadUri = $downloadSource + $latestFile.href
$outputFile = "..\wwwroot\$($latestFile.href)"
Invoke-WebRequest -Uri $downloadUri -OutFile $outputFile -UseBasicParsing
Expand-Archive -Path $outputFile -DestinationPath ..\wwwroot

Once the deployment is complete your web app wwwroot folder should have a sonarqube folder and just a few files. You could also manually upload sonarqube binaries.

AzureDeployFiles

Runtime Files

This project was made possible due to how an app service hosts Java applications. It does this using the HttpPlatformHandler extension. This extension will start any executable defined in the web.config and forward any requests it receives to the port defined by the HTTP_PLATFORM_PORT environment variable. This environment variable is randomly set by the HttpPlatformHandler when it invokes the startup executable.

Web.Config

The web.config file shown below is very simple. It adds the HttpPlatformHandler extension to the handlers then defines the behavior of the HttpPlatformHandler. The handler itself is told to run PowerShell and execute the HttpPlatformHandlerStartup.ps1 script. We will go into details of this script later. It also tells the handler to log stdout messages, do not retry the startup and wait 300 seconds before timeout on startup. We want a long startup timeout since SonarQube takes a while to start. Especially the first time if your using an in-memory database.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" requireAccess="Script" />
    </handlers>
    <httpPlatform stdoutLogEnabled="true" startupTimeLimit="300" startupRetryCount="0"
	  processPath="%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" 
	  arguments="%home%\site\wwwroot\HttpPlatformHandlerStartup.ps1"> 
    </httpPlatform>
  </system.webServer>
</configuration>
HttpPlatformHandlerStartup.ps1

This script writes the HTTP_PLATFORM_PORT port to the sonar.properties file, updates the wrapper.conf with the java.exe location and runs StartSonar.bat. The most important thing happening here is setting the HTTP_PLATFORM_PORT as it is randomized each time the application is started. I’ve removed the logging and error handling lines for brevity in the code block below.

$port = $env:HTTP_PLATFORM_PORT
$propFile = Get-ChildItem 'sonar.properties' -Recurse    
$configContents = Get-Content -Path $propFile.FullName -Raw
$configContents -ireplace '#?sonar.web.port=.+', "sonar.web.port=$port" | Set-Content -Path $propFile.FullName
$wrapperConfig = Get-ChildItem 'wrapper.conf' -Recurse
$wrapperConfigContents = Get-Content -Path $wrapperConfig.FullName -Raw
$wrapperConfigContents -ireplace 'wrapper.java.command=java', 'wrapper.java.command=%JAVA_HOME%\bin\java' | Set-Content -Path $wrapperConfig.FullName
$startScript = Get-ChildItem 'StartSonar.bat' -Recurse
& $startScript[-1].FullName

On another side note, the script executes the last StartSonar.bat file it finds so that it runs the script from the x64 folder and not the x86 if present.

Hopefully this is helpful if you are looking at setting up a cloud based SonarQube server.

4 comments

Discussion is closed. Login to edit/delete existing comments.

  • Imad Sabonji 1

    is there a way to enable to autoupdates? otherwise, how can we update the SonarQube version?

    • Nathan Vanderby 1

      To update you could create a deployment slot then re-run Deploy-SonarQubeAzureAppService.ps1 script to pull down the latest bits. Then do a slot swap when things are complete. Don’t forget to take a backup of the database before upgrading it.

  • DevOps 0

    Hi,

    need some help, my Sonarqube which is installed as an app service on Azure is getting erased automatically every 5 days. I am losing all projects and user profiles.

    Any idea how to resolve this issue ?

    Thanks

  • Luis de Diego 0

    How much does it cost? I’m aksing because azure show me a “purchase” button to your templates and i need to give some reason to my boss.

Feedback usabilla icon