Brand Logo
Acerca dePortafolioBlog
Hablemos

Un estudio boutique de software que crea experiencias digitales con comprensión humana y excelencia técnica.

Navegación

  • Acerca de
  • Portafolio

Recursos

  • Blog

© 2026 OSSO Studio. Hecho con cuidado.

Volver al Blog
sonarqube-article-image
ugreentesting

SonarQube en un UGREEN NAS

Montar SonarQube en un NAS permite centralizar el análisis estático de los proyectos sin depender de un servicio externo. Para un equipo pequeño o un desarrolla...

Oscar Casado
October 22, 2026
9 min de lectura

Tabla de contenidos

  • Arquitectura
  • Antes de desplegar
  • Comprueba el almacenamiento y los recursos
  • Elige y verifica las imágenes
  • Protege las credenciales
  • Prepara el host para Elasticsearch
  • Arranca SonarQube con Docker Compose
  • Primer acceso
  • Publicación detrás de un proxy
  • Configura la URL pública de SonarQube
  • Integra el análisis en GitHub Actions
  • Copias de seguridad y actualizaciones
  • Referencias

Montar SonarQube en un NAS permite centralizar el análisis estático de los proyectos sin depender de un servicio externo. Para un equipo pequeño o un desarrollador que quiere integrar controles de calidad en CI, un UGREEN NAS con Docker Compose puede ser suficiente, siempre que se prepare correctamente el host y se protejan los datos y el acceso.


Este artículo recorre una instalación de SonarQube Community Build en un NAS UGREEN, desde PostgreSQL y Elasticsearch hasta el análisis de un repositorio con GitHub Actions. Los comandos y rutas reflejan una instalación concreta; adapta las rutas, las versiones de imagen y el dominio a tu entorno antes de ejecutarlos.


Arquitectura

La instalación se compone de dos servicios en una red privada de Docker Compose:

- SonarQube sirve la interfaz web y procesa los análisis. En este ejemplo se publica en el puerto `9000`.

- PostgreSQL guarda los proyectos y resultados. No se publica en la red del NAS: SonarQube se conecta a la base de datos por la red interna de Compose.

El despliegue original vive en `/volume1/docker/sonarqube`, con su archivo `docker-compose.yaml` en esa carpeta. Los datos persistentes se guardan mediante directorios del NAS montados dentro de los contenedores:

Directorio del NAS

Ruta en el contenedor

Contenido

.../postgres

/var/lib/postgresql/data

Base de datos PostgreSQL

.../data

/opt/sonarqube/data

Datos e índices de Elasticsearch

.../extensions

/opt/sonarqube/extensions

Extensiones y plugins

.../logs

/opt/sonarqube/logs

Registros de SonarQube

La base de datos es el estado más importante: contiene los proyectos y sus análisis. Los índices de SonarQube pueden regenerarse en general, pero conservar también los demás directorios facilita la recuperación y las actualizaciones.


Antes de desplegar

Comprueba el almacenamiento y los recursos

El NAS de referencia utiliza un Intel N100 de arquitectura `x86_64`, dispone de 8 GB de RAM y guarda sus datos en un volumen Btrfs RAID1 basado en discos duros. El equipo admite ampliar la memoria y cuenta con ranuras M.2, pero disponer de una ranura no significa que ya exista un volumen SSD utilizable por Docker.


El ejemplo usa `/volume1/docker/sonarqube` como raíz de almacenamiento. Si has creado un volumen de almacenamiento en una M.2, sustituye la ruta por el punto de montaje real que muestra UGOS. No confundas una caché de Docker en SSD con un volumen SSD dedicado a los datos persistentes de SonarQube.


Elige y verifica las imágenes

El Compose preparado para esta instalación fija las versiones en lugar de usar `latest`:

bash
1sonarqube:26.10.0.133078-community
2postgres:17.9-bookworm

Verifica que las etiquetas existan y que PostgreSQL sea compatible con la versión de SonarQube que vayas a instalar. Antes de actualizar una instalación existente, revisa la guía oficial de actualización y los requisitos de compatibilidad de la base de datos.


Protege las credenciales

