Setting Up Static Code Analysis with SonarQube

Traducciones al Español
Estamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
Create a Linode account to try this guide with a $ credit.
This credit will be applied to any valid services used during your first  days.

SonarQube gives you a tool for automating and managing static code analyses, with a host of features like issue reports and customized quality gates. SonarQube stands out further by integrating with a range of other tools, from project frameworks like Maven to CI/CD pipelines like Jenkins.

In this guide, learn everything you need to get started using SonarQube. The guide walks you through setting up your own SonarQube server. And it demonstrates how to integrate SonarQube with your projects by using it with an example Maven project.

Before You Begin

  1. If you have not already done so, create a Linode account and Compute Instance. See our Getting Started with Linode and Creating a Compute Instance guides.

  2. Follow our Setting Up and Securing a Compute Instance guide to update your system. You may also wish to set the timezone, configure your hostname, create a limited user account, and harden SSH access.

Note
The steps in this guide are written for non-root users. Commands that require elevated privileges are prefixed with sudo. If you’re not familiar with the sudo command, see the Linux Users and Groups guide.

What Is Static Code Analysis?

Static code analysis reviews code for issues, bugs, and standards violations. On the one hand, static code analysis goes deeper and wider in its review than the grammar and error checking done by compilers and interpreters. On the other hand, static code analysis automates code review and can often catch issues that a human code review may miss.

Tools for static code analysis can prevent potential issues from reaching production environments, and they can also enforce coding standards and legibility in your codebase.

You can learn more about static code analysis and what it has to offer in our What is Static Code Analysis? guide.

Why SonarQube?

SonarQube is a tool that automates static code reviews by integrating with your projects. SonarQube covers a wide range of programming languages, with useful code standards built in. At the same time, SonarQube is capable of integrating with several project frameworks, from Maven to .NET, or using its CLI tool.

SonarQube emphasizes integration with CI/CD and DevOps platforms. There, working as part of your GitHub workflows or Jenkins pipelines, SonarQube can automatically enforce quality gates and reporting.

How to Install SonarQube

SonarQube runs as a self-hosted server. Projects can then add the SonarScanner plugin or CLI, together with a token generated in your SonarQube instance, to request code analyses from the server.

So, to start, you need to install SonarQube and start running the SonarQube server. This tutorial does so using Docker Compose, which lets you manage the SonarQube server and database implementation from one source.

Install Docker and Docker Compose

These next steps show you how to install Docker with the Docker Compose plugin on Debian and Ubuntu and CentOS and Fedora systems. For other operating systems and distributions, refer to the official instructions for installing Docker Engine along with the Docker Compose plugin.

On Debian and Ubuntu

  1. Remove any existing Docker installations.

    sudo apt remove docker docker-engine docker.io containerd runc
  2. Install the prerequisite packages for adding the Docker repository to the APT package manager.

    sudo apt install ca-certificates curl gnupg lsb-release
  3. Add the GPG key for the Docker repository to the APT package manager. Replace debian in the URL in this command with ubuntu if you are on an Ubuntu distribution.

    sudo mkdir -m 0755 -p /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
  4. Add the Docker repository to the APT package manager. Again, replace debian in the command’s URL with ubuntu if you are on an Ubuntu distribution.

    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  5. Update the APT indices, and install the Docker Engine along with the Docker Compose plugin.

    sudo apt update
    sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

CentOS and Fedora

  1. Remove any existing Docker installations.

    sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
  2. Install the core plugins for the DNF package manager. These give you access to tools for managing DNF repositories.

    sudo dnf -y install dnf-plugins-core
  3. Add the Docker repository to the DNF package manager. Replace centos in the URL in this command with fedora if you are on a Fedora distribution.

    sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
  4. Install the Docker Engine along with the Docker Compose plugin.

    sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    You may be prompted to verify the GPG key, and you should see the following key listed.

    060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35

Completing the Installation

Following either installation path, you can ensure that the Docker daemon is running with the command here.

sudo systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2023-02-16 20:38:07 UTC; 1s ago
     Docs: https://docs.docker.com

If it is not running (active), enable and start the Docker daemon with these commands.

sudo systemctl enable docker
sudo systemctl start docker

Finally, you should add your limited user to the Docker user group. Otherwise, you would need to run Docker commands as root, or with sudo. Replace example-user with the username for your limited user.

sudo usermod -aG docker example-user

For this last change to take effect, you have to restart your shell session, which you can do by exiting and reentering it.

