Move Sonarqube Dev Edition from docker to k8s - Web UI remains stuck on Loading

SonarQube 2025.5 Developer Edition – Kubernetes/NKP Deployment Summary

1. Objective

Deploy SonarQube 2025.5.0 Developer Edition on a Kubernetes/NKP cluster with:

  • PostgreSQL 15 as an external database

  • Persistent storage using Kubernetes PVCs

  • SonarQube deployed with the official Helm chart

  • HTTPS exposure through Traefik IngressRoute

  • Secure Kubernetes Secrets for database and monitoring credentials

  • Migration of the existing Developer Edition license to the new instance


2. PostgreSQL 15 Deployment

A dedicated PostgreSQL 15.18 instance was deployed in the sonarqube namespace using:

  • Kubernetes StatefulSet

  • Persistent Volume Claim

  • Nutanix/NKP CSI storage

  • ClusterIP service

  • Kubernetes Secret for database credentials

Database configuration:

Database: sonar
User:     sonar
Port:     5432
Service:  postgres-sonarqube

SonarQube JDBC endpoint:

jdbc:postgresql://postgres-sonarqube:5432/sonar

Database connectivity and authentication were successfully validated.


3. SonarQube Deployment

The official SonarSource Helm chart was used:

Chart:       sonarqube/sonarqube
Version:     2025.5.0
Edition:     Developer
Image:       sonarqube:2025.5.0-developer

The embedded PostgreSQL chart was disabled:

postgresql:
  enabled: false

The external database was configured using:

jdbcOverwrite:
  enabled: true
  jdbcUrl: "jdbc:postgresql://postgres-sonarqube:5432/sonar"
  jdbcUsername: "sonar"
  jdbcSecretName: "postgres-sonarqube-secret"
  jdbcSecretPasswordKey: "POSTGRES_PASSWORD"

The generated Helm manifests were validated before installation.


4. Kubernetes Services

The following services are operational:

postgres-sonarqube
  ClusterIP: 10.101.5.8
  Port:      5432/TCP

sonarqube-sonarqube
  ClusterIP: 10.110.173.7
  Port:      9000/TCP

The corresponding endpoints correctly point to the PostgreSQL and SonarQube pods.


5. Traefik / HTTPS

SonarQube is exposed through Traefik using an IngressRoute:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: ingress-sonarqube
  namespace: sonarqube
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`sonar.lgbow.com`)
      services:
        - name: sonarqube-sonarqube
          port: 9000
  tls: {}

No Traefik middleware is currently configured.

External NKP URL:

https://sonar.lgbow.com


6. Application Validation

The SonarQube API was tested both internally and through Traefik.

curl https://sonar.lgbow.com/api/system/status

Result:

{
  "id": "C3D19B47-AYhHoWw6z91Hifz7jD7X",
  "version": "2025.5.0.113872",
  "status": "UP"
}

This confirms that the complete application path is operational:

Client
  |
  | HTTPS
  v
Traefik
  |
  v
IngressRoute
  |
  v
SonarQube Service :9000
  |
  v
SonarQube 2025.5
  |
  | JDBC
  v
PostgreSQL 15


7. Administrator Authentication

Administrator authentication was successfully validated through the API:

curl -u 'admin:<password>' \
  https://sonar.lgbow.com/api/authentication/validate

Result:

{"valid":true}

The /api/users/current endpoint also confirms that the account is logged in and has SonarQube administrative permissions.


8. Developer Edition Validation

Application logs confirm that Developer Edition is correctly loaded.

The server loads the expected core extensions, including:

developer-edition
ai-code-assurance
developer-scanner
developer-server
license
monitoring
architecture

The server explicitly reports:

Running Developer Edition

Runtime version:

2025.5.0.113872


9. License Issue

A license verification issue was identified during startup.

SonarQube repeatedly reports:

Error in verifying license signature.

followed by:

LicenseSpringException: Could not verify license

During initialization, the application also reports:

Unknown error when initializing license system

The previous SonarQube installation had its license unset before migration.

The new installation has the following Server ID:

N/A

A license reissue/reactivation for the new Server ID is therefore required.


10. LicenseSpring Connectivity

Connectivity from the SonarQube pod to the SonarSource licensing infrastructure was validated directly:

curl -Iv \
  https://api.prod.sonarsource.licensespring.com

The test confirmed:

DNS resolution:       OK
TCP/443 connectivity: OK
TLS 1.3 handshake:    OK
Certificate:          Valid
HTTP response:        200

The license verification problem is therefore not caused by DNS, firewall rules, TLS validation, Kubernetes networking, or Internet connectivity.


11. Credential Rotation

During troubleshooting, the PostgreSQL JDBC password and SonarQube monitoring passcode were exposed in terminal output.

A rotation of both credentials is therefore required.

PostgreSQL

The rotation procedure consists of:

  1. Generate a new PostgreSQL password.

  2. Change the password of the PostgreSQL sonar role.

  3. Validate the new credentials.

  4. Update postgres-sonarqube-secret.

  5. Restart only the SonarQube workload.

No PostgreSQL restart or PVC recreation is required.