El valor de POSTGRES_PASSWORD debe coincidir exactamente con SONAR_JDBC_PASSWORD. Sustituye cualquier valor de ejemplo por una contraseña robusta antes de levantar los servicios. Si las variables están escritas directamente en el archivo Compose, ese archivo contiene un secreto: limita sus permisos y evita incluirlo en capturas, registros compartidos o repositorios.


Prepara el host para Elasticsearch

SonarQube incluye Elasticsearch. Uno de sus requisitos se aplica al kernel Linux del NAS, no al interior del contenedor: vm.max_map_count debe ser al menos 262144.

En esta instalación el valor del host era 65530, por lo que Elasticsearch no pudo iniciar. Se ajustó a 524288 desde el NAS:

bash
1sudo sysctl -w vm.max_map_count=524288

Ese cambio se aplica inmediatamente, pero no sobrevive a un reinicio. Para hacerlo persistente, se creó una configuración de sysctl y se cargó:

bash
1sudo sh -c 'printf "vm.max_map_count=524288\n" > /etc/sysctl.d/99-sonarqube.conf'
2sudo sysctl --system

La salida de sysctl --system debe confirmar que se ha aplicado el valor. En el NAS de referencia, ejecutar sysctl sin sudo devolvió command not found porque el binario no estaba en la ruta de búsqueda del usuario SSH; eso no indicaba que el ajuste hubiera fallado.


Arranca SonarQube con Docker Compose

Desde SSH, puedes comprobar que Compose reconoce los dos servicios:

bash
1sudo docker compose \
2  -f /volume1/docker/sonarqube/docker-compose.yaml \
3  config --services

La salida esperada es similar a:

bash
1db
2sonarqube

Si la base de datos ya está activa y falta el contenedor de la aplicación, inicia solo el servicio de SonarQube:

bash
1sudo docker compose \
2  -f /volume1/docker/sonarqube/docker-compose.yaml \
3  up -d sonarqube

⚠️ No uses docker compose down -v como rutina de reinicio. La opción -v puede eliminar volúmenes gestionados por Compose y provocar pérdida de datos. Para consultar el estado:

bash
1sudo docker ps -a --filter name=sonarqube

La primera puesta en marcha puede tardar varios minutos. Si el contenedor de la aplicación no aparece o termina con error, consulta sus registros:

bash
1sudo docker logs --tail 200 <nombre-del-contenedor-sonarqube>

Si SonarQube informa de errores de conexión a PostgreSQL, o si la base de datos no está saludable, revisa también:

bash
1sudo docker logs --tail 200 sonarqube-db-1

Primer acceso

Antes de añadir un proxy o depurar un dominio público, prueba la aplicación desde un dispositivo de la red local con http://<IP-LAN-DEL-NAS>:9000

En el primer inicio de sesión de SonarQube, las credenciales iniciales son `admin` / `admin`. Cambia la contraseña cuando la interfaz lo solicite. Estas credenciales pertenecen a la aplicación y no son las de la cuenta `sonar` de PostgreSQL.


Publicación detrás de un proxy

Si utilizas Nginx Proxy Manager (NPM), configura el host para que reenvíe las peticiones a la IP local del NAS y al puerto `9000`:

- Dominio público, por ejemplo `sonarqube.example.com`.

- Esquema hacia el upstream: `http`.

- Host o IP de destino: IP LAN del NAS.

- Puerto de destino: `9000`.

- WebSockets: habilitado.

El proxy debe conectarse al NAS, no volver a llamar al dominio público. En la instalación de referencia, el dominio devolvía `502` cuando el contenedor de SonarQube todavía no estaba en ejecución. Por eso conviene confirmar primero que la URL local funciona y solo después investigar el proxy.


No reenvíes directamente el puerto `9000` desde el router a Internet. Si el servicio tiene que ser accesible desde fuera, protege el acceso con una política de autenticación. Con Cloudflare, configura un modo de cifrado adecuado entre Cloudflare y el origen, como **Full (strict)**, o valora Cloudflare Tunnel para evitar abrir puertos entrantes en el router. Para uso privado, una VPN suele ser preferible a exponer la interfaz públicamente.