Prepare the System

SonarQube requires you to make certain adjustments to system settings. This includes opening the port that SonarQube runs on, and also includes changing limits for map count, files, and threads.

  1. Open the port for SonarQube in your system’s firewall. By default, SonarQube uses port 9000, and you can use the commands here to open that port.

    • On Debian and Ubuntu:

      sudo ufw allow 9000/tcp
    • On CentOS and Fedora:

      sudo firewall-cmd --zone=public --add-port=9000/tcp --permanent
      sudo firwall-cmd --reload
  2. SonarQube requires the limits for map counts, files, and threads to be set at least to certain values, shown here. These commands create dedicated files for the configurations, making the settings persistent.

    sudo tee /etc/sysctl.d/99-sonarqube.conf > /dev/null <<EOF
    vm.max_map_count=524288
    fs.file-max=131072
    ulimit -n 131072
    ulimit -u 8192
    EOF
    sudo tee /etc/security/limits.d/99-sonarqube.conf > /dev/null <<EOF
    sonarqube   -   nofile   131072
    sonarqube   -   nproc   8192
    EOF
  3. Reboot the system for the changed limits to take effect.

    sudo reboot

Install and Start Running SonarQube

Now your system is ready to host a SonarQube server. Since this setup uses Docker Compose, the actual installation process entails creating a Compose definition file and running it.

If you are, instead, interested in a more traditional installation for your SonarQube instance, you can see the steps outlined in the official installation documentation.

  1. Create and change into a new directory for the Docker Compose setup.

    mkdir ~/sonarqube-compose
    cd ~/sonarqube-compose
  2. Within that directory, create a docker-compose.yml file. Give that file the contents here.

    File: docker-compose.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    version: "3"
    
    services:
      sonarqube:
        image: sonarqube:community
        depends_on:
          - db
        environment:
          SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
          SONAR_JDBC_USERNAME: sonar
          SONAR_JDBC_PASSWORD: sonar
        volumes:
          - sonarqube_data:/opt/sonarqube/data
          - sonarqube_extensions:/opt/sonarqube/extensions
          - sonarqube_logs:/opt/sonarqube/logs
        ports:
          - "9000:9000"
      db:
        image: postgres:12
        environment:
          POSTGRES_USER: sonar
          POSTGRES_PASSWORD: sonar
        volumes:
          - postgresql:/var/lib/postgresql
          - postgresql_data:/var/lib/postgresql/data
    
    volumes:
      sonarqube_data:
      sonarqube_extensions:
      sonarqube_logs:
      postgresql:
      postgresql_data:

    This defines a basic SonarQube setup. The definition includes the community edition of the sonarqube Docker image, running it with the required volumes. And there is a definition for a PostgreSQL database server as well, which the SonarQube server uses to persist data.

  3. Start running the Docker Compose setup for SonarQube by executing the following command within the directory with the docker-compose.yml file.

    docker compose up -d

    Docker Compose downloads and prepares the necessary resources and starts up the PostgreSQL and SonarQube servers. From here, you can control the servers using Docker Compose commands.

    Warning
    Avoid using the -v option with the docker compose down command, or using the docker volume prune or docker system prune commands. Doing so may remove your otherwise persistent data.

Access the Interface

With docker compose up, your SonarQube server should be running and available to start using. To get started, you should log in, both to set a password for your administrator user and to get familiar with the interface.

  1. In a web browser, navigate to port 9000 on your SonarQube server’s public IP address, or domain name if you have one set up. This takes you to the SonarQube login page.

    SonarQube login page

  2. Log into your SonarQube server with the credentials here.

    • Username: admin

    • Password: admin

    SonarQube prompts you immediately to change the password for this admin user.

    SonarQube prompting to change initial administrator password

After creating a new password for the administrator user, SonarQube directs you to the dashboard for your server. This dashboard gives you access to the tools you need to start analyzing your code and the reports for your analyses.

The initial dashboard for SonarQube

The dashboard starts with a prompt to create a new project, and the guide picks up with that further on in the next section.

How to Analyze Code with SonarQube

With a SonarQube server established, your next step is enabling SonarQube code analyses for one of your projects. To show you how, this section of the guide walks you through creating a simple example project with Maven and Spring Boot. The example shows you how to add the SonarScanner plugin for a Maven project and how to start scanning.

Additionally, the example shows how to enable projects and review analysis reports from within the SonarQube interface. These steps apply to a wide range of project types. And, moreover, going through them can give you a clearer idea of what SonarQube can do and how to make the most of it.

Setting Up an Example Project

SonarQube uses the SonarScanner to scan and analyze a project’s code. The SonarScanner itself can be either a plugin for your project framework, or the CLI tool for any unsupported projects types.

You can see a list of SonarScanner options in the SonarQube documentation.

The example project for this guide uses Maven, for which there is a SonarScanner plugin that can readily fit into the project. Follow along here to create the project and see how to add the SonarScanner plugin to it.

Installing Maven

Since this project uses the Maven framework to create a base Java web application, you need to have Maven itself installed.

  1. Navigate to the Maven download page, and identify the URL for the latest Maven version.

  2. Download the package with the latest Maven binary, and move the binary directory to a centralized directory on your system. Replace the download URL and filename below with what you found in the previous step.

    cd ~/
    wget https://dlcdn.apache.org/maven/maven-3/3.9.1/binaries/apache-maven-3.9.1-bin.tar.gz
    tar xzvf apache-maven-3.9.1-bin.tar.gz
    sudo mv apache-maven-3.9.1 /usr/local/maven
  3. Create a shell script as part of your shell profile. This adds two necessary environment variables — for the locations of Java and Maven — and adds the Maven binary directory to your shell path.

    sudo tee "/etc/profile.d/maven.sh" > /dev/null <<'EOF'
    export JAVA_HOME=/usr/lib/jvm/jre-openjdk
    export MAVEN_HOME=/usr/local/maven
    export PATH=${PATH}:/usr/local/maven/bin
    EOF
    sudo chmod +x /etc/profile.d/maven.sh
  4. Either exit and reopen the shell or use the command below to load the new script above to the current shell profile.

    source /etc/profile.d/maven.sh
  5. Verify that the Maven binary is installed and accessible.

    mvn --version
    Apache Maven 3.9.1 (2e178502fcdbffc201671fb2537d0cb4b4cc58f8)
    Maven home: /usr/local/maven
    Java version: 17.0.6-ea, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-17-openjdk-17.0.6.0.9-0.3.ea.el8.x86_64
    Default locale: en_US, platform encoding: UTF-8
    OS name: "linux", version: "4.18.0-483.el8.x86_64", arch: "amd64", family: "unix"
  6. Open the Maven global settings file, at /usr/local/maven/conf/settings.xml in this case, and make the following changes to it:

    • Within the <pluginGroups> block, add the <pluginGroup> line here to enable the SonarScanner plugin.

      File: settings.xml
      1
      2
      3
      4
      5
      
      [...]
      <pluginGroups>
        <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
      </pluginGroups>
      [...]
    • Within the <profiles> block, add the <profile> block shown below for the SonarScanner plugin. Replace SONARQUBE_URL in this example with the actual URL for your SonarQube server. Alternatively, remove the <sonar.host.url> block if you want to use localhost.

      File: settings.xml
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      [...]
      <profiles>
      [...]
      
        <profile>
          <id>sonar</id>
          <activation>
            <activeByDefault>true</activeByDefault>
          </activation>
          <properties>
            <sonar.host.url>
              http://SONARQUBE_URL:9000
            </sonar.host.url>
          </properties>
        </profile>
      </profiles>

Creating a Spring Boot Project

You can now use Maven to create your base project. To start with a useful base for a web application, this guide leverages the Spring Boot framework. The guide also relies on the Spring Boot CLI to initialize the project, saving you from having to create the necessary files and directories manually.

  1. Install the Spring Boot CLI. Visit the documentation for installing the Spring Boot CLI to find the URL for the latest stable version, and replace the URL in the command below with that.

    wget https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-cli/3.0.5/spring-boot-cli-3.0.5-bin.tar.gz
    tar xzvf spring-boot-cli-3.0.5-bin.tar.gz
    sudo mv spring-3.0.5 /usr/local/spring
  2. As with the Maven installation, create a shell script for your shell profile, adding the Spring CLI binary to the shell path.

    sudo tee "/etc/profile.d/spring.sh" > /dev/null <<'EOF'
    export SPRING_HOME=/usr/local/spring
    export PATH=${PATH}:/usr/local/spring/bin
    EOF
    sudo chmod +x /etc/profile.d/spring.sh
  3. Either exit and reopen the shell or run the command here for the changes to the shell path to take effect.

    source /etc/profile.d/spring.sh

    You can then verify the installation by checking the spring version.

    spring --version
    Spring CLI v3.0.5
  4. Create a Spring Boot project. This example command creates a new directory for the project, then names the project example-java-project. The command additionally defines the group for the project, com.example.app. Lastly, the resulting zip file is extracted, creating the project subdirectories.

    mkdir ~/example-java-project
    cd ~/example-java-project
    spring init --group-id=com.example.app \
    --artifact-id=example-java-project \
    --build=maven --language=java \
    --java-version=17
    unzip example-java-project.zip
    rm example-java-project.zip
  5. Open the pom.xml file, and add the <plugin> block shown below at the end of the <plugins> block that should already be in the file. You should also first identify the latest version of the plugin to use here.

    File: pom.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [...]
            <plugin>
              <groupId>org.sonarsource.scanner.maven</groupId>
              <artifactId>sonar-maven-plugin</artifactId>
              <version>3.9.1.2184</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>

