Backstage SonarQube plugin for code quality

Show SonarQube quality gates and metrics on each Backstage component page, using the community plugin, a catalog annotation and a token that never reaches the browser.

On this page

How the Backstage SonarQube plugin puts quality gates on component pages

Engineers who own a service currently switch between Backstage and SonarQube to find out whether their last change passed the quality gate, and platform teams want that answer on the component page where ownership, docs and deployments already live. The community SonarQube plugin for Backstage closes that gap by reading project measures and gate status from SonarQube Server and showing them on the entity. The key decision is the link between each catalog entity and its SonarQube project, because the plugin cannot guess which project belongs to which component.

The plugin works through the Backstage backend. Each catalog entity carries the sonarqube.org/project-key annotation in its descriptor, and the backend uses that key to query the matching SonarQube project. Your work in this section is to agree on one naming rule for project keys, decide which team owns the annotation (usually the template that scaffolds the component), and confirm that every entity that should show a gate actually carries it. Entities without the annotation will show nothing, so the gap is easy to miss unless you audit the catalog for it.

This page covers the plugin itself, the annotation, the connection to SonarQube Server and how the access token is handled so it never reaches the browser. Before you install anything, confirm the plugin version, the Backstage release it targets and the SonarQube Server versions it supports against the plugin's own documentation and repository, because community plugins change independently of Backstage core. The Backstage release line you run is covered in the upgrades section of this pillar, and the plugin vetting checklist is covered on its own page.

What you need before connecting Backstage to SonarQube

Connecting the SonarQube plugin touches four parts of your setup: the Backstage backend, the SonarQube Server, the credential that links them, and the catalog entities that point to SonarQube projects. Confirm each one before you write configuration, because a gap in any of them shows up as an empty or erroring card rather than a clear message.

A running Backstage backend

The SonarQube plugin reads data through the Backstage backend, so the backend package must be installed, started and reachable before you add anything for SonarQube. Confirm that your instance builds and starts on the Backstage release line you plan to keep, and that you know which version of the community plugin matches it. Plugin packages and Backstage packages should be upgraded together, so check the plugin's supported version range before you install it.

A reachable SonarQube Server

The backend, not the browser, calls SonarQube's API, so the Backstage backend host must reach the SonarQube Server URL on the port it listens on. Confirm this from the same network segment and container or pod where the backend runs, since a laptop test does not prove the production path. Ask your SonarQube administrator which edition and version run in your environment, because API behavior and project metadata can differ between them.

A service account token with read access

Create a dedicated SonarQube user or token for Backstage with read access only to the projects you intend to show. The token should not belong to a person who may leave, and it should not hold administrative rights. Confirm with your SonarQube administrator how group permissions apply to each project, because a token that cannot see a project will return no data for it without an obvious error.

Certificate trust between backend and SonarQube

If SonarQube sits behind an internal certificate authority or a private load balancer, the Backstage backend container must trust that chain. Gather the CA bundle, confirm the hostname on the certificate matches the URL in your configuration, and test the connection from inside the runtime image. Proxy settings and egress rules in your cluster can block the call even when a workstation reaches SonarQube without trouble.

Catalog entities that can carry annotations

Each component that should show quality data needs a catalog entry with an annotation that names its SonarQube project key. Confirm that the entities exist in your catalog, that each has a clear owner, and that the project key matches the key used in SonarQube exactly, including case and any separators. Entities created from templates or repository discovery are the usual place to add the annotation once, so the pattern is consistent.

Versions confirmed against the current release line

Before you write configuration, confirm the exact Backstage release and SonarQube plugin version you will run, since both change on a regular cadence. The versioning policy describes a monthly main line and a weekly next line, so the release you test may not be the one you deploy. Record the versions in your change ticket, and recheck them at the time of deployment rather than relying on this page.

Configuring the SonarQube plugin in order

