Install and configure SonarQube for code quality analysis with PostgreSQL and SSL

Intermediate 45 min Apr 01, 2026 26 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up SonarQube Community Edition with PostgreSQL database backend, SSL/TLS encryption, and CI/CD integration for comprehensive static code analysis and security scanning.

Prerequisites

  • Server with 4GB+ RAM
  • Domain name with DNS access
  • Sudo privileges
  • Basic PostgreSQL knowledge

What this solves

SonarQube provides automated code quality analysis, security vulnerability detection, and technical debt measurement for your development projects. This tutorial sets up a production-ready SonarQube instance with PostgreSQL database backend, SSL encryption via reverse proxy, and integration points for CI/CD pipelines.

Step-by-step installation

Update system packages and install prerequisites

Start by updating your system and installing Java 17, which is required for SonarQube 10.x.

sudo apt update && sudo apt upgrade -y
sudo apt install -y openjdk-17-jre-headless wget unzip postgresql postgresql-contrib nginx certbot python3-certbot-nginx
sudo dnf update -y
sudo dnf install -y java-17-openjdk-headless wget unzip postgresql postgresql-server postgresql-contrib nginx certbot python3-certbot-nginx

Configure system limits for SonarQube

SonarQube requires specific kernel parameters and file limits to operate efficiently with Elasticsearch.

vm.max_map_count=524288
fs.file-max=131072
sudo sysctl -p /etc/sysctl.d/99-sonarqube.conf
sonarqube   -   nofile   131072
sonarqube   -   nproc    8192

Initialize PostgreSQL and create SonarQube database

Set up PostgreSQL database server and create a dedicated database and user for SonarQube.

sudo systemctl enable --now postgresql
sudo systemctl status postgresql
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
sudo systemctl status postgresql
sudo -u postgres createuser sonarqube
sudo -u postgres createdb -O sonarqube sonarqube
sudo -u postgres psql -c "ALTER USER sonarqube WITH ENCRYPTED PASSWORD 'SecureP@ssw0rd123';"

Create SonarQube system user

Create a dedicated system user to run SonarQube services securely without root privileges.

sudo useradd --system --no-create-home --shell /bin/false sonarqube
sudo mkdir -p /opt/sonarqube /var/log/sonarqube
sudo chown sonarqube:sonarqube /opt/sonarqube /var/log/sonarqube

Download and install SonarQube Community Edition

Download the latest SonarQube Community Edition and extract it to the installation directory.

