SonarQube analiza el código fuente en busca de bugs, vulnerabilidades, código duplicado y problemas de mantenibilidad, y bloquea los cambios que no superan un umbral de calidad (quality gate). En este tutorial instalarás SonarQube Community Build en Ubuntu 24.04 con PostgreSQL como base de datos, lo ejecutarás como servicio systemd detrás de Nginx con HTTPS y analizarás un primer proyecto con SonarScanner.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM y 2 vCPU. SonarQube incluye Elasticsearch y con menos memoria se vuelve inestable.
- Un usuario no root con privilegios
sudo. - Un dominio o subdominio, por ejemplo
sonar.your_domain, con un registro A apuntando a la IP del servidor. - Los puertos 22, 80 y 443 abiertos en UFW.
- Docker en tu equipo o en tu CI, para ejecutar SonarScanner en el paso 8.
Paso 1: Instalar Java y preparar el kernel
SonarQube es una aplicación Java. Instala OpenJDK 21 y unzip, que necesitarás para descomprimir la distribución:
sudo apt update
sudo apt install openjdk-21-jre-headless unzip
java -version
openjdk version "21.0.x" ...
El Elasticsearch que incluye SonarQube necesita más áreas de memoria mapeada y descriptores de archivo de los que Ubuntu permite por defecto. Crea un archivo de sysctl:
sudo nano /etc/sysctl.d/99-sonarqube.conf
vm.max_map_count=524288
fs.file-max=131072
Aplica los valores y compruébalos:
sudo sysctl --system
sysctl vm.max_map_count
vm.max_map_count = 524288
Paso 2: Crear la base de datos en PostgreSQL
Instala PostgreSQL 16, la versión incluida en Ubuntu 24.04:
sudo apt install postgresql
Crea el usuario sonar y la base de datos sonarqube, de la que será propietario. Sustituye your_strong_password por una contraseña robusta y guárdala, la necesitarás en el paso 4:
sudo -u postgres psql -c "CREATE USER sonar WITH PASSWORD 'your_strong_password';"
sudo -u postgres createdb -O sonar sonarqube
Comprueba que puedes conectarte con ese usuario:
psql -h 127.0.0.1 -U sonar -d sonarqube -c "SELECT current_user;"
Tras pedirte la contraseña, deberías ver:
current_user
--------------
sonar
(1 row)
Paso 3: Descargar SonarQube
Crea un usuario de sistema sin shell para ejecutar SonarQube. Elasticsearch se niega a arrancar como root:
sudo useradd --system --home-dir /opt/sonarqube --shell /usr/sbin/nologin sonarqube
Consulta la última versión de SonarQube Community Build en la página de descargas de SonarSource (https://www.sonarsource.com/products/sonarqube/downloads/) y guarda su número completo en una variable. Sustituye VERSION por el número real, por ejemplo con el formato 25.x.y.zzzzzz:
SONAR_VERSION=VERSION
Descarga el archivo y descomprímelo en /opt:
cd /tmp
curl -fLO "https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONAR_VERSION}.zip"
sudo unzip -q "sonarqube-${SONAR_VERSION}.zip" -d /opt
sudo mv "/opt/sonarqube-${SONAR_VERSION}" /opt/sonarqube
sudo chown -R sonarqube:sonarqube /opt/sonarqube
Comprueba que el directorio contiene, entre otros, bin, conf, data, elasticsearch, extensions y logs:
ls /opt/sonarqube
Paso 4: Configurar SonarQube
Edita el archivo de configuración principal:
sudo nano /opt/sonarqube/conf/sonar.properties
Todas las líneas vienen comentadas. Añade al final del archivo estas propiedades, con la contraseña del paso 2:
sonar.jdbc.username=sonar
sonar.jdbc.password=your_strong_password
sonar.jdbc.url=jdbc:postgresql://127.0.0.1:5432/sonarqube
sonar.web.host=127.0.0.1
sonar.web.port=9000
sonar.web.host=127.0.0.1 hace que SonarQube solo escuche en local; el acceso desde fuera será a través de Nginx. Protege el archivo, ya que contiene la contraseña de la base de datos:
sudo chmod 600 /opt/sonarqube/conf/sonar.properties
Paso 5: Crear el servicio systemd
Crea una unidad systemd para arrancar SonarQube con el sistema y con los límites de recursos que necesita:
sudo nano /etc/systemd/system/sonarqube.service
[Unit]
Description=SonarQube
After=network.target postgresql.service
[Service]
Type=forking
User=sonarqube
Group=sonarqube
ExecStart=/opt/sonarqube/bin/linux-x86-64/sonar.sh start
ExecStop=/opt/sonarqube/bin/linux-x86-64/sonar.sh stop
LimitNOFILE=131072
LimitNPROC=8192
Restart=on-failure
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target
Recarga systemd y arranca el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now sonarqube
El primer arranque crea el esquema de la base de datos y tarda uno o dos minutos. Sigue el log principal hasta ver que está operativo:
sudo tail -f /opt/sonarqube/logs/sonar.log
... INFO app[][o.s.a.SchedulerImpl] SonarQube is operational
Pulsa Ctrl+C y confirma el estado con la API:
curl -s http://127.0.0.1:9000/api/system/status
{"id":"...","version":"25.x.y.zzzzzz","status":"UP"}
Paso 6: Publicar SonarQube con Nginx y HTTPS
Instala Nginx y Certbot:
sudo apt install nginx certbot python3-certbot-nginx
Crea un bloque de servidor para el subdominio:
sudo nano /etc/nginx/sites-available/sonarqube
server {
listen 80;
server_name sonar.your_domain;
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;
}
}
client_max_body_size permite subir los informes de análisis de proyectos grandes. Activa el sitio, comprueba la sintaxis y recarga Nginx:
sudo ln -s /etc/nginx/sites-available/sonarqube /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Permite el tráfico web en el firewall y obtén el certificado de Let's Encrypt. Certbot modificará el bloque de servidor para servir HTTPS y redirigir HTTP:
sudo ufw allow 'Nginx Full'
sudo certbot --nginx -d sonar.your_domain
Successfully deployed certificate for sonar.your_domain to /etc/nginx/sites-enabled/sonarqube
Congratulations! You have successfully enabled HTTPS on https://sonar.your_domain
Paso 7: Primer acceso y token de análisis
Abre https://sonar.your_domain en el navegador. Inicia sesión con el usuario admin y la contraseña admin; SonarQube te obligará a cambiarla en ese momento.
Después ajusta dos cosas:
- En Administration > Configuration > General Settings > General, establece Server base URL a
https://sonar.your_domain, para que los enlaces de correos e integraciones sean correctos. - En Administration > Configuration > General Settings > Security, activa Force user authentication si no estaba ya activo, para que nadie sin cuenta vea el código analizado.
Crea ahora el proyecto que vas a analizar:
- Pulsa Create Project > Local project.
- Escribe un nombre, por ejemplo
myapp, y una Project key comomyapp. Indica la rama principal (main). - Elige Use the global setting para la definición de código nuevo y pulsa Create project.
- Cuando te pregunte cómo analizar el repositorio, elige Locally y genera un token de tipo Project Analysis Token. Cópialo: solo se muestra una vez.
Paso 8: Analizar un proyecto con SonarScanner
SonarScanner es el cliente que lee el código, lo analiza y envía el resultado al servidor. En la raíz del repositorio que quieres analizar, crea el archivo sonar-project.properties:
nano sonar-project.properties
sonar.projectKey=myapp
sonar.sources=.
sonar.exclusions=**/node_modules/**,**/vendor/**,**/*.min.js
sonar.qualitygate.wait=true
sonar.qualitygate.wait=true hace que el escáner espere al resultado del quality gate y termine con error si no se supera, que es lo que quieres en un pipeline de CI.
Ejecuta el escáner con la imagen oficial de Docker. Guarda el token en una variable de entorno en lugar de escribirlo en la línea de comandos del contenedor:
export SONAR_TOKEN=your_project_token
docker run --rm \
-e SONAR_HOST_URL="https://sonar.your_domain" \
-e SONAR_TOKEN \
-v "$(pwd):/usr/src" \
sonarsource/sonar-scanner-cli
Al terminar verás el resultado del análisis y del quality gate:
INFO ANALYSIS SUCCESSFUL, you can find the results at: https://sonar.your_domain/dashboard?id=myapp
INFO QUALITY GATE STATUS: PASSED - View details on https://sonar.your_domain/dashboard?id=myapp
INFO EXECUTION SUCCESS
Abre el enlace para ver los bugs, vulnerabilidades, code smells y duplicados detectados. El quality gate por defecto, Sonar way, evalúa sobre todo el código nuevo, así que no te bloqueará por deuda técnica heredada.
En CI, el procedimiento es el mismo: guarda SONAR_TOKEN como variable secreta del pipeline (en GitLab, Settings > CI/CD > Variables con Masked activado) y ejecuta un job con la imagen sonarsource/sonar-scanner-cli.
Mantenimiento
Para actualizar SonarQube, haz primero copia de la base de datos, descarga la nueva versión en un directorio aparte, copia tu configuración de conf/sonar.properties y los plugins de terceros de extensions/plugins, y arranca la nueva versión. Después abre https://sonar.your_domain/setup para ejecutar la migración de la base de datos.
La base de datos contiene todo el historial de análisis y la configuración. Una copia diaria con pg_dump es suficiente:
sudo -u postgres pg_dump -Fc sonarqube > sonarqube-$(date +%F).dump
Los logs de SonarQube están en /opt/sonarqube/logs/: sonar.log (proceso principal), web.log (interfaz y API), ce.log (procesado de análisis) y es.log (Elasticsearch).
Solución de problemas
El servicio se detiene tras arrancar y es.log muestra max virtual memory areas vm.max_map_count [65530] is too low: el sysctl del paso 1 no se ha aplicado. Ejecuta sudo sysctl --system y comprueba el valor.
sonar.log muestra errores de conexión JDBC: revisa usuario, contraseña y URL en sonar.properties y que PostgreSQL está en marcha con sudo systemctl status postgresql.
El análisis termina pero el proyecto no se actualiza: el informe se procesa en segundo plano. Revisa la pestaña Background Tasks del proyecto y ce.log.
Error 413 Request Entity Too Large al enviar el análisis: aumenta client_max_body_size en el bloque de Nginx y recarga el servicio.
Conclusión
Tienes SonarQube funcionando en Ubuntu 24.04 con PostgreSQL, como servicio systemd, publicado con HTTPS a través de Nginx, y un proyecto analizado con un quality gate que puede detener un pipeline. Como siguientes pasos, puedes añadir el análisis a tus pipelines de GitLab Runner o Jenkins, ajustar los quality profiles de cada lenguaje en Quality Profiles o crear un quality gate propio con umbrales de cobertura de tests.