This sequence takes a Backstage instance from no SonarQube integration to entity pages that show quality gate status and metrics for each component. Each step ends with a check so you can confirm the connection works before moving on.

  1. Confirm prerequisites and SonarQube access

    Before changing the Backstage repository, confirm which SonarQube edition and version your organization runs, and that the Backstage backend can reach its base URL over the network. Ask the SonarQube administrator for a dedicated user token with read access to the projects you want to display, rather than a personal token. Check the community plugin's README for the Backstage release line it targets, since the plugin must match your @backstage packages. You are done when a request to the SonarQube web API from the Backstage backend host returns a response for a known project key, using a token held only in your shell session for the test.

  2. Install the community plugin frontend and backend packages

    In the Backstage monorepo, add the community SonarQube frontend and backend packages to the correct app and backend workspaces with yarn, then register the backend module in the backend index file alongside your other plugins. Keep the package versions aligned with the rest of your @backstage packages so a later yarn backstage-cli versions:bump does not break them. Review the package source before installing, because plugins run unsandboxed inside your backend. You are done when yarn install completes and the backend starts without module resolution errors.

  3. Add the SonarQube base URL and token in configuration

    In app-config.yaml, add the SonarQube base URL under the plugin's configuration key, and reference the token through an environment variable instead of writing the value into the file. Use a name such as SONARQUBE_TOKEN in your deployment secret store, and mark the config entry so Backstage reads it only on the backend. Do not add the token under any key that the frontend bundle reads, because anything in the frontend configuration is visible to every signed-in user. You are done when the backend starts with the variable set and the startup log shows the SonarQube integration loaded without printing the token value.

  4. Verify the backend returns project data

    Before touching any catalog entity, query the Backstage backend endpoint that the plugin exposes for SonarQube data, using a project key you already know exists in SonarQube. Run the request from a machine that can reach the backend but is not a browser, and check that the response contains the project's quality gate status and metrics. If the response is empty or reports an authorization error, check the token scope and the base URL before continuing. You are done when the backend returns the expected project key and gate status, which proves the server-side connection works independently of the UI.

  5. Annotate the catalog descriptor with the project key

    Open the catalog-info.yaml descriptor for the component you want to display, and add the sonarqube.org/project-key annotation under metadata.annotations with the exact SonarQube project key as its value. Use the key from SonarQube itself, not the display name, because the lookup is exact. Commit the change to the same repository that owns the component so the annotation follows the code. You are done when the catalog shows the updated entity after the next catalog refresh, and the annotation value matches the project key in SonarQube character for character.

  6. Wire the entity card or page

    Add the SonarQube card to the entity page definition in your frontend, usually in the component overview or a dedicated CI or quality tab, and limit it to entities that carry the annotation so unrelated components do not show empty panels. Keep the placement consistent with the other quality and delivery cards so teams find the information in the same place. Rebuild the frontend and restart the app. You are done when a component with the annotation shows its current quality gate status and metrics on the entity page, and a component without the annotation does not show the card.

  7. Check the end-to-end result and record the setup

    Test the full path from a signed-in user's browser: open an annotated component, confirm the gate status matches what SonarQube shows for the latest analysis, and then change the project key to an invalid value on a test entity to confirm the card reports an error instead of stale data. Record the SonarQube base URL, the environment variable name, the plugin version, and the owner of the token in your platform runbook. You are done when the displayed status matches SonarQube for at least one component, and the runbook names the person who rotates the token.

Mapping SonarQube projects to Backstage entities

This table compares each catalog field and annotation involved in the mapping with what it controls on the page and what goes wrong when it is off. Read it before you annotate components, because the project key is the only link between an entity and its SonarQube metrics. The main takeaway is that one entity should map to one project key, and that a mismatch fails quietly rather than with a clear error.