cd /tmp
wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-10.3.0.82913.zip
unzip sonarqube-10.3.0.82913.zip
sudo mv sonarqube-10.3.0.82913/* /opt/sonarqube/
sudo chown -R sonarqube:sonarqube /opt/sonarqube

Configure SonarQube database connection

Configure SonarQube to connect to your PostgreSQL database with proper authentication.

# Database Configuration
sonar.jdbc.username=sonarqube
sonar.jdbc.password=SecureP@ssw0rd123
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonarqube

Web Server Configuration

sonar.web.host=127.0.0.1 sonar.web.port=9000 sonar.web.context=/

System Configuration

sonar.path.data=/opt/sonarqube/data sonar.path.temp=/opt/sonarqube/temp sonar.path.logs=/var/log/sonarqube

Security

sonar.forceAuthentication=true sonar.security.realm=sonar
sudo chown sonarqube:sonarqube /opt/sonarqube/conf/sonar.properties
sudo chmod 640 /opt/sonarqube/conf/sonar.properties

Create SonarQube systemd service

Set up a systemd service to manage SonarQube startup, shutdown, and automatic restart.

[Unit]
Description=SonarQube service
After=syslog.target network.target postgresql.service
Requires=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
TimeoutStartSec=5
SuccessExitStatus=143
KillMode=mixed

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable sonarqube

Configure NGINX reverse proxy with SSL

Set up NGINX as a reverse proxy to handle SSL termination and serve SonarQube over HTTPS.

server {
    listen 80;
    server_name sonar.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name sonar.example.com;

    # SSL Configuration (will be populated by certbot)
    
    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    
    # Proxy Configuration
    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $http_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;
        client_max_body_size 50m;
    }
    
    # Logs
    access_log /var/log/nginx/sonarqube.access.log;
    error_log /var/log/nginx/sonarqube.error.log;
}
sudo ln -s /etc/nginx/sites-available/sonarqube /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl enable --now nginx

Obtain SSL certificate with Let's Encrypt

Use Certbot to automatically obtain and configure SSL certificates for your domain.

Warning: Replace sonar.example.com with your actual domain name and ensure DNS is properly configured.
sudo certbot --nginx -d sonar.example.com
sudo systemctl enable certbot.timer

Configure firewall rules

Open necessary ports for HTTP/HTTPS traffic while keeping the SonarQube port (9000) internal.

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Start SonarQube service

Start SonarQube and monitor the startup process to ensure successful initialization.

sudo systemctl start sonarqube
sudo systemctl status sonarqube
sudo tail -f /var/log/sonarqube/sonar.log
Note: SonarQube startup can take 2-3 minutes. Wait for the message "SonarQube is operational" in the logs.

Configure LDAP authentication (optional)

Integrate SonarQube with your existing LDAP/Active Directory for centralized user management.

# LDAP Configuration
sonar.security.realm=LDAP
ldap.url=ldaps://ldap.example.com:636
ldap.bindDn=cn=sonar,ou=users,dc=example,dc=com
ldap.bindPassword=LdapBindPassword123

User Configuration

ldap.user.baseDn=ou=users,dc=example,dc=com ldap.user.request=(&(objectClass=inetOrgPerson)(uid={login})) ldap.user.realNameAttribute=cn ldap.user.emailAttribute=mail

Group Configuration

ldap.group.baseDn=ou=groups,dc=example,dc=com ldap.group.request=(&(objectClass=groupOfUniqueNames)(uniqueMember={dn})) ldap.group.idAttribute=cn

Configure performance settings

Optimize SonarQube performance based on your server resources and expected usage.

# Performance Tuning
sonar.web.javaOpts=-Xmx2g -Xms1g -XX:+HeapDumpOnOutOfMemoryError
sonar.ce.javaOpts=-Xmx2g -Xms1g -XX:+HeapDumpOnOutOfMemoryError
sonar.search.javaOpts=-Xmx1g -Xms1g -XX:MaxDirectMemorySize=512m -XX:+HeapDumpOnOutOfMemoryError

Database Connection Pool

sonar.jdbc.maxActive=60 sonar.jdbc.maxIdle=5 sonar.jdbc.minIdle=2 sonar.jdbc.maxWait=5000
sudo systemctl restart sonarqube

Set up backup automation

Create automated backup scripts for SonarQube configuration and PostgreSQL database.

#!/bin/bash
BACKUP_DIR="/backup/sonarqube"
DATE=$(date +%Y%m%d_%H%M%S)

Create backup directory

mkdir -p "$BACKUP_DIR"

Backup PostgreSQL database

pg_dump -U sonarqube -h localhost sonarqube | gzip > "$BACKUP_DIR/sonarqube_db_$DATE.sql.gz"

Backup SonarQube configuration

tar -czf "$BACKUP_DIR/sonarqube_config_$DATE.tar.gz" /opt/sonarqube/conf/

Cleanup old backups (keep 30 days)

find "$BACKUP_DIR" -name "sonarqube_*" -mtime +30 -delete echo "SonarQube backup completed: $DATE"
sudo chmod +x /opt/backup-sonarqube.sh
sudo chown root:root /opt/backup-sonarqube.sh
sudo crontab -e
# Daily SonarQube backup at 2 AM
0 2   * /opt/backup-sonarqube.sh >> /var/log/sonarqube-backup.log 2>&1

Verify your setup

Test your SonarQube installation and verify all components are working correctly.

# Check service status
sudo systemctl status sonarqube postgresql nginx

Test database connection

sudo -u postgres psql -d sonarqube -c "SELECT version();"

Check SonarQube logs

sudo tail -20 /var/log/sonarqube/sonar.log

Test web interface

curl -I https://sonar.example.com

Verify SSL certificate

echo | openssl s_client -connect sonar.example.com:443 -servername sonar.example.com 2>/dev/null | openssl x509 -noout -dates

Access your SonarQube instance at https://sonar.example.com and log in with the default credentials: username admin, password admin. You'll be prompted to change the password on first login.

CI/CD integration examples

GitLab CI integration

Configure GitLab CI to run SonarQube analysis on code commits and merge requests.

sonarqube-check:
  stage: test
  image: 
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  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_NAME}
      -Dsonar.sources=.
      -Dsonar.host.url=https://sonar.example.com
      -Dsonar.login=${SONAR_TOKEN}
  allow_failure: true
  only:
    - merge_requests
    - master
    - develop

Jenkins integration

Set up Jenkins pipeline to integrate SonarQube analysis with your build process.

pipeline {
    agent any
    
    environment {
        SONAR_TOKEN = credentials('sonar-token')
    }
    
    stages {
        stage('Build') {
            steps {
                // Your build steps
                sh 'mvn clean compile'
            }
        }
        
        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
        
        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar -Dsonar.projectKey=my-project'
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
    }
}

Common issues

SymptomCauseFix
SonarQube won't startInsufficient memory or wrong Java versionCheck java -version and increase heap size in sonar.properties
Database connection failedWrong credentials or PostgreSQL not runningVerify PostgreSQL status: sudo systemctl status postgresql
502 Bad Gateway on web interfaceSonarQube service not respondingCheck logs: sudo tail -f /var/log/sonarqube/sonar.log
SSL certificate errorsDomain mismatch or certificate expiredRun sudo certbot renew and verify domain configuration
LDAP authentication not workingWrong LDAP configuration or network issuesTest LDAP connection with ldapsearch tool
Analysis fails with permission errorsScanner can't write to temp directoriesEnsure CI runner has write access to project directory
Out of memory during analysisLarge codebase exceeds default limitsIncrease scanner memory: -Xmx2g in scanner options

Next steps

Automated install script

Run this to automate the entire setup

#sonarqube #code-quality-analysis #postgresql #ssl #devsecops

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer