Skip to content

SonarQube Installation

SonarQube is a Static Application Security Testing (SAST)


SonarQube will be installed on 🟢 Management Kubernetes Cluster

  • 📥Ingress Service provided as Kubernetes Ingress Class (IngressClass)
  • 🛡️TLS Certificate for SonarQube provided as Kubernetes Secret
    • SonarQube will be exposed as HTTPS with Kubernetes Ingress.

SonarQube depends on multiple dependencies to be up and running but only the following will be provisioned and/or managed by you.

  • 📦PostgreSQL SQL Database ; Deploy external/dedicated instance of Database.
    • Do you bring your own PostgreSQL SQL Database for SonarQube?
    • In case will be installed on Kubernetes Cluster.
      • Will require 💿Persistence Storage as Kubernetes Storage Class (StorageClass)

Once finished everything, these are systems that up and running.

No.ToolDescriptionKubernetes NamespaceKubernetes Cluster
1.PostgreSQL for SonarQubeDatabase System for SonarQubedevsecops-system🟢 Management
2.SonarQubeStatic Application Security Testing (SAST)devsecops-system🟢 Management

Ensure you have defined and loaded your Global Shell Variables as described in Shell Variables.

  1. Connect to 🟢 Management Kubernetes Cluster ; i.e w/ Kubeconfig File

    Ensure you have defined and loaded your Global Shell Variables as described in Shell Variables.

    Terminal window
    source $HOME/opstella-installation/shell-values/kubernetes/management_cluster.vars.sh
    source $HOME/opstella-installation/shell-values/tools/sonarqube.vars.sh
    Terminal window
    export KUBECONFIG="$HOME/opstella-installation/kubeconfigs/management_cluster.yaml"
  2. Export Required Shell Variables

    Ensure SONARQUBE_DOMAIN and SONARQUBE_ADMIN_PASSWORD are defined as per the Shell Variables guide.

    Ensure K8S_INTERNAL_DOMAIN, K8S_INGRESSCLASS_NAME, K8S_STORAGECLASS_NAME, K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME are defined as per the Shell Variables guide. Additionally, export the following variables:

    Terminal window
    # PostgreSQL Backend Passwords
    export SONARQUBE_POSTGRES_SUPERUSER_PASSWORD="CHANGEME"
    export SONARQUBE_POSTGRES_USER_PASSWORD="CHANGEME"
  3. Create Kubernetes Secret for 🛡️ TLS Certificate for SonarQube in Namespace devsecops-system.

    Kubernetes Ingress for SonarQube will associate TLS Certificate with Kubernetes Secret named $K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME.

    Create one using from .crt and .key file.

    Terminal window
    kubectl create secret tls $K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME \
    --cert=/path/to/cert/file --key=/path/to/key/file \
    --namespace devsecops-system

    💡 Should return secret/... created message.

  1. Set PostgreSQL Information

    • Database Name: sonarqube (Defined in manifest)
    • Database User: sonarqube (Defined in manifest)
    • Database Password: ${SONARQUBE_POSTGRES_USER_PASSWORD} (Previously exported)
    • Postgres Superuser Password: ${SONARQUBE_POSTGRES_SUPERUSER_PASSWORD} (Previously exported)
  2. Provision PostgreSQL for SonarQube

    The following manifest defines the entire PostgreSQL system, including credentials and the CNPG cluster.

    Terminal window
    kubectl apply --namespace devsecops-system -f - <<EOF
    ---
    # SonarQube Postgres Superuser Credentials
    apiVersion: v1
    kind: Secret
    type: kubernetes.io/basic-auth
    metadata:
    name: sonarqube-postgres-superuser
    namespace: devsecops-system
    stringData:
    username: postgres
    password: "${SONARQUBE_POSTGRES_SUPERUSER_PASSWORD}"
    ---
    # SonarQube Application User Credentials
    apiVersion: v1
    kind: Secret
    type: kubernetes.io/basic-auth
    metadata:
    name: sonarqube-postgres-user
    namespace: devsecops-system
    stringData:
    username: sonarqube
    password: "${SONARQUBE_POSTGRES_USER_PASSWORD}"
    ---
    # S3 Credentials for Postgres Backups (to SeaweedFS HA)
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
    name: sonarqube-postgres-s3-secret
    namespace: devsecops-system
    stringData:
    S3_ACCESS_KEY: "postgres-backup"
    S3_SECRET_KEY: "${SEAWEEDFS_HA_S3_POSTGRES_BACKUP_PASSWORD}"
    ---
    apiVersion: barmancloud.cnpg.io/v1
    kind: ObjectStore
    metadata:
    name: sonarqube-postgres-backup
    namespace: devsecops-system
    spec:
    # This resource defines the backup destination for the Barman Cloud Plugin
    configuration:
    destinationPath: s3://postgres-backups/
    endpointURL: http://seaweedfs-s3.apps-supporting-services.svc:9000
    s3Credentials:
    accessKeyId:
    name: sonarqube-postgres-s3-secret
    key: S3_ACCESS_KEY
    secretAccessKey:
    name: sonarqube-postgres-s3-secret
    key: S3_SECRET_KEY
    wal:
    compression: gzip
    data:
    compression: gzip
    # Retention policy for backups and WALs handled by the plugin
    retentionPolicy: "30d"
    ---
    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    metadata:
    name: sonarqube-postgres
    namespace: devsecops-system
    labels:
    app.kubernetes.io/name: sonarqube-postgres
    app.kubernetes.io/part-of: sonarqube
    spec:
    instances: 1
    # Image configuration (Postgres 16)
    imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ClusterImageCatalog
    name: postgresql-standard-trixie
    major: 16
    # Enable the Barman Cloud Plugin for backups
    plugins:
    - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
    serverName: "sonarqube-postgres"
    barmanObjectName: "sonarqube-postgres-backup"
    # Storage Configuration
    storage:
    size: 5Gi
    storageClass: "${K8S_STORAGECLASS_NAME}"
    walStorage:
    size: 2Gi
    storageClass: "${K8S_STORAGECLASS_NAME}"
    # Bootstrap Configuration
    bootstrap:
    initdb:
    database: sonarqube
    owner: sonarqube
    secret:
    name: sonarqube-postgres-user
    # Superuser credentials (root/postgres)
    superuserSecret:
    name: sonarqube-postgres-superuser
    # Backup Configuration (Barman Cloud Plugin will automatically detect matching ObjectStore)
    backup:
    {}
    # Resources
    resources:
    requests:
    memory: "256Mi"
    cpu: "200m"
    limits:
    memory: "1Gi"
    cpu: "1000m"
    EOF

    💡 Should return secret/sonarqube-postgres-superuser, secret/sonarqube-postgres-user, and cluster.postgresql.cnpg.io/sonarqube-postgres created messages.

  3. Check for PostgreSQL for SonarQube Readiness - MUST be Ready and Running.

    Get Pod Status - PostgreSQL for SonarQube

    Terminal window
    kubectl get pods -n devsecops-system

    💡 PostgreSQL for SonarQube MUST be Running

    NAME READY STATUS RESTARTS AGE
    ... (deducted)
    sonarqube-postgres-1 2/2 Running 0 XdXh
    sonarqube-postgres-2 2/2 Running 0 XdXh
    sonarqube-postgres-3 2/2 Running 0 XdXh
  1. Install Opstella Logo for Single Sign-On Button

    You will be creating Kubernetes ConfigMap named sonarqube-opstella-logo

    Terminal window
    # Create Kubernetes ConfigMap
    kubectl create configmap sonarqube-opstella-logo \
    -n devsecops-system \
    --from-file=$HOME/opstella-installation/assets/files/opstella-logo.svg

    💡 Should return configmap/sonarqube-opstella-logo created message.

  1. SonarQube Entrypoint Domain

    • Domain: ${SONARQUBE_DOMAIN} (Previously exported)
  2. Set SonarQube Credentials for Initial Admin Account

    export SONARQUBE_DB_HOST="jdbc:postgresql://sonarqube-postgres-rw.devsecops-system.svc.${K8S_INTERNAL_DOMAIN}/sonarqube?socketTimeout=1500"
  3. Create Kubernetes Secret named sonarqube-credentials

    Terminal window
    kubectl apply --namespace devsecops-system -f - <<EOF
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
    name: sonarqube-credentials
    stringData:
    password: ${SONARQUBE_ADMIN_PASSWORD}
    currentPassword: admin
    EOF
  4. Create Helm Values Configurations

    Terminal window
    cat <<EOF > $HOME/opstella-installation/helm-values/sonarqube-full-values.yaml
    # OPSTELLA_CUSTOMIZE/Helm: Deploy Name Overriding; defaults will deploy sonarqube pods with 'sonarqube-sonarqube-0' name, saddd.
    nameOverride: sonarqube
    fullnameOverride: sonarqube
    # Kubernetes: Fundamental Configurations
    clusterDomain: ${K8S_INTERNAL_DOMAIN}
    # OPSTELLA_CUSTOMIZE: Disable built-in NGINX Ingress from Helm Chart
    nginx:
    enabled: false
    # Kubernetes: Expose through Ingress
    ingress:
    enabled: true
    hosts:
    - name: ${SONARQUBE_DOMAIN}
    path: "/"
    ingressClassName: ${K8S_INGRESSCLASS_NAME}
    annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 100m
    ingress.kubernetes.io/proxy-body-size: 100m
    tls:
    - secretName: ${K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME}
    hosts:
    - ${SONARQUBE_DOMAIN}
    # TODO: Application: Monitoring - Move to Existing Secret
    monitoringPasscode: "P@ssw0rd"
    # OPSTELLA_CUSTOMIZE/Application: SonarQube Edition
    community:
    enabled: true
    # Application: Database Configuration
    postgresql:
    enabled: false
    jdbcOverwrite:
    enable: true
    # The JDBC url of the external DB
    jdbcUrl: ${SONARQUBE_DB_HOST}
    # The DB user that should be used for the JDBC connection
    jdbcUsername: sonarqube
    ## Alternatively, use a pre-existing k8s secret containing the DB password
    jdbcSecretName: sonarqube-postgres-user
    ## and the secretValueKey of the password found within that secret
    jdbcSecretPasswordKey: password
    # Application: SonarQube Plugins Configurations
    # - OIDC Plugin
    plugins:
    install:
    - https://github.com/vaulttec/sonar-auth-oidc/releases/download/v2.1.1/sonar-auth-oidc-plugin-2.1.1.jar
    ## Kubernetes/Application: Authentication
    # The above values can be also provided by a secret that contains "password" and "currentPassword" as keys. You can generate such a secret in your cluster
    # using "kubectl create secret generic admin-password-secret-name --from-literal=password=admin --from-literal=currentPassword=admin"
    setAdminPassword:
    passwordSecretName: sonarqube-credentials
    # OPSTELLA_CUSTOMIZE/Application: Add Opstella Platform Logo for OIDC Login
    persistence:
    volumes:
    - name: opstella-logo
    configMap:
    name: sonarqube-opstella-logo
    items:
    - key: opstella-logo.svg
    path: opstella-logo.svg
    mounts:
    - name: opstella-logo
    mountPath: /opt/sonarqube/web/images/opstella-logo.svg
    subPath: opstella-logo.svg
    readOnly: true
    # Kubernetes: Security Context
    containerSecurityContext:
    allowPrivilegeEscalation: false
    privileged: false
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 0
    seccompProfile:
    type: RuntimeDefault
    capabilities:
    drop: ["ALL"]
    ## OPSTELLA_CUSTOMIZE: Disable By Default to encourage configurations on Host OS instead.
    initSysctl:
    enabled: false
    ## OPSTELLA_CUSTOMIZE: Disable By Default to encourage configurations on CSI driver instead.
    initFs:
    enabled: false
    EOF
  1. Check for PostgreSQL for SonarQube Readiness - MUST be Running and Ready.

    Get Pod Status - PostgreSQL for SonarQube

    Terminal window
    kubectl get pods -n devsecops-system

    💡 PostgreSQL for SonarQube MUST be Running

    NAME READY STATUS RESTARTS AGE
    ... (deducted)
    sonarqube-postgres-1 2/2 Running 0 XdXh
    sonarqube-postgres-2 2/2 Running 0 XdXh
    sonarqube-postgres-3 2/2 Running 0 XdXh
  2. Add SonarQube Helm Repository

    Terminal window
    helm repo add sonarqube https://SonarSource.github.io/helm-chart-sonarqube
    helm repo update
  3. Install SonarQube

    • Install a Helm Release with specific Helm Chart Version --version 10.8.1 (App Version: 10.8.1)

      Terminal window
      helm install sonarqube sonarqube/sonarqube --version 10.8.1 \
      --namespace devsecops-system \
      -f $HOME/opstella-installation/helm-values/sonarqube-full-values.yaml
  1. Get Pod Status - SonarQube

    Terminal window
    kubectl get pods -n devsecops-system

    💡 SonarQube should be Running

    NAME READY STATUS RESTARTS AGE
    ... (deducted)
    sonarqube-0 1/1 Running 0 XdXh
  2. Visit https://${SONARQUBE_DOMAIN}

    • It should be accessible.
    • TLS Certificate should be valid and coresponding to your TLS Certificate Installed

  3. Login with Users

    • Try to login with Initial Admin Account

      admin, $SONARQUBE_ADMIN_PASSWORD (Log in with credentials), if success then it works.

Finished?

Use the below navigation to proceed