ElementWhat it controlsCommon mistakeHow to confirm
sonarqube.org/project-key annotationThe SonarQube project whose quality gate and metrics the entity page readsKey copied from the project name instead of the exact key in SonarQubeCompare the annotation with the project key shown in SonarQube's project settings
metadata.nameThe entity name shown in Backstage and used in catalog referencesRenaming the entity without updating dashboards, links or the annotationSearch the catalog for the name and check each linked entity page after changes
spec.ownerWhich team is shown as accountable for the quality resultsOwner set to a group that does not exist in the catalogConfirm the owner resolves to a catalog group or user on the entity page
Quality gate statusPass or fail state shown for the mapped projectExpecting a status when the project key is wrong or the project has never been analyzedRun an analysis for the project and reload the entity page
Coverage, bugs, vulnerabilities, code smellsMetrics displayed for the mapped project's latest analysisAssuming metrics update on every commit when analysis runs only in the CI pipelineCheck the timestamp of the last analysis in SonarQube against the pipeline run
Monorepo with several componentsOne project key per component entity, not one per repositoryAnnotating every component with the repository-wide key, so metrics blend across servicesGive each component its own SonarQube project and annotate each entity separately
Missing or wrong project keyThe entity page shows no data or data from a different projectA silent empty panel that looks like a clean resultTreat an empty panel as unverified until the key is checked against SonarQube

Keeping the SonarQube token out of the frontend

The SonarQube plugin needs a credential to read quality data, and that credential is the main security decision on this integration. The cards below cover where the token lives, how narrowly it is scoped, how it is rotated, which entities can reach it, and what the plugin itself does in the browser.

Keep the token in backend secrets

Store the SonarQube token as a backend secret, referenced from configuration through an environment variable, rather than as a plain value in app-config.yaml that ships with the frontend bundle. Anything the frontend can read, a signed-in user can read too. Check the built frontend bundle and the browser's network responses after deployment to confirm the token never appears. Ask the plugin maintainer which configuration keys are read on the backend and which, if any, are passed to the browser.

Scope the token to read-only access

Create a dedicated SonarQube user for Backstage and issue a token for that user only. Grant it browse permission on the projects that should appear in the portal, and nothing that allows changing quality gates, project settings or administration. If a project is not meant to be visible in Backstage, leave it out of that user's permissions. Confirm the exact permission model with the SonarQube Server documentation for your version before you grant access.

Plan rotation and revocation

Set an owner and a rotation schedule for the token, and record where it is stored so every copy can be replaced in one change. Test rotation in a non-production Backstage first, because a changed token that is not updated in the secret store will show empty quality data rather than an obvious error. Keep a documented revocation step for suspected exposure, and confirm with your security team how quickly a token must be revoked after a leak.

Limit which entities show data

The plugin only fetches data for entities that carry the project annotation, so the annotation list is an access boundary. Review which catalog entities declare a SonarQube project key, and avoid mapping one token to projects that belong to other business units or regulated data domains. Where your Backstage permission model supports it, restrict who can view those entity pages so that code quality data follows the same visibility as the repository.

Review the plugin's browser requests

Open the entity page in a browser with developer tools and inspect every request the SonarQube plugin makes. Confirm that calls go through the Backstage backend or proxy, that no request includes the SonarQube token, and that no response returns more fields than the card displays. Repeat this check after every plugin upgrade, because a new version can change which requests the frontend makes.

Vet the plugin before trusting it

Backstage plugins run unsandboxed inside the application, so a plugin has the same access as the portal code and to any secret the backend can read. Before installing, check who maintains the package, where its source repository lives, how recently it was released, and which configuration and credentials it asks for. Record the review in your change process so the choice of a community plugin is a decision, not a default.

Common SonarQube plugin failures and their fixes

This table lists the failures teams most often hit when wiring SonarQube into Backstage, with the likely cause and fix for each. Use it as a first-pass checklist, then confirm exact error text and configuration keys against the plugin's own documentation for your version.

