How to Install and Configure SonarQube on RHEL 7
SonarQube is an open-source platform for continuous code quality inspection and static analysis. It detects bugs, vulnerabilities, code smells, and security hotspots across dozens of programming languages, integrating naturally into CI/CD pipelines to enforce quality gates before code reaches production. On RHEL 7, setting up SonarQube involves installing Java 11, provisioning a PostgreSQL database, configuring the SonarQube server itself, running it as a non-root service user, exposing it behind an Nginx reverse proxy, and connecting a project scanner. This tutorial covers every step in detail.
Prerequisites
- RHEL 7 server with at least 4 GB RAM and 2 CPU cores (8 GB RAM recommended for production)
- Root or sudo access
- Ports 9000 (SonarQube), 5432 (PostgreSQL), and 80/443 (Nginx) available
- Active RHEL subscription or access to a configured yum repository for base packages
wgetorcurlfor downloading archives
Step 1: Install Java 11
SonarQube 9.x and later require Java 11. RHEL 7 ships with Java 8 in its standard repositories, so install OpenJDK 11 from the official channel:
sudo yum install -y java-11-openjdk java-11-openjdk-devel
If multiple Java versions are installed, set Java 11 as the default using alternatives:
sudo alternatives --config java
# Select the entry pointing to /usr/lib/jvm/java-11-openjdk-.../bin/java
java -version
# openjdk version "11.0.x" ...
Set the JAVA_HOME environment variable system-wide:
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk' | sudo tee /etc/profile.d/java.sh
source /etc/profile.d/java.sh
echo $JAVA_HOME
Step 2: Configure System Limits for Elasticsearch
SonarQube ships with an embedded Elasticsearch instance that requires elevated OS resource limits. Without these settings, Elasticsearch will fail to start:
# Increase virtual memory map count (required by Elasticsearch)
sudo sysctl -w vm.max_map_count=524288
sudo sysctl -w fs.file-max=131072
# Make these settings persistent across reboots
cat >> /etc/sysctl.conf <<'EOF'
vm.max_map_count=524288
fs.file-max=131072
EOF
# Increase ulimits for the sonarqube service user
cat >> /etc/security/limits.conf <<'EOF'
sonarqube - nofile 131072
sonarqube - nproc 8192
EOF
Step 3: Install and Configure PostgreSQL
SonarQube requires an external relational database for production use. Install PostgreSQL 13 from the official PostgreSQL yum repository:
# Install the PostgreSQL 13 repo RPM
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install PostgreSQL 13 server
sudo yum install -y postgresql13-server postgresql13
# Initialize the database cluster
sudo /usr/pgsql-13/bin/postgresql-13-setup initdb
# Enable and start PostgreSQL
sudo systemctl enable postgresql-13
sudo systemctl start postgresql-13
sudo systemctl status postgresql-13
Create the SonarQube database user and database:
sudo -u postgres psql <<'EOF'
CREATE USER sonarqube WITH PASSWORD 'StrongSonarPassword1!';
CREATE DATABASE sonardb OWNER sonarqube ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE template0;
GRANT ALL PRIVILEGES ON DATABASE sonardb TO sonarqube;
q
EOF
Update /var/lib/pgsql/13/data/pg_hba.conf to allow password authentication from localhost:
# Edit the pg_hba.conf — change the local/host entries for the sonardb
sudo sed -i 's/^host all all 127.0.0.1/32 ident/host all all 127.0.0.1/32 md5/'
/var/lib/pgsql/13/data/pg_hba.conf
sudo systemctl reload postgresql-13
Step 4: Create the SonarQube System User
SonarQube must not run as root. Create a dedicated service account:
sudo useradd --system --no-create-home --shell /bin/false sonarqube
Step 5: Download and Install SonarQube
# Download SonarQube Community Edition
SONAR_VERSION="10.4.1.88267"
cd /tmp
wget "https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONAR_VERSION}.zip"
# Install unzip if needed
sudo yum install -y unzip
# Extract to /opt
sudo unzip "sonarqube-${SONAR_VERSION}.zip" -d /opt
sudo mv /opt/sonarqube-${SONAR_VERSION} /opt/sonarqube
# Set ownership to the sonarqube user
sudo chown -R sonarqube:sonarqube /opt/sonarqube
Step 6: Configure sonar.properties
Edit the main configuration file at /opt/sonarqube/conf/sonar.properties:
sudo vi /opt/sonarqube/conf/sonar.properties
Set the following properties (uncomment and modify the relevant lines):
# Database connection
sonar.jdbc.username=sonarqube
sonar.jdbc.password=StrongSonarPassword1!
sonar.jdbc.url=jdbc:postgresql://localhost/sonardb
# Web server
sonar.web.host=0.0.0.0
sonar.web.port=9000
sonar.web.context=/
# Elasticsearch
sonar.search.port=9001
sonar.search.host=127.0.0.1
# Logs
sonar.log.level=INFO
sonar.path.logs=/opt/sonarqube/logs
sonar.path.temp=/opt/sonarqube/temp
# JVM options (tune heap for your server's RAM)
sonar.web.javaOpts=-Xmx1g -Xms512m -XX:+HeapDumpOnOutOfMemoryError
sonar.ce.javaOpts=-Xmx2g -Xms1g -XX:+HeapDumpOnOutOfMemoryError
sonar.search.javaOpts=-Xmx1g -Xms512m
Step 7: Create a systemd Service for SonarQube
sudo tee /etc/systemd/system/sonarqube.service <<'EOF'
[Unit]
Description=SonarQube service
After=network.target postgresql-13.service
Requires=postgresql-13.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=300
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable sonarqube
sudo systemctl start sonarqube
# Monitor the startup (takes 1-3 minutes)
sudo tail -f /opt/sonarqube/logs/sonar.log
Wait until you see SonarQube is up in the log before proceeding.
Step 8: Configure Nginx as a Reverse Proxy
Install Nginx and configure it to proxy requests to SonarQube on port 9000:
sudo yum install -y nginx
sudo tee /etc/nginx/conf.d/sonarqube.conf <<'EOF'
server {
listen 80;
server_name sonar.example.com;
access_log /var/log/nginx/sonar.access.log;
error_log /var/log/nginx/sonar.error.log;
# Increase max body size for uploading analysis reports
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1: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_read_timeout 300;
}
}
EOF
sudo nginx -t
sudo systemctl enable nginx
sudo systemctl start nginx
Open the firewall to allow HTTP traffic:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Step 9: Initial Admin Login and Configuration
Open a browser and navigate to http://sonar.example.com (or http://<server-ip>:9000 if Nginx is not yet configured). Log in with the default credentials:
- Username: admin
- Password: admin
SonarQube will immediately prompt you to change the default password. Do so before proceeding. After login, navigate to Administration → Security → Force user authentication and enable it to prevent anonymous access.
Step 10: Scanning a Project
Install the SonarScanner CLI on your build machine (or CI agent) and run an analysis:
# Download SonarScanner CLI
SCANNER_VERSION="5.0.1.3006"
wget "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SCANNER_VERSION}-linux.zip"
sudo unzip "sonar-scanner-cli-${SCANNER_VERSION}-linux.zip" -d /opt
sudo ln -s /opt/sonar-scanner-${SCANNER_VERSION}-linux/bin/sonar-scanner /usr/local/bin/sonar-scanner
Create a sonar-project.properties file in your project root:
sonar.projectKey=my-project
sonar.projectName=My Application
sonar.projectVersion=1.0
sonar.sources=src
sonar.exclusions=**/node_modules/**,**/*.test.js
sonar.host.url=http://sonar.example.com
sonar.login=your-sonarqube-user-token
sonar.language=java
sonar.java.binaries=target/classes
Run the scan:
cd /path/to/your/project
sonar-scanner
Results appear in the SonarQube dashboard within seconds of the scan completing.
SonarQube on RHEL 7 gives your team a powerful, centralized platform for enforcing code quality standards across all your projects. By integrating the scanner into your CI pipeline — Jenkins, GitLab CI, GitHub Actions, or any other platform — every pull request gets automatic quality gate feedback before merge, dramatically reducing the cost of fixing defects and security vulnerabilities. With Nginx providing SSL termination and PostgreSQL supplying durable storage, this setup is production-ready and scalable to hundreds of projects and developers.