Adding the Project to SonarQube

The last step for setting up your project with SonarQube is to create a project item within the SonarQube server interface. Doing so gives you a token to use with the Maven project, allowing you to trigger scans from there.

  1. Open the SonarQube interface again, and select the Manually option from the list of options for creating a project.

  2. Enter a name and a key for the project. This guide uses the name from the Maven project, example-java-project, for both of these fields.

    Naming a new SonarQube project

  3. Choose Locally for the prompt on how SonarQube should analyze the project.

    Selecting to analyze a new SonarQube project locally

  4. Generate a token on the resulting page, giving the token a name and choosing an expiration period for it. Keep track of this token for use within your Maven project in the next section.

    Generating a token for a new SonarQube project

Running and Reviewing the Analysis

All that remains to test out SonarQube’s code analysis is to run the SonarScanner against the example project. At this point, everything is set up to run a scan manually with the Maven project manager.

  1. Run the command here to set up your Maven project with its dependencies and to execute the initial code scan. Replace SONARQUBE_PROJECT_TOKEN with the project token you generated for the project within the SonarQube interface.

    mvn clean verify sonar:sonar -Dsonar.projectKey=example-java-project   -Dsonar.projectName='example-java-project' -Dsonar.token=SONARQUBE_PROJECT_TOKEN

    On subsequent runs, you can shorten the command like you see below, assuming you have not made any changes to the project’s dependencies.

    mvn sonar:sonar -Dsonar.projectKey=example-java-project   -Dsonar.projectName='example-java-project' -Dsonar.token=SONARQUBE_PROJECT_TOKEN
  2. Navigate to the project page within the SonarQube server interface, and see SonarQube’s analysis results.

    An overview of a project analysis in SonarQube

The Spring Boot base project fails SonarQube’s analysis. To understand why, navigate to the Issues tab, where you can find a description for the issue.

The list of issues on a scan from SonarQube

SonarQube found that a test case within the project does not have any assertions, which it flags as an error. You can use this interface to manage the error, redefining it, for instance, or giving this instance a pass, or closing the issue as resolved.

You can get more details still by selecting the issue. There, you can see the offending code snippet as well as an explanation as to why SonarQube marks this as an error.

A code snippet from an error found on a SonarQube scan

Conclusion

You now have an operating SonarQube server, and an example Maven project to start building off of for your own projects. SonarQube integrates with a wide range of project frameworks, and you can see more on those from the link further above.

One of the other benefits of SonarQube is its integration with CI/CD pipelines, like Jenkins. And you can start getting an idea for what that might look like through our Jenkins CI/CD on Linode to Any Hyperscaler reference architecture. The architecture gives a robust CI/CD system and includes a code analysis step.

To keep learning what SonarQube is capable of, be sure to look over the official SonarQube documentation linked below. There, you can see more of what the tool is capable of and how to get the most out of it.

More Information

You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

This page was originally published on


Your Feedback Is Important

Let us know if this guide was helpful to you.


Join the conversation.
Read other comments or post your own below. Comments must be respectful, constructive, and relevant to the topic of the guide. Do not post external links or advertisements. Before posting, consider if your comment would be better addressed by contacting our Support team or asking on our Community Site.
The Disqus commenting system for Linode Docs requires the acceptance of Functional Cookies, which allow us to analyze site usage so we can measure and improve performance. To view and create comments for this article, please update your Cookie Preferences on this website and refresh this web page. Please note: You must have JavaScript enabled in your browser.