SonarQube
Set up SonarQube for comprehensive code quality and security analysis. Learn configuration, quality gates, and CI/CD integration.
SonarQube is an open-source platform for continuous code quality and security inspection. It analyzes source code for bugs, vulnerabilities, and code smells across 30+ programming languages, making it a popular choice for enterprise DevSecOps pipelines.
SonarQube Architecture
SonarQube consists of three main components:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ SonarScanner │ ───▶ │ SonarQube │ ───▶ │ Database │
│ (CI Runner) │ │ Server │ │ (PostgreSQL) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Analyzes Processes Stores
source code results history
- SonarScanner — Runs in your CI/CD pipeline, analyzes code, sends results to server
- SonarQube Server — Web interface, API, rule engine, and compute engine
- Database — PostgreSQL, Oracle, or SQL Server (not embedded H2 for production)
Setting Up SonarQube with Docker
The fastest way to get started is with Docker:
# Create a network for SonarQube and PostgreSQL
docker network create sonarnet
# Start PostgreSQL database
docker run -d --name sonar-postgres \\
--network sonarnet \\
-e POSTGRES_USER=sonar \\
-e POSTGRES_PASSWORD=sonar_password \\
-e POSTGRES_DB=sonarqube \\
-v sonar_postgres_data:/var/lib/postgresql/data \\
postgres:15-alpine
# Start SonarQube server
docker run -d --name sonarqube \\
--network sonarnet \\
-p 9000:9000 \\
-e SONAR_JDBC_URL=jdbc:postgresql://sonar-postgres:5432/sonarqube \\
-e SONAR_JDBC_USERNAME=sonar \\
-e SONAR_JDBC_PASSWORD=sonar_password \\
-v sonar_data:/opt/sonarqube/data \\
-v sonar_extensions:/opt/sonarqube/extensions \\
-v sonar_logs:/opt/sonarqube/logs \\
sonarqube:lts-community
Important: Wait 1-2 minutes for SonarQube to initialize, then access http://localhost:9000.
Default credentials: admin / admin (change immediately after first login).
Docker Compose Setup
For a more maintainable setup, use Docker Compose:
# docker-compose.yml
version: '3.8'
services:
sonarqube:
image: sonarqube:lts-community
container_name: sonarqube
depends_on:
- db
ports:
- "9000:9000"
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarqube
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar_password
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
ulimits:
nofile:
soft: 65536
hard: 65536
db:
image: postgres:15-alpine
container_name: sonar-postgres
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar_password
POSTGRES_DB: sonarqube
volumes:
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql_data:
Start with docker compose up -d.
Configuring Your First Project
Step 1: Create a Project in SonarQube
- Log into SonarQube at
http://localhost:9000 - Click Create Project > Manually
- Enter a project key (e.g.,
my-webapp) and display name - Choose Locally for the analysis method (for initial setup)
- Generate a token and save it securely
Step 2: Create sonar-project.properties
In your project root, create a configuration file:
# sonar-project.properties
# Required: Unique project identifier
sonar.projectKey=my-webapp
# Optional but recommended
sonar.projectName=My Web Application
sonar.projectVersion=1.0.0
# Source code location (relative to this file)
sonar.sources=src
# Test code location
sonar.tests=tests
# Exclude files from analysis
sonar.exclusions=**/node_modules/**,**/vendor/**,**/*.min.js
# Language-specific settings (for Python example)
sonar.python.version=3.11
# Coverage report location (if using coverage tools)
sonar.python.coverage.reportPaths=coverage.xml
Step 3: Run the Scanner
Install and run SonarScanner:
# Install SonarScanner (macOS)
brew install sonar-scanner
# Or download from sonarqube.org and add to PATH
# Run the scan
sonar-scanner \\
-Dsonar.host.url=http://localhost:9000 \\
-Dsonar.token=your_generated_token
After the scan completes, view results in the SonarQube web interface.
Understanding SonarQube Metrics
SonarQube categorizes issues into several types:
Issue Types
| Type | Description | Example |
|---|---|---|
| Bug | Code that is demonstrably wrong | Null pointer dereference |
| Vulnerability | Security weakness | SQL injection, XSS |
| Code Smell | Maintainability issue | Duplicate code, long methods |
| Security Hotspot | Needs manual review | Hardcoded IP address |
Severity Levels
| Severity | Description |
|---|---|
| Blocker | Must be fixed immediately |
| Critical | High impact, fix soon |
| Major | Significant issue |
| Minor | Low impact |
| Info | Informational only |
Key Metrics
┌───────────────────────────────────────────────┐
│ Quality Gate: PASSED │
├───────────────────────────────────────────────┤
│ Bugs: 3 Vulnerabilities: 1 │
│ Code Smells: 47 Security Hotspots: 5 │
├───────────────────────────────────────────────┤
│ Coverage: 78% Duplications: 2.3% │
└───────────────────────────────────────────────┘
- Coverage — Percentage of code covered by tests
- Duplications — Percentage of duplicated code blocks
- Technical Debt — Estimated time to fix all code smells
Quality Gates
Quality Gates define the minimum quality standards for your project. If code fails the gate, the build should fail.
Default Quality Gate
SonarQube's default "Sonar way" quality gate requires:
- No new bugs
- No new vulnerabilities
- All security hotspots reviewed
- Code coverage on new code >= 80%
- Duplications on new code < 3%
Creating Custom Quality Gates
- Go to Quality Gates in the SonarQube UI
- Click Create
- Add conditions:
Condition: Coverage on New Code
Operator: is less than
Value: 80%
Status: Error
Example custom quality gate for security-focused projects:
| Condition | Operator | Value | Status |
|---|---|---|---|
| New Bugs | is greater than | 0 | Error |
| New Vulnerabilities | is greater than | 0 | Error |
| New Security Hotspots Reviewed | is less than | 100% | Error |
| New Code Coverage | is less than | 70% | Warning |
CI/CD Integration
GitHub Actions
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for blame information
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies and run tests
run: |
pip install -r requirements.txt
pip install pytest pytest-cov
pytest --cov=src --cov-report=xml
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
GitLab CI
# .gitlab-ci.yml
sonarqube-check:
stage: test
image: sonarsource/sonar-scanner-cli:latest
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- sonar-scanner
-Dsonar.projectKey=${CI_PROJECT_PATH_SLUG}
-Dsonar.host.url=${SONAR_HOST_URL}
-Dsonar.token=${SONAR_TOKEN}
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Jenkins Pipeline
// Jenkinsfile
pipeline {
agent any
environment {
SONAR_TOKEN = credentials('sonar-token')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build & Test') {
steps {
sh 'mvn clean verify'
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn sonar:sonar'
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 5, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
}
}
Security Rules Deep Dive
SonarQube includes extensive security rules based on OWASP, CWE, and SANS standards.
Vulnerability Categories
| Category | CWE | Example Rule |
|---|---|---|
| Injection | CWE-89 | SQL queries should not be vulnerable to injection |
| XSS | CWE-79 | HTTP responses should not be vulnerable to XSS |
| CSRF | CWE-352 | Server-side requests should not be vulnerable to forging |
| Hardcoded Secrets | CWE-798 | Credentials should not be hardcoded |
| Weak Crypto | CWE-327 | Cryptographic algorithms should be secure |
Viewing Security Reports
- Navigate to your project in SonarQube
- Click Security Reports in the left menu
- View reports by:
- OWASP Top 10 — Categorized by OWASP 2021 risks
- CWE Top 25 — Most dangerous software weaknesses
- Security Hotspots — Code requiring manual security review
Customizing Security Rules
Administration > Quality Profiles > [Your Profile] > Activate More Rules
Filter by:
- Tag: security, vulnerability, cwe-top-25
- Type: Vulnerability, Security Hotspot
- Severity: Blocker, Critical
Best Practices
1. Start with the Default Quality Gate
SonarQube's "Sonar way" gate is well-calibrated. Customize only after understanding your project's needs.
2. Focus on New Code
Don't try to fix all legacy issues at once. SonarQube's "Clean as You Code" approach focuses on keeping new code clean.
3. Review Security Hotspots Regularly
Hotspots are not confirmed vulnerabilities—they require human judgment. Schedule weekly reviews.
4. Integrate with Pull Requests
Block merges that fail the quality gate. This prevents new vulnerabilities from entering the main branch.
5. Exclude Generated Code
Don't waste time analyzing auto-generated files:
# sonar-project.properties
sonar.exclusions=**/generated/**,**/migrations/**,**/*.min.js
SonarQube Editions
| Feature | Community | Developer | Enterprise |
|---|---|---|---|
| Price | Free | Paid | Paid |
| Languages | 19+ | 24+ | 30+ |
| Branch Analysis | Main only | All branches | All branches |
| PR Decoration | No | Yes | Yes |
| SAST Depth | Basic | Advanced | Advanced |
| Portfolio Mgmt | No | No | Yes |
Community Edition is sufficient for most open-source projects. Developer Edition adds branch analysis and PR integration essential for enterprise workflows.
Troubleshooting
Common Issues
Scanner cannot connect to server:
# Check server is running
curl -s http://localhost:9000/api/system/status | jq
# Verify token is valid
curl -u your_token: http://localhost:9000/api/projects/search
Out of memory during analysis:
# Increase scanner memory
export SONAR_SCANNER_OPTS="-Xmx2048m"
sonar-scanner
Analysis takes too long:
# Limit scope in sonar-project.properties
sonar.exclusions=**/test/**,**/docs/**
sonar.cpd.exclusions=**/test/**
Key Takeaways
- SonarQube provides comprehensive analysis — Bugs, vulnerabilities, code smells, and coverage in one platform
- Quality Gates enforce standards — Block merges that don't meet your security requirements
- CI/CD integration is essential — Automate analysis on every commit
- Focus on new code — Don't get overwhelmed by legacy issues
- Review Security Hotspots — These require human judgment, not automated fixes
Next, we'll explore Semgrep for fast, customizable security scanning.
Found an issue?