How to Use SonarQube for Code Analysis (Community Build, Step by Step)
To use SonarQube for code analysis, start the server (the quickest way is docker run -d -p 9000:9000 sonarqube:community), create a project and an analysis token, and run the scanner for your language from your project folder. SonarQube then shows bugs, vulnerabilities, security hotspots and code smells. Add a quality gate to CI so new code with serious issues cannot be merged.
Quick answer
docker run -d --name sonarqube -p 9000:9000 sonarqube:community
# open http://<server>:9000, log in admin/admin, change the password,
# create a project "orders-api" and a token, then from the project folder:
mvn clean verify sonar:sonar -Dsonar.projectKey=orders-api \
-Dsonar.host.url=http://<server>:9000 -Dsonar.token=<token>
A live example first
We run SonarQube on a t3.medium EC2 instance (it needs about 2 GB of RAM; a t2.micro is too small), in a private subnet reached over a VPN.
- Set the kernel value that Elasticsearch inside SonarQube needs, then start it:
sudo sysctl -w vm.max_map_count=524288
docker run -d --name sonarqube -p 9000:9000 sonarqube:community
docker logs -f sonarqube | grep -m1 "SonarQube is operational"
- Open
http://<private-ip>:9000, log in withadmin/admin, and set a new password when asked. - Click Create project → Local project, name it
orders-api, and pick "Use the global setting" for new code. - Choose Locally, generate a token, and choose your build tool.
Now we scan a small Spring Boot app that has this method:
String sql = "SELECT * FROM orders WHERE customer = '" + name + "'";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
mvn clean verify sonar:sonar -Dsonar.projectKey=orders-api \
-Dsonar.host.url=http://10.0.2.15:9000 -Dsonar.token=sqp_xxx
The project page shows 1 Vulnerability (or a Security Hotspot, depending on the rules) on that line, with a message along the lines of "Change this code to not construct SQL queries directly from user-controlled data." We change it to a PreparedStatement with ? and scan again. The finding disappears and the quality gate shows Passed. Friends, the tool explained the risk in plain words and pointed to the exact line.
How does SonarQube work?
The scanner sends results to the server, and the quality gate decides if new code can be merged.
There are two parts. The server stores rules, history and results and shows the web UI. The scanner runs where your code is (your laptop or a CI runner), reads the code, and sends a report to the server. The server then applies the quality gate. The default gate, "Sonar way", focuses on new code, so an old project can start today without fixing ten years of issues first.
What the results mean
| Type | Meaning | Example |
|---|---|---|
| Bug | Code that will probably break | Null pointer on a path you can reach |
| Vulnerability | Code that can be attacked | SQL built from user input |
| Security Hotspot | Sensitive code a human must review | Hard-coded IP, weak hash, CORS * |
| Code smell | Hard to maintain | A 300-line method, duplicated blocks |
| Coverage | Lines run by tests | Needs a test report (JaCoCo, lcov, coverage.xml) |
Scan each language
Java (Maven or Gradle)
mvn clean verify sonar:sonar -Dsonar.projectKey=orders-api -Dsonar.token=$SONAR_TOKEN
For Gradle, add the org.sonarqube plugin and run ./gradlew sonar. Add JaCoCo to get coverage.
.NET
dotnet tool install --global dotnet-sonarscanner
dotnet sonarscanner begin /k:"billing-api" /d:sonar.host.url="http://10.0.2.15:9000" /d:sonar.token="$SONAR_TOKEN"
dotnet build
dotnet sonarscanner end /d:sonar.token="$SONAR_TOKEN"
Node.js / TypeScript, Python, PHP, Go and Ruby (sonar-scanner CLI)
Create sonar-project.properties in the project root:
sonar.projectKey=web-frontend
sonar.sources=src
sonar.exclusions=**/node_modules/**,**/vendor/**
sonar.javascript.lcov.reportPaths=coverage/lcov.info
Then run the scanner in Docker so you do not install anything:
docker run --rm -e SONAR_HOST_URL=http://10.0.2.15:9000 -e SONAR_TOKEN=$SONAR_TOKEN \
-v "$PWD:/usr/src" sonarsource/sonar-scanner-cli
| Language | Coverage report key |
|---|---|
| JavaScript / TypeScript | sonar.javascript.lcov.reportPaths |
| Python | sonar.python.coverage.reportPaths (coverage.xml) |
| PHP | sonar.php.coverage.reportPaths (clover.xml) |
| Go | sonar.go.coverage.reportPaths (coverage.out) |
Add the quality gate to CI
GitHub Actions
- uses: SonarSource/sonarqube-scan-action@v4
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
- uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Jenkins
Install the SonarQube Scanner plugin, then use withSonarQubeEnv('sonar') { sh 'mvn sonar:sonar' } followed by waitForQualityGate abortPipeline: true.
Keep SonarQube itself secure
- Change the default admin password on first login.
- In Administration → Security, turn on Force user authentication.
- Keep it in a private subnet, reached through a VPN or bastion.
- Use project tokens in CI, stored as CI secrets, never in the repo.
- Use PostgreSQL for anything beyond a lab (the built-in H2 database is for evaluation only).
Real example
In October 2020 the FBI published a flash alert saying that attackers had been stealing source code from US government agencies and companies through SonarQube servers exposed to the internet with default settings, such as the default admin password. A tool meant to make code safer leaked it instead. That is why step 1 above is "change the password" and step 3 is "keep it private".
Mistakes to avoid
- Gating on overall code on day one. The project fails forever. Gate on new code.
- Marking every hotspot "Safe" without reading. Each one needs a short reason.
- Thinking SonarQube replaces other tests. Pair it with dependency scanning (Trivy) and DAST in staging.
Summary table
| Step | Command / place |
|---|---|
| Run the server | docker run -p 9000:9000 sonarqube:community |
| Java | mvn sonar:sonar / ./gradlew sonar |
| .NET | dotnet sonarscanner begin/end |
| JS, Python, PHP, Go | sonar-scanner-cli + sonar-project.properties |
| CI gate | Quality gate action / waitForQualityGate |
| Secure it | New password, force auth, private network |
Quick quiz: check what you learned
What kind of testing does SonarQube do?
- Static analysis of source code
- Load testing of web servers
- Scanning cloud IP addresses
- Fuzzing a running binary
Show answer
A. SonarQube reads the code without running it.
What is a quality gate?
- Pass or fail rules for new code
- A firewall in front of the server
- A Docker network for scanners
- A list of approved IDE plugins
Show answer
A. The gate checks conditions such as new critical issues and coverage.
Which tool fits library CVEs better than SonarQube Community?
- Trivy or Dependency-Check
- The SonarLint IDE plugin
- A Git pre-push hook only
- The Jenkins Blue Ocean UI
Show answer
A. SCA tools match library versions against CVE databases.
Why keep SonarQube off the public internet?
- It stores your source code
- It needs port 22 to work
- It blocks the CI runners
- It can only run on a VPN
Show answer
A. An exposed instance can leak private code.
Learn it properly
These pages go deeper, with labs:
Frequently asked questions
What is SonarQube used for?
SonarQube reads your source code without running it (static analysis) and reports bugs, security vulnerabilities, security hotspots, code smells, duplication and test coverage.
Is SonarQube free?
The Community Build is free and open source and covers many languages. Paid editions add branch analysis, more security rules and more languages.
What is a security hotspot?
Code that touches something sensitive, such as a hard-coded IP or a weak hash, that a person must review. It is not always a bug.
What is a quality gate?
A set of pass/fail conditions, like "no new critical vulnerabilities" and "80% coverage on new code". CI can stop a merge when it fails.
Does SonarQube find vulnerable libraries?
Mostly no in the Community Build. Use Trivy, OWASP Dependency-Check or npm audit for library CVEs. SonarQube focuses on your own code.
Should SonarQube be open to the internet?
No. It holds your source code. Keep it behind a VPN or private network, with a strong admin password and no anonymous access.