Ten en cuenta también que Cloudflare Access u otra pantalla de inicio de sesión puede impedir que un runner de CI llegue al servidor. Los runners hospedados por GitHub normalmente no pueden acceder a una IP privada de tu NAS; para una instalación privada, un runner autohospedado dentro de la LAN suele ser la opción más sencilla.


Configura la URL pública de SonarQube

La URL base de SonarQube debe coincidir con la dirección externa que usan los usuarios y GitHub. Si la integración intenta volver a http://localhost:9000, la URL base está configurada como localhost o no refleja el proxy.

En Administration > Configuration > General Settings > General, establece la Server base URL con tu dominio HTTPS, por ejemplo:


El proxy puede seguir comunicándose con el contenedor por HTTP en la red local. Después de guardar el cambio, vuelve a intentar la configuración de GitHub. Si el intento anterior llegó a crear una GitHub App antes de fallar la redirección, comprueba si existe y reutilízala o elimina la configuración incompleta antes de crear otra. No compartas los parámetros temporales `code` y `state` de una URL de callback.


En Community Build, la GitHub App sirve para importar repositorios y otras integraciones, pero no habilita el análisis ni la decoración de pull requests. Si solo necesitas analizar la rama principal desde GitHub Actions, puedes omitir ese asistente, crear un token de análisis de SonarQube y configurar el workflow.


Integra el análisis en GitHub Actions

Para analizar un monorepo desde su raíz, SonarQube necesita una configuración de proyecto y un workflow. En el repositorio OSSO del ejemplo, basado en TypeScript/JavaScript, Next.js, NestJS, pnpm y Turborepo, se añadieron:

  • sonar-project.properties en la raíz, con la clave del proyecto.
  • .github/workflows/build.yml, activado con pushes a master.

El workflow instala Node.js 22.11.0 y pnpm 9.14.4, instala dependencias con pnpm install --frozen-lockfile y ejecuta el scanner de SonarQube. En su estado documentado no ejecuta los comandos de build ni de tests del repositorio; añádelos si quieres que formen parte del mismo control de CI.


Configura estos secretos en Settings > Secrets and variables > Actions del repositorio:

  • SONAR_TOKEN: token de análisis creado desde **My Account > Security** en SonarQube. Usa uno limitado al proyecto cuando sea posible. No es un token de GitHub.
  • SONAR_HOST_URL: URL pública de SonarQube, por ejemplo . No es confidencial, aunque el workflow de ejemplo la lee desde secrets; también podría definirse como variable si se ajusta el workflow.

Después de subir los archivos al repositorio:

1. Revisa la ejecución de **Build** en la pestaña **Actions**.

2. Confirma que la instalación de dependencias y el análisis terminan correctamente.

3. Abre el proyecto en SonarQube y comprueba que aparece el análisis de la rama principal y el resultado del Quality Gate.

4. Si el runner no conecta, revisa la resolución del dominio y si Cloudflare Access está bloqueando la petición.

5. Si SonarQube rechaza el análisis, valida el token y comprueba que la clave de proyecto coincide exactamente con `sonar-project.properties`.


Esta configuración es para análisis de la rama principal. Community Build no proporciona análisis ni decoración de pull requests.


Copias de seguridad y actualizaciones

Haz copias periódicas de PostgreSQL en una ubicación distinta del volumen que aloja la instancia. Para una base de datos en ejecución, utiliza una copia lógica —por ejemplo, un dump— en vez de copiar sin más el directorio de datos activo. Protege esos backups: los registros de análisis pueden contener información sensible de los proyectos.


Antes de cambiar una etiqueta de imagen, consulta la documentación de actualización de SonarQube y verifica la compatibilidad de la base de datos. Conserva una copia de seguridad probada antes de actualizar. Cambiar el tag en Compose no constituye por sí solo un plan seguro de actualización o reversión.


Referencias

- [Imagen oficial de SonarQube en Docker Hub](https://hub.docker.com/_/sonarqube)

- [Instalación de la base de datos y requisitos de PostgreSQL](https://docs.sonarsource.com/sonarqube-server/server-installation/installing-the-database.md)

- [Bootstrap checks de Elasticsearch](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/bootstrap-checks)

Última actualización: 23 de octubre de 2026

Leer Más Artículos