FailureLikely causeFix
Component shows no SonarQube dataMissing or misspelled sonarqube.org/project-key annotation on the catalog entityAdd the annotation to catalog-info.yaml with the exact SonarQube project key, then refresh the entity and check the key in SonarQube
Entity shows a not found or empty result for a projectAnnotation value does not match the SonarQube project key (case or separator differences)Copy the project key from the SonarQube project page and paste it unchanged into the annotation
Backend returns authorization errorsToken lacks permission to view the project, or the token belongs to a user who cannot browse itIssue a token for a service account with browse permission on the relevant projects, and store it in the backend secret store
TLS or certificate errors in backend logsBackend does not trust the certificate chain of the SonarQube Server, often an internal certificate authorityAdd the internal CA to the backend trust store or the Node.js CA configuration, then restart the backend and confirm the connection
Frontend card is blank with no backend errorsBackend plugin route is not registered in the backend index, or the frontend points to a different base URLRegister the plugin backend in the backend entry point and confirm the configured SonarQube base URL in app-config
Plugin fails to load or build after an upgradeVersion mismatch between the SonarQube plugin packages and the Backstage release lineMove plugin packages to versions listed for your Backstage release, bump all @backstage packages together, then rebuild
Token appears in browser network trafficToken placed in frontend configuration or a proxy path exposed to the browserKeep the token in backend-only configuration, call SonarQube from the backend plugin, and never reference the token in frontend code

Questions teams ask before connecting SonarQube to Backstage

What drives the cost of connecting SonarQube to Backstage?

The cost depends on how many components need the annotation, how many SonarQube instances you run, and how much network and credential work sits between Backstage and SonarQube. Three components usually carry the effort:

  • Plugin setup in the Backstage frontend and backend, including configuration and testing in a non-production environment.
  • Token and network work: creating a scoped SonarQube token, storing it in your secrets system, and confirming that the Backstage backend can reach the SonarQube Server URL.
  • Annotation rollout: adding the sonarqube.org/project-key annotation to each catalog entity so it maps to the right SonarQube project.

Setup is largely one-time. Annotation rollout and ongoing plugin maintenance recur as the catalog grows and the plugin changes. Ask any partner for a quote that lists each of these three items separately, with the catalog size and instance count it assumes.

How long does a SonarQube plugin integration take?

Duration depends on the number of SonarQube instances, the state of your catalog metadata, and how quickly your SonarQube administrator can issue a scoped token and open the network path. A single instance with a clean catalog is a much smaller job than several instances with inconsistent project keys. No timing figure is supplied for this work, so ask your partner or internal team to state the duration in writing against the assumptions above. Confirm with your SonarQube administrator how long token creation and firewall changes take in your environment, since those steps often set the critical path.

What does our team need to provide for this work?

You need a named owner for the Backstage instance, a SonarQube administrator who can create a token with the minimum read access the plugin requires, and someone who owns the catalog metadata. Your secrets team should decide where the token lives and how it is rotated. Engineers who own services need to confirm the project key that maps each component to its SonarQube project. Before work starts, confirm with the plugin maintainer which SonarQube Server versions and Backstage release lines the plugin supports, and which token permissions it documents.

Can an internal team connect SonarQube to Backstage without a partner?

Yes, a platform team with Backstage and frontend experience can usually do the integration alone, provided it has access to the SonarQube administrator and the secrets store. The parts most likely to need outside help are the backend configuration that keeps the token off the frontend, and a repeatable annotation rollout across a large catalog. Check the plugin's documentation and its maintainer's release activity before committing, and review the plugin against your own vetting checklist. A fixed-scope engagement can cover the parts your team does not want to own.

How do we handle multiple SonarQube instances in Backstage?

Plan each SonarQube Server as a separate source with its own URL and token, and record which instance hosts each component's project in the catalog. Engineers then need a consistent convention so that a project key is unambiguous across instances. Confirm with the plugin maintainer whether its configuration accepts more than one instance and how it selects the right one per entity. Also confirm with your SonarQube administrator whether project keys are unique across the instances you run, since duplicate keys make the annotation ambiguous.

How do Backstage upgrades affect the SonarQube plugin?

Backstage moves all @backstage packages together with yarn backstage-cli versions:bump, and the Backstage Upgrade Helper shows template changes between versions. Community plugins are separate packages, so each one must be checked against the Backstage version you move to. Test the SonarQube plugin in a staging environment after every bump, and confirm that the token, the backend route and the annotation still resolve. Ask the plugin maintainer which Backstage release lines they test against before you schedule a production upgrade. Any custom code you wrote around the plugin will also need review.

