SonarQube Kurulumu ve Kod Kalitesi Analizi
Kod kalitesi meselesi çoğu zaman “sonra hallederiz” kategorisine giriyor. Sprint baskısı var, deadline yaklaşıyor, feature çıkması lazım. Sonunda teknik borç birikmeye başlıyor ve bir gün bakıyorsunuz ki codebase’in yarısı kimsenin dokunmak istemediği karanlık bir bölgeye dönmüş. SonarQube tam da bu noktada devreye giriyor; size hem anlık bir rapor hem de uzun vadeli kod sağlığı takibi sunuyor. Ben de bu yazıda sıfırdan kurulumdan gerçek anlamda kullanışlı bir analiz ortamı kurmaya kadar her şeyi aktaracağım.
SonarQube Nedir, Ne Değildir
Önce şunu netleştirelim: SonarQube bir sihir değil. Kodu sizin yerinize temizlemiyor, mimari kararlarınızı vermiyor. Ama şunları yapıyor: bug potansiyeli taşıyan kod bloklarını işaretliyor, güvenlik açıklarını (vulnerability) ve güvenlik hotspot’larını raporluyor, kod tekrarını (duplication) ölçüyor, test coverage’ınızı görselleştiriyor ve teknik borcu sayısal olarak ifade ediyor.
Community Edition ücretsiz ve birçok dil için yeterli. Java, JavaScript, TypeScript, Python, C#, PHP, Go ve daha fazlasını destekliyor. Enterprise ihtiyaçlarınız varsa Developer veya Enterprise Edition’a geçebilirsiniz ama çoğu ekip için Community Edition başlangıç için fazlasıyla yeterli.
Sistem Gereksinimleri
SonarQube, Elasticsearch üzerine kurulu olduğu için kaynak gereksinimlerine dikkat etmek gerekiyor. Kurulum öncesi şunlara bakın:
- RAM: Minimum 2 GB, önerilen 4 GB. Elasticsearch tek başına 512 MB ile 2 GB arasında bellek kullanıyor.
- CPU: 2 core yeterli başlangıç için, yoğun analiz ortamında 4 core önerilir.
- Disk: Proje sayısına göre değişir, başlangıç için 20 GB yeterli.
- Java: SonarQube 10.x sürümleri JDK 17 gerektiriyor.
- Veritabanı: PostgreSQL 13+ önerilen. H2 embedded sadece test için kullanılmalı, production’da kesinlikle kullanmayın.
- OS: Linux için
vm.max_map_countvefs.file-maxdeğerlerini ayarlamak şart.
Sistem Hazırlığı
Önce kernel parametrelerini ayarlayalım. Bu adımı atladığınızda Elasticsearch başlamıyor:
# /etc/sysctl.conf dosyasına ekleyin
sudo sysctl -w vm.max_map_count=524288
sudo sysctl -w fs.file-max=131072
# Kalıcı hale getirmek için
echo "vm.max_map_count=524288" | sudo tee -a /etc/sysctl.conf
echo "fs.file-max=131072" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Kullanıcı limitleri için /etc/security/limits.conf dosyasına şunları ekleyin:
sudo tee -a /etc/security/limits.conf << 'EOF'
sonarqube - nofile 131072
sonarqube - nproc 8192
EOF
SonarQube için ayrı bir kullanıcı oluşturun, root ile çalıştırmayın:
sudo useradd -r -m -U -d /opt/sonarqube -s /bin/bash sonarqube
PostgreSQL Kurulumu ve Yapılandırması
# Ubuntu/Debian için
sudo apt update
sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable postgresql
sudo systemctl start postgresql
# Veritabanı ve kullanıcı oluşturma
sudo -u postgres psql << 'EOF'
CREATE USER sonarqube WITH ENCRYPTED PASSWORD 'guclu_bir_sifre_koyun';
CREATE DATABASE sonarqube OWNER sonarqube;
GRANT ALL PRIVILEGES ON DATABASE sonarqube TO sonarqube;
EOF
SonarQube Kurulumu
En güncel Community Edition sürümünü indirip kuralım:
SONAR_VERSION="10.4.1.88267"
cd /tmp
wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONAR_VERSION}.zip
sudo apt install -y unzip
sudo unzip sonarqube-${SONAR_VERSION}.zip -d /opt
sudo mv /opt/sonarqube-${SONAR_VERSION} /opt/sonarqube
# Sahipliği sonarqube kullanıcısına ver
sudo chown -R sonarqube:sonarqube /opt/sonarqube
Şimdi temel yapılandırmayı yapalım. /opt/sonarqube/conf/sonar.properties dosyasını düzenleyin:
sudo -u sonarqube tee /opt/sonarqube/conf/sonar.properties << 'EOF'
# Veritabanı bağlantısı
sonar.jdbc.username=sonarqube
sonar.jdbc.password=guclu_bir_sifre_koyun
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonarqube
# Web sunucu ayarları
sonar.web.host=0.0.0.0
sonar.web.port=9000
sonar.web.context=/
# Elasticsearch
sonar.search.javaOpts=-Xmx512m -Xms512m -XX:MaxDirectMemorySize=256m
# Web JVM
sonar.web.javaOpts=-Xmx512m -Xms128m
# Compute Engine
sonar.ce.javaOpts=-Xmx512m -Xms128m
# Log dizini
sonar.path.logs=logs
sonar.path.data=data
sonar.path.temp=temp
EOF
Systemd Servisi Oluşturma
sudo tee /etc/systemd/system/sonarqube.service << 'EOF'
[Unit]
Description=SonarQube service
After=syslog.target network.target postgresql.service
[Service]
Type=forking
ExecStart=/opt/sonarqube/bin/linux-x86-64/sonar.sh start
ExecStop=/opt/sonarqube/bin/linux-x86-64/sonar.sh stop
User=sonarqube
Group=sonarqube
Restart=always
LimitNOFILE=131072
LimitNPROC=8192
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable sonarqube
sudo systemctl start sonarqube
Başlamasını bekleyin, Elasticsearch yüzünden ilk açılış 2-3 dakika sürebilir:
# Log takibi
sudo tail -f /opt/sonarqube/logs/sonar.log
sudo tail -f /opt/sonarqube/logs/web.log
# Servis durumu
sudo systemctl status sonarqube
Kurulum başarılıysa http://sunucu_ip:9000 adresine gidin. Varsayılan kullanıcı adı ve şifre admin/admin. İlk girişte şifre değiştirmenizi isteyecek, bunu kesinlikle yapın.
Nginx ile Ters Proxy Yapılandırması
Production ortamında SonarQube’u direkt 9000 portunda açık bırakmak yerine Nginx arkasına almak daha doğru:
sudo apt install -y nginx
sudo tee /etc/nginx/sites-available/sonarqube << 'EOF'
server {
listen 80;
server_name sonar.sirketiniz.com;
# HTTP'yi HTTPS'ye yönlendir
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name sonar.sirketiniz.com;
ssl_certificate /etc/letsencrypt/live/sonar.sirketiniz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sonar.sirketiniz.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 50M;
location / {
proxy_pass http://localhost:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/sonarqube /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
SonarScanner Kurulumu
SonarQube sunucusu hazır, şimdi analizi çalıştıracak aracı kuralım. SonarScanner’ı kod analizi yapılacak makinelere veya CI/CD agent’larına kuruyoruz:
SCANNER_VERSION="5.0.1.3006"
cd /tmp
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SCANNER_VERSION}-linux.zip
unzip sonar-scanner-cli-${SCANNER_VERSION}-linux.zip
sudo mv sonar-scanner-${SCANNER_VERSION}-linux /opt/sonar-scanner
# PATH'e ekle
echo 'export PATH=$PATH:/opt/sonar-scanner/bin' | sudo tee /etc/profile.d/sonar-scanner.sh
source /etc/profile.d/sonar-scanner.sh
# Test
sonar-scanner --version
İlk Proje Analizi
Bir Java Maven projesi için örnek sonar-project.properties dosyası:
# Proje kimliği - SonarQube'da görünecek isim
sonar.projectKey=my-java-app
sonar.projectName=My Java Application
sonar.projectVersion=1.0
# Kaynak kodun yolu
sonar.sources=src/main/java
sonar.tests=src/test/java
# Java için bytecode yolu (coverage için gerekli)
sonar.java.binaries=target/classes
sonar.java.test.binaries=target/test-classes
# JaCoCo coverage raporu
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
# Encoding
sonar.sourceEncoding=UTF-8
# SonarQube sunucu adresi
sonar.host.url=https://sonar.sirketiniz.com
Analizi çalıştırmak için:
# Token ile kimlik doğrulama (önerilen yöntem)
sonar-scanner
-Dsonar.projectKey=my-java-app
-Dsonar.sources=.
-Dsonar.host.url=https://sonar.sirketiniz.com
-Dsonar.token=sqp_xxxxxxxxxxxxxxxxxxxxxxxxx
GitLab CI Entegrasyonu
Gerçek hayatta analizi elle çalıştırmıyorsunuz. CI/CD pipeline’ınıza entegre etmek asıl hedef. İşte GitLab CI için bir .gitlab-ci.yml örneği:
stages:
- build
- test
- sonar-analysis
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
cache:
paths:
- .m2/repository
- .sonar/cache
build:
stage: build
image: maven:3.9-eclipse-temurin-17
script:
- mvn compile
test:
stage: test
image: maven:3.9-eclipse-temurin-17
script:
- mvn test jacoco:report
artifacts:
paths:
- target/
sonar-analysis:
stage: sonar-analysis
image: maven:3.9-eclipse-temurin-17
script:
- mvn sonar:sonar
-Dsonar.projectKey=$CI_PROJECT_NAME
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
only:
- main
- merge_requests
GitLab’da SONAR_HOST_URL ve SONAR_TOKEN değişkenlerini Settings > CI/CD > Variables altına ekleyin. Token’ı SonarQube arayüzünden My Account > Security > Generate Tokens bölümünden alabilirsiniz. Token’ı protected ve masked olarak işaretlemeyi unutmayın.
Quality Gate Yapılandırması
Quality Gate, analizin “geçti mi geçmedi mi” kararını veren kural setidir. Varsayılan “Sonar way” gate’ini production için biraz sıkılaştırabilirsiniz. SonarQube arayüzünden Quality Gates > Create ile yeni bir gate oluşturun.
Tipik bir production Quality Gate kriterleri şöyle olabilir:
- Coverage on New Code: 80%’den az ise başarısız
- Duplicated Lines on New Code: 3%’den fazla ise başarısız
- Maintainability Rating on New Code: A veya B değilse başarısız
- Reliability Rating on New Code: A değilse başarısız
- Security Rating on New Code: A değilse başarısız
- Security Hotspots Reviewed on New Code: 100% değilse başarısız
“New Code” kavramı önemli: SonarQube, son analiz tarihinden itibaren değişen satırları yeni kod olarak değerlendiriyor. Bu sayede legacy bir projeyi baştan mükemmel yapmaya çalışmak yerine, sadece yeni yazdığınız kodun kalitesini korumak üzerine odaklanabiliyorsunuz. Hem daha gerçekçi hem de ekip motivasyonu açısından çok daha sağlıklı bir yaklaşım.
Önemli Güvenlik Ayarları
Kurulumu bitirdikten sonra bazı güvenlik adımları şart:
# Anonim erişimi kapatın - sonar.properties dosyasına ekleyin
echo "sonar.forceAuthentication=true" >> /opt/sonarqube/conf/sonar.properties
# Servis tokenları için ayrı hesaplar oluşturun
# Administration > Security > Users bölümünden
# "ci-bot" gibi bir service account oluşturun
# ve bu hesaba sadece "Execute Analysis" yetkisi verin
sudo systemctl restart sonarqube
SonarQube’u internet’e açık tutuyorsanız, arayüzde Administration > Security bölümünden şunları kontrol edin:
- Force user authentication: Açık olmalı
- Anyone group: Hiçbir şeye erişimi olmamalı
- Default admin şifresi değiştirilmiş olmalı
Performans Sorunlarında Yapılacaklar
Ekip büyüdükçe ve proje sayısı arttıkça SonarQube yavaşlayabiliyor. Yaşadığım senaryolarda şu çözümler işe yaradı:
Compute Engine queue’u doluyorsa (Administration > Projects > Background Tasks) birden fazla CE worker açabilirsiniz. Bunun için lisans gerekiyor ancak şunu da yapabilirsiniz: büyük projeleri gece analiz edilecek şekilde schedule’layın, küçük projeleri gündüz.
Elasticsearch disk I/O problemi sık karşılaşılan bir durum. Mümkünse SonarQube data dizinini SSD’ye alın:
# sonar.properties dosyasında data dizinini değiştirin
sonar.path.data=/mnt/ssd-disk/sonarqube/data
sonar.path.temp=/mnt/ssd-disk/sonarqube/temp
# Dizinleri oluşturun ve izinleri ayarlayın
sudo mkdir -p /mnt/ssd-disk/sonarqube/{data,temp}
sudo chown -R sonarqube:sonarqube /mnt/ssd-disk/sonarqube
Log rotasyonu için /opt/sonarqube/conf/sonar.properties dosyasına:
# Log seviyeleri - production'da INFO yeterli
sonar.log.level=INFO
sonar.log.level.web=INFO
sonar.log.level.ce=INFO
sonar.log.level.es=INFO
# Log rotation - her biri max 20MB, 5 dosya tut
sonar.log.maxFiles=5
sonar.log.maxFileSize=20MB
Docker ile Hızlı Test Ortamı
Production’a geçmeden önce ya da geliştirici makinelerinde hızlıca denemek için Docker Compose kullanabilirsiniz:
# docker-compose.yml
version: "3.8"
services:
sonarqube:
image: sonarqube:10.4-community
container_name: sonarqube
depends_on:
- sonarqube-db
environment:
SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_extensions:/opt/sonarqube/extensions
ports:
- "9000:9000"
ulimits:
nofile:
soft: 131072
hard: 131072
sonarqube-db:
image: postgres:15
container_name: sonarqube-db
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar
volumes:
- sonarqube_db:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_logs:
sonarqube_extensions:
sonarqube_db:
# vm.max_map_count ayarını unutmayın, Docker için de gerekli
sudo sysctl -w vm.max_map_count=524288
docker-compose up -d
docker-compose logs -f sonarqube
Sonuç
SonarQube’u kurmak aslında hikayenin küçük bir parçası. Asıl mesele ekibin bu aracı benimsemesi ve Quality Gate kriterlerini ciddiye alması. “Analiz kırmızı ama biz yine de merge ettik” durumu yaşanmaya başlarsa, tool’un hiçbir değeri kalmıyor.
Benim önerim şu: ilk kurulumda Quality Gate’i çok sıkı tutmayın. Mevcut projeyi sıfır hata ile geçirecek şekilde ayarlayın, sonra her sprint’te biraz daha sıkılaştırın. Ekip “kalite = engel” yerine “kalite = standart” olarak görmeye başladığında iş değişiyor.
Teknik borç raporlamasını sprint planning toplantılarına dahil edin. “Bu sprint 2 gün teknik borç ödeyeceğiz” diyebilmek için önce onu sayısal olarak görebilmeniz gerekiyor. SonarQube bunu sağlıyor. Geri kalanı ekip kültürü meselesi.
Son bir not: sürüm güncellemelerini takip edin. SonarQube güvenlik yamaları ve dil desteği güncellemeleri açısından sık güncelleniyor. Her major versiyon upgrade öncesi mutlaka backup alın; PostgreSQL dump’ı ve SonarQube data dizininin yedeği hayat kurtarıyor.