Monitoring Passcode

The monitoring passcode should be stored in a dedicated Kubernetes Secret:

sonarqube-monitoring-passcode

and referenced from Helm using:

monitoringPasscodeSecretName: sonarqube-monitoring-passcode
monitoringPasscodeSecretKey: monitoringPasscode


12. Residual Issue

Web UI remains stuck on Loading...

Although the SonarQube backend is operational, the SonarQube web interface remains stuck indefinitely on the Loading... screen.

The issue has been reproduced using multiple browsers, including private/incognito sessions.

The browser JavaScript console reports:

Uncaught (in promise) TypeError: n.filter is not a function

The problem therefore appears to occur during frontend initialization.

Backend status

The backend itself remains healthy:

/api/system/status
    -> HTTP 200
    -> status: UP

Administrator authentication is also operational:

/api/authentication/validate
    -> HTTP 200
    -> {"valid":true}

Frontend API investigation

The main API calls observed during frontend initialization were individually tested.

The following endpoints return HTTP 200 with apparently valid JSON responses:

/api/system/status
/api/authentication/validate
/api/features/list
/api/navigation/global
/api/users/current
/api/settings/values

For example:

/api/features/list

correctly returns a JSON array containing features such as:

from-sonarqube-update
ai-code-assurance
branch-support
github-provisioning
gitlab-provisioning
...

The global navigation endpoint correctly reports:

{
  "canAdmin": true,
  "edition": "developer",
  "version": "2025.5 (build 113872)",
  "productionDatabase": true
}

The current user endpoint correctly reports:

{
  "isLoggedIn": true,
  "login": "admin",
  "local": true
}

The architecture configuration endpoint also returns a valid response:

{
  "settings": [
    {
      "key": "sonar.architecture.visualization.enabled",
      "value": "false",
      "inherited": true
    }
  ],
  "setSecuredSettings": []
}

Traefik status

No evidence currently indicates that Traefik is responsible for the frontend failure.

The IngressRoute is minimal and contains:

  • no StripPrefix

  • no ReplacePath

  • no ForwardAuth

  • no custom middleware

API requests successfully pass through Traefik and return HTTP 200.

Browser status

The problem was initially observed in Firefox.

A Firefox extension generated an unrelated JavaScript error, but the SonarQube issue was subsequently reproduced using Microsoft Edge in InPrivate mode.

This ruled out the Firefox extension as the root cause.

Current hypothesis

The strongest remaining anomaly is the SonarQube licensing subsystem.

During startup, the license subsystem fails with:

Error in verifying license signature

LicenseSpringException:
Could not verify license

Unknown error when initializing license system

At the same time:

  • Developer Edition loads successfully.

  • SonarQube reaches status: UP.

  • Authentication works.

  • Main frontend APIs return valid responses.

  • LicenseSpring is reachable over HTTPS.

  • The frontend fails during initialization with n.filter is not a function.

The current working hypothesis is therefore that the frontend failure may be related to an inconsistent or invalid Developer Edition license state, although this relationship has not yet been conclusively proven.

A second possibility is a SonarQube 2025.5.0 frontend defect triggered by this particular feature/license state.

No manual database modification should be performed until the license has been reissued and the behavior retested.


13. Data Preservation

No destructive storage operation is currently required.

The following resources must not be deleted as part of troubleshooting:

PostgreSQL PVC
PostgreSQL sonar database
SonarQube PVC

In particular, the PostgreSQL database should not be recreated because it contains the persistent identity of the new SonarQube instance.

The Server ID must remain:

N/A


15. Current Status

Component Status
Kubernetes/NKP :white_check_mark: Operational
PostgreSQL 15.18 :white_check_mark: Operational
PostgreSQL PVC :white_check_mark: Bound
PostgreSQL authentication :white_check_mark: Operational
SonarQube 2025.5.0 :white_check_mark: Operational
Developer Edition :white_check_mark: Loaded
JDBC connection :white_check_mark: Operational
SonarQube Service :white_check_mark: Operational
Traefik IngressRoute :white_check_mark: Operational
HTTPS :white_check_mark: Operational
SonarQube system API :white_check_mark: UP
Admin authentication :white_check_mark: Valid
Main frontend APIs :white_check_mark: HTTP 200 / valid JSON
LicenseSpring network access :white_check_mark: HTTP 200
License verification :cross_mark: Could not verify license
Web frontend :cross_mark: Stuck on Loading...
Browser JavaScript :cross_mark: n.filter is not a function
Credential rotation :warning: Pending
License reissue :warning: Pending

Hello @515chris,

Thanks for reaching out and welcome to the Community.

I checked your account internally, and I see that you indicated that you had successfully upgraded in communication with your Account Manager. You were provided a new license, as the Server ID had changed. That was applied on August 13, and our license manager application indicates it was successfully activated.

Can you confirm if you are still having any trouble with your upgrade and migration to K8?

Best regards,

Stevan

Dear Stevan,

Thank you for your message. Yes, I’ve unset the license on the source, export the DB, reinstall and apply the license.

I confirm, it’s in production and usable.

Kind regards

Christophe