Where should the SonarQube token be stored and who can read it?

Store the token in your secrets system and inject it into the Backstage backend only, never into frontend code or the browser bundle. Ask your SonarQube administrator to create a token with the read permissions the plugin documents and nothing more, and to record its owner and rotation schedule. Confirm with the plugin maintainer whether all calls to SonarQube go through the backend. Limit who can change the Backstage configuration, because a configuration change can expose the token in logs or responses.

What should we ask a vendor or partner before agreeing to a SonarQube integration scope?

Ask for a written scope that names the Backstage version, the SonarQube Server versions, the number of instances, the number of catalog entities receiving the annotation, and the token and network steps. Ask who will maintain the plugin after go-live and how upgrades are tested. Request a list of the decisions that remain with your team, such as token storage and project key conventions. A quote should follow from that written scope. DeployOpen plans and implements these integrations in infrastructure you control and agrees scope, deliverables and timelines in writing before work starts.

Vetting the community plugin before it reaches production

Before you install the community SonarQube plugin, check who maintains it and whether that maintenance is still active. Open the plugin's repository and confirm the publisher, the date and size of recent releases, and how quickly maintainers respond to open issues. Compare the plugin's declared compatibility with the Backstage release line you run. Backstage ships a main line monthly and a next line weekly, and a plugin written for an older @backstage package set can break on upgrade, so confirm it targets your current line before you pin it. Check the license file as well. Backstage itself is licensed under Apache-2.0, but the plugin carries its own license, and your legal team should approve that license separately.

Next, read the plugin's configuration reference and list every credential it asks for. For SonarQube, the question is which token the plugin needs, what permissions that token carries on the SonarQube Server, and whether it reads only project metrics and quality gate status or can also write to the server. Ask the SonarQube administrator to create a dedicated, scoped token for Backstage rather than reusing a personal token. Confirm where the token is read from, which must be the backend configuration and secret store and not any frontend bundle. Run the plugin against a non-production SonarQube instance first and watch which requests it makes, using your network logs or proxy.

Treat this check as the first part of your wider plugin review. The general checklist covers maintainers, repository location, release activity, permissions and why plugins run unsandboxed. This section adds the SonarQube-specific items: the token scope, the Backstage release line the plugin supports, and the license. Record the answers in the same review file, so that when you upgrade Backstage or the SonarQube Server, the person doing the upgrade can repeat the same checks against the new versions.

How DeployOpen scopes and delivers the SonarQube integration

DeployOpen plans and builds the Backstage SonarQube integration inside your own infrastructure, starting from a written scope that names the SonarQube Server instance, the components to cover and the token handling. Engagements are fixed-scope, with deliverables and timelines agreed in writing before work begins.

How we scope

  • Confirm which SonarQube Server instance, version and projects will feed the portal, and who owns each one.
  • Agree which catalog components get the sonarqube.org/project-key annotation and how project keys map to entities.
  • Record the token scope, secret storage location and access review process in the written scope before work starts.

How we build

  • Install and configure the community plugin against your Backstage version, keeping the frontend free of SonarQube credentials.
  • Route SonarQube API calls through the Backstage backend so the token never reaches the browser.
  • Test quality gate and metric display on representative components, including projects with missing or failing analyses.

How we hand over

  • Deliver annotation guidance, configuration documentation and a runbook for rotating the SonarQube token.
  • Walk platform and service teams through how to add the annotation to new catalog entries and templates.
  • Document the plugin version pinning and the steps to verify it after each Backstage upgrade.

How we support

  • Offer ongoing support for the plugin, upgrades and SonarQube connection changes as a retainer.
  • Review plugin releases and Backstage version bumps before they reach production, and report compatibility findings.
  • Confirm with your team what support hours, response expectations and upgrade cadence the retainer should cover.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.