Backstage and Gitea integration

Connect a self-hosted Gitea server to Backstage for catalog discovery and repository creation from Software Templates, with the configuration sequence, data mapping and checks that close each step.

On this page

Backstage and Gitea integration for self-hosted source control

If your organization runs Gitea and wants catalog entities discovered from repositories, and new repositories created from Software Templates, Backstage reaches Gitea through its Gitea integration, the catalog-backend-module-gitea discovery module, and the Gitea scaffolder actions provided by @backstage/plugin-scaffolder-backend-module-gitea. Gitea is an *MIT-licensed*, self-hosted, all-in-one development service written in Go. It combines Git hosting, code review, team collaboration, package management and CI/CD (Gitea Actions), so it is often the system of record for the code your catalog describes. The Backstage integration covers two jobs: reading catalog-info.yaml files from Gitea repositories into the catalog, and calling Gitea's API from a template to create repositories. It does not replace Gitea's own permissions, and it does not cover sign-in, which is configured separately under Backstage authentication.

Before you build, decide which Gitea scope Backstage will read. Discovery can be limited to specific organizations, paths and branches, and the credential you choose determines what the catalog can see. Use a dedicated service account with read access to the repositories that hold catalog files, and a separate account with the narrowest write rights needed for scaffolder publishing. Confirm in your own Gitea version which token scopes each function needs, because token scope names and the API behavior should be checked against the Gitea documentation for the release you run rather than assumed. Also confirm that your Gitea instance is reachable from the Backstage backend over the network path you plan to use, including any private certificate authority your team operates.

Plan for the operational edges early. Repositories that are archived, forked or renamed will change what the catalog shows, so agree on a naming and ownership convention before the first discovery run. Scaffolder publishing creates repositories under identities that other teams will trust, so review the template's target organization and default branch settings as part of template review. Gitea versions move on their own release cadence, and the Backstage plugin version should be tested against your Gitea release before each upgrade. Ask your DeployOpen team to confirm the supported Gitea version pairing for your Backstage release, and to test discovery and publishing in a staging instance first.

What you need before connecting Backstage to Gitea

Gitea integration in Backstage depends on five things lining up before the first catalog read: a Backstage release on a supported Node.js line, a Gitea server version you have confirmed, a scoped service account, a network path with trusted TLS, and a repository layout the catalog module can scan. Confirm each item in your own environment before you write any configuration.

Backstage version and Node.js line

Start from the Backstage release you already run, or the one you plan to install, and confirm which Node.js releases it supports. Backstage supports two adjacent even-numbered Node.js releases, and as of Backstage 1.46.0 these are Node.js 22 and 24. Check the current support table in the versioning policy because the line moves with new Backstage releases. The Gitea integration and catalog module ship as @backstage packages, so they must move with the rest of the app through yarn backstage-cli versions:bump.

Gitea server version in use

Record the exact Gitea version your team runs, including whether it is a self-hosted install or Gitea Cloud. Gitea publishes its releases on GitHub, and the v1.27 line and the v28 line both appear in the current release history, so confirm which one your server runs before you test API calls. Check that the Gitea API endpoints used by the catalog and scaffolder modules behave the same on that version, and test against a non-production instance first. Do not assume the version that a vendor page lists is the one your server runs.

Scoped service account and token

Create a dedicated Gitea user for Backstage rather than reusing a personal account, so audit logs show which actions came from the portal. Issue an access token with the narrowest scopes that allow reading the catalog repositories and, if you use Software Templates, creating repositories in the target organization. Store the token in your secrets manager and reference it from the Backstage configuration instead of committing it. Confirm the scope names with your Gitea version, because they change between releases.

Network reachability and TLS trust

Confirm that the Backstage backend can reach the Gitea host and port from the network segment where it runs, including any proxy or egress rules. If Gitea uses a certificate from an internal certificate authority, add that CA to the trust store used by the Backstage backend container, or the integration will fail with certificate errors that look like connectivity problems. Test the path from the same runtime that will serve Backstage, not from a laptop, and record the hostname the URL uses so the integration config matches it.

Repository layout for catalog files

Decide how catalog-info.yaml files are placed in Gitea before enabling discovery. The catalog module scans repositories under the locations you configure, so choose whether entities live in one repository per service, a monorepo with several files, or a dedicated catalog repository that the module reads. Agree on the default branch name and the file path, and check that the scan will not pick up forks, archived repositories or test projects you do not want in the catalog.

Items to confirm in your environment

Some details depend on your own setup and must be verified rather than assumed: the Gitea edition and any licensing terms that apply to your organization, the database backend behind Gitea, the exact plugin package versions your Backstage app resolves, and who owns the token rotation schedule. Write down the owner and the answer for each item in your implementation plan. Your Gitea administrator and Backstage platform owner should both sign off before the integration reaches a shared environment.

How to configure the Gitea integration step by step

This sequence connects a self-hosted Gitea server to Backstage so the catalog can discover catalog files and software templates can create new repositories. Each step ends with a check that confirms it worked before the next one begins.

  1. Create a scoped Gitea token for Backstage

    A Gitea administrator or the platform owner creates a dedicated service account in Gitea and issues an access token with only the scopes needed to read the catalog repositories and, if templates will publish, to create repositories in the target organization. Store the token in your secrets manager, not in the repository that holds the Backstage configuration. Confirm the token by calling the Gitea API with it from the Backstage host and checking that it returns the repositories the account should see and no others.

  2. Add the Gitea host under integrations configuration

    The platform engineer adds a Gitea entry under the integrations section of the Backstage app configuration, setting the host to your Gitea server's hostname and referencing the token through an environment variable. Use the self-hosted hostname your users already browse to, and confirm the exact configuration keys against the Backstage integrations documentation for your Backstage version. Confirm the step by starting the backend and checking that the integration loads without configuration errors in the startup log.

  3. Install the catalog and scaffolder Gitea modules

    A Backstage developer adds the Gitea catalog backend module and the Gitea scaffolder backend module to the backend package, using the package manager and the Backstage CLI so versions stay aligned with the other @backstage packages. The catalog module reads catalog files, and the scaffolder module provides the actions that publish to Gitea. Confirm the step by rebuilding the backend and checking that both modules register at startup, which the backend log will show.

  4. Set discovery locations and filters

    The platform engineer defines the Gitea discovery provider settings in the catalog configuration, naming the organizations to scan and the catalog file path to look for, and adds branch or path filters so only the intended default branches and descriptor locations are read. Keep the scope narrow for the first run, because broad discovery across a large Gitea instance can create many entities at once. Confirm the step by reviewing the configured filters with a sample repository that should match and one that should not.

  5. Add a publish action to a software template

    A template author adds a Gitea publish action to a software template's steps, setting the target host, the organization, the new repository name and the default branch, and passes the values from the template parameters. The action should also register the new component in the catalog through a catalog registration step so the repository is visible after creation. Confirm the step by validating the template file and checking that the action appears in the template editor without schema errors.

  6. Test catalog discovery

    The platform engineer triggers a catalog refresh for the Gitea locations or waits for the next scheduled run, then checks the catalog for the entities that should appear and the absence of entities from excluded paths. Compare the entity count and owners with the repositories in Gitea. Confirm the step by finding one expected component in the catalog with its source link pointing to the correct Gitea repository, and by reviewing the processing errors list for any unresolved locations.

  7. Run a dry-run scaffold and confirm the repository

    A template tester runs the software template in dry-run mode with sample parameters so the steps execute without creating a repository, and reviews the logged actions and generated files. Then the tester runs the template for real in a sandbox organization set aside for testing, and checks that the repository exists in Gitea with the expected default branch, files and catalog registration. Confirm the step by deleting the test repository afterward and recording the results before any production organization is opened to templates.

How catalog discovery reads Gitea repositories

The Gitea catalog module finds catalog entities by querying the Gitea API for repositories in the scope you configure, then reading one descriptor file from each matching repository. The module does not scan every file in every repository. It reads only the path and branch you set, usually a root-level catalog-info.yaml, and turns the descriptor into entities. Before you go further, confirm in the Backstage integrations documentation and the module source in the plugins directory how your version resolves organizations, paths and branches, because these choices decide which repositories the portal ever sees.

Discovery runs on a schedule defined in the provider configuration, so Backstage does not react to each commit by default. A new descriptor file appears in the catalog on the first run after it lands on the scanned branch. An edited file updates its entity on the next run, and a removed file stops producing its entity, which then follows the orphan handling your catalog uses. The practical consequence is a lag between a Git change and the portal. Measure that lag in a test instance with your own schedule before telling owners that a change is visible immediately.

Broad discovery, such as an entire Gitea instance or a large organization, finds every service without team registration, but it increases API load on the Gitea server and brings in forks, experiments and archived repositories that need cleanup. Narrow filters, such as a single organization, a repository name pattern or a fixed path, keep the catalog accurate but require teams to be added to scope. Agree the rule with your Gitea administrators and platform owners. Confirm whether your module version supports webhook or event-driven updates and which filter options it accepts, and confirm the token scope and API rate limits your Gitea server allows.

How Gitea repositories, owners and teams map to catalog entities

This table shows which Backstage entity each Gitea object becomes and where each value comes from. Read it as two sources: fields you write in catalog-info.yaml, and fields the Gitea catalog module reads from the repository and organization. The main takeaway is that the owner reference in the descriptor only resolves if a matching Group or User already exists in the catalog, so Gitea team names and sign-in identities must line up.

Backstage entity or fieldSource of the valueWhat to confirm before relying on it
Component (one per repository with a descriptor)Repository path and catalog-info.yaml in the repository, read by the Gitea catalog moduleConfirm the descriptor file name and the branch or path the module scans in your configuration
metadata.name and metadata.descriptionDescriptor file; the Gitea repository description is not copied automaticallyDecide whether teams keep names in the descriptor or derive them from repository metadata in a processor
System (grouping of components)Descriptor field spec.system, written by the team that owns the repositoryAgree on one system name per product so components group correctly in the catalog
Owner reference (spec.owner)Descriptor file; must name a Group or User entity already in the catalogCheck that the name matches the team entity exactly, including case and any namespace prefix
Group entity for a Gitea teamTeam and membership data from the Gitea organization, ingested by a separate org data source if you use oneConfirm which Gitea module or provider populates Group entities in your version of Backstage
User entity and sign-in identitySign-in provider identity and resolver; Gitea user records may only supply login namesMap Gitea login names to the same identity the sign-in resolver uses so one person maps to one User
Repository visibility and accessGitea permissions on the token used by the integration, not catalog metadataTest with a token that has read access only to the repositories you intend to catalog

Securing the Gitea token and repository creation

The Gitea token is the credential Backstage uses to read catalog files and, through Software Templates, to create repositories. Anyone who holds it can reach every repository it can see, so the controls below limit what it can do, where it is stored, and which organizations templates can write into.

Scope the token to the minimum

Create a dedicated Gitea account or access token for Backstage rather than reusing a personal token. Grant read access only to the organizations and repositories that hold catalog files, and add write or repository creation rights only to the account used by the scaffolder. Review scopes whenever a new discovery location or template target is added. Ask your Gitea administrator to confirm which permission set the scaffolder needs for the version you run, because scope names change between releases.

Keep the token out of plain configuration

Backstage reads integration credentials from its configuration, so a token written directly into the app config file ends up in container images, Git history and support bundles. Reference the token through an environment variable or an external secrets store that injects it at runtime. Restrict who can read the secret, rotate it on a fixed schedule and on staff changes, and confirm that logs and error pages never print the value.

Restrict which organizations templates publish into

A template with publish access can create repositories wherever the token allows. Limit the target organization or group in each template's publish step, and do not accept a free-text owner field from the user without validating it against an allowlist. Confirm that a template author cannot change the target by editing the template parameters. Keep production platform organizations separate from sandbox organizations so a mistake in one does not spill into the other.

Review scaffolder actions for risky inputs

Template parameters flow into scaffolder actions that fetch content, write files and call the Gitea API. Treat every parameter as untrusted input, including repository names, descriptions and topics. Check which actions a template calls, avoid passing user text into shell-like or URL fields without validation, and limit the fetch targets a template can reach. Review custom actions with the same rigor as application code, because they run with the portal's credentials.

Keep Gitea on a supported release

Gitea is self-hosted, so its patching is your responsibility. Track the Gitea release line you run, read release notes for security fixes, and schedule upgrades in a test instance first. Confirm with your Gitea administrator which versions receive security fixes and how long each line is supported, since the project's support windows are published in its documentation. A Gitea that falls behind exposes the token and every repository it guards.

Align sign-in with the authentication pages

Who may trigger a template is decided by how users sign in to Backstage, not by the Gitea token. Map sign-in identities to catalog users with resolvers that resolve each provider to one identity, and disable guest access in production. The sign-in configuration and resolver details are covered in the Backstage authentication pages, so confirm those settings before granting any user access to publish templates.

How to test discovery and template publishing before rollout

Run discovery and template publishing against a non-production Gitea before any team depends on them. Start by seeding a test repository with a valid catalog descriptor, typically catalog-info.yaml at the repository root, and register the Gitea catalog location in a staging Backstage instance. Confirm that the entity appears in the catalog with the kind, name and owner you expect. Then commit a deliberately invalid descriptor, such as a missing metadata.name or an unknown kind, to a second repository. The import should fail visibly in the catalog's error and processing views rather than silently skipping the file. A test that never produces a failure does not prove the validation path works.

Next, run a Software Template end to end into a sandbox organization that exists only for testing. Use a template whose publish step creates a repository through the Gitea scaffolder actions, and choose a name that cannot collide with production repositories. After the run, verify three things in Gitea: the repository exists under the expected owner, the default branch is the one your template and branch policy specify, and the seeded files, including the descriptor, are present with the expected content. Then check that the new entity is registered in the catalog and links back to the repository. Record each result so the same checklist can be repeated after upgrades.

Before you copy this plan into a production schedule, confirm the exact Backstage and Gitea versions you run, and check the Gitea integration and scaffolder module documentation for those versions. Behavior around token scopes, default branch handling and template parameters can change between releases, so a plan validated against one pairing may not hold for another. Use a token with the narrowest scope that still allows the test, and use a separate token for the sandbox so that a failed run cannot touch production organizations. Keep the test repositories and the sandbox organization in your own Gitea instance so the results reflect the environment you will operate.

Common Gitea integration failures and how to fix them

This table lists the failures teams most often hit when connecting Backstage to a self-hosted Gitea server, with the likely cause and fix for each. Read it by matching the symptom you see in the Backstage logs or catalog to the row, then checking the cause against your Gitea and Backstage configuration. Most issues trace back to token scope, certificate trust, or path and naming rules that are easy to miss on the first setup.

FailureLikely causeFix
Token scope errors on discovery or publishThe Gitea access token lacks the read permission needed to list repositories, or the write permission needed to create repositories during scaffolding.Issue a token from a dedicated service account with only the repository and organization scopes the module needs. Test read and write separately, and confirm the scopes against your Gitea version's token settings.
TLS certificate trust failuresBackstage's backend does not trust the certificate authority that signed your internal Gitea HTTPS certificate, so requests fail during discovery or scaffolding.Add your internal CA to the Node.js trust store used by the Backstage backend, or configure the integration to trust the chain. Confirm the Gitea host name in the integration config matches the certificate's subject alternative names.
Discovery returns no entitiesCatalog path filters or the catalog file location do not match where catalog-info.yaml files actually live, or the branch being scanned does not contain them.Review the discovery location and path settings against a known repository. Confirm the file name and branch, then check the backend logs for skipped locations before changing filters.
Duplicate entity names across repositoriesTwo repositories declare catalog descriptors with the same metadata name in the same namespace, so the catalog rejects or overwrites one of them.Set unique metadata names per component, or use a consistent naming convention that includes the team or repository. Check the catalog errors view after each discovery run to find collisions early.
Scaffolder publish fails on existing repository namesThe template tries to create a Gitea repository whose name is already taken in the target organization or user account.Add a check or parameter validation for repository names in the template, and choose a naming pattern that avoids collisions. Confirm the target owner and the repository name before the publish step runs.
Slow discovery on large Gitea instancesDiscovery scans many repositories and branches on each run, and the default schedule or the number of matching locations makes each pass take a long time.Narrow discovery to the organizations and paths you need, and review the schedule with your Backstage and Gitea operators. Ask the Gitea team about instance capacity and API load before increasing scan frequency.
Entities stop updating after a Gitea changeDiscovery runs on a schedule rather than reacting to changes, so edits to catalog files appear only after the next scan completes.Confirm the configured schedule and allow for the interval before troubleshooting further. Use a manual refresh for urgent checks, and document the expected delay for template authors.

Questions teams ask before connecting Backstage to Gitea

What drives the cost of connecting Backstage to a self-hosted Gitea server?

The cost depends on how many repositories and catalog files Backstage must read, how many teams publish through Software Templates, and how much of the Gitea setup your team already has in place. The work splits into one-time items (reviewing the Gitea access model, creating a dedicated token owner, setting up the catalog module and scaffolder publish step, and testing) and recurring items (keeping the Backstage packages and the Gitea integration current). Ask any partner for a quote built from a written scope that lists the Gitea version, the number of repositories to discover, the template types to publish, and the sign-in arrangement, because each of these changes the effort.

How long does a Backstage and Gitea integration usually take?

No duration was supplied for this integration, so treat any single number with caution and confirm it against your own environment. The main drivers are the number of repositories and descriptor conventions already in use, whether catalog files exist yet or must be written, the number of Software Templates that create repositories in Gitea, and how many Gitea instances or organizations are involved. Access approvals inside your organization often take longer than the configuration itself. Ask for a timeline that separates discovery, the first working catalog import, template publishing and verification, since each phase can move independently.

What does our team need to provide before the integration starts?

Your team needs administrative access to the Gitea server or a clear path to the admins who can make changes, plus a named account that will own the access token Backstage uses. You also need to agree on descriptor conventions: where catalog-info.yaml files live, which organizations and repositories Backstage should scan, and which branch is the source of truth. For template publishing, decide which Gitea organization receives new repositories and what default settings they should carry. Finally, provide a test Gitea instance or a safe window in production, along with the Backstage hosting details and the people who will review the first catalog import.

Can an internal platform team connect Backstage to Gitea without outside help?

Yes, a team with experience in Backstage configuration, Gitea administration and token management can usually do it, and the Backstage integrations documentation covers the Gitea provider and the catalog module. The harder parts tend to be the design decisions: which repositories are discovered, how ownership maps to Gitea teams, how credentials are scoped and rotated, and how the scaffolder publish step behaves across templates. If your team has not run Backstage in production before, a fixed-scope engagement can cover those decisions and leave your staff with written configuration and runbooks. Either way, confirm the skills and time available before deciding.

Should we choose Gitea, Forgejo or GitLab as the source for our Backstage catalog?

The choice should follow your existing platform, licensing needs and support model rather than the Backstage integration alone, because Backstage reads each source through its own provider. Gitea is MIT licensed, written in Go and offered both self-hosted and as Gitea Cloud. Forgejo is licensed GPL-3.0-or-later from v9.0 onward and has a different governance model, with Codeberg e.V. owning its domains. GitLab Community Edition is MIT licensed, but files in the ee/ directory are proprietary and need a paid subscription. Compare the provider support in the Backstage integrations documentation for each platform, then confirm the exact module and version you plan to run before committing.

When does a Gitea Enterprise license matter for a Backstage setup?

A Gitea Enterprise license matters when your organization needs features that the community edition does not provide, such as SAML 2.0 service provider support, audit logging, organization-level branch protection inheritance, IP allowlisting, mandatory two-factor authentication or dependency scanning. The Backstage integration itself does not depend on these features, but your security and compliance requirements might. CommitGo, Inc. provides leadership and commercial support for Gitea and sells Gitea Enterprise. Check the current feature list on the Gitea Enterprise page and confirm with your security team which controls must be enforced at the source before you sign a subscription.

Which Gitea credentials and permissions should Backstage use?

Use a dedicated service account with the narrowest read access that still lets Backstage discover catalog files, and a separate token with write access only for the Software Templates that create repositories. Avoid tying the token to a personal administrator account, because that account's removal or role change would break the catalog. Record who owns the token, when it expires, and how it is rotated, and confirm the exact scopes against your Gitea version in the Gitea documentation. Keeping read and write credentials apart makes access reviews easier and limits the damage from a leaked token.

What typically breaks after a Gitea upgrade, and how do we catch it early?

The most common issues are changed API behavior, renamed scopes or tokens that stop working after a version change, and template actions that assume an older response format. Gitea release notes are published on the go-gitea/gitea GitHub releases page, so read them before each upgrade and test the catalog import and one template run in a non-production instance first. Pair Backstage upgrades with Gitea upgrades in the same test window, and keep a short checklist that covers discovery, ingestion, template publishing and sign-in. Ask any partner to include this regression test in the written scope.

Official documentation for the Gitea integration

Start with the Backstage integrations documentation when you need to know how Backstage models a Gitea host in app-config.yaml, including the integrations block, the host name, and the token that the catalog and scaffolder use to reach it. Read this page before you write any Gitea-specific configuration, because the same integration model applies to every source control provider and the key names are easier to confirm here than in a plugin README. Confirm the token scopes it describes against your own Gitea version, since the minimum permissions for reading catalog files differ from those needed to create repositories.

Next, use the backstage/backstage plugins directory to find the Gitea catalog module, catalog-backend-module-gitea, and the scaffolder module, @backstage/plugin-scaffolder-backend-module-gitea. The directory is the best source for the exact package names, the README configuration for each module, and the version your Backstage release line expects. Compare the package versions there with the Backstage release you run, because a module pinned to an older release can drift during an upgrade.

For the actions that create repositories, read the Backstage builtin actions page to confirm which Gitea publish action is available, what inputs it takes, and which repository and branch options a template author can set. Then open the Gitea documentation to check the server side: the API token model, organization and team permissions, and the settings that control who may create repositories. Gitea is the authority on how your server behaves, so verify each permission against the Gitea version you run, not against examples written for other releases.

How DeployOpen scopes and delivers a Backstage and Gitea integration

DeployOpen plans, builds, documents and supports the Backstage and Gitea integration inside your own infrastructure, so catalog discovery and template publishing run against the Gitea server you operate. Engagements are fixed-scope, with the scope, deliverables and timeline agreed in writing before work starts.

How we scope

  • Inventory the Gitea version, database, hosting model and the organizations and repositories that will hold catalog files.
  • Agree which repositories, branches and catalog file paths the Gitea catalog module will discover.
  • Define the access token, its owner and permissions, and which templates may create repositories in Gitea.
  • Record the scope, deliverables and timeline in writing so the quote follows directly from it.

How we build

  • Configure the Gitea integration and catalog discovery module in your Backstage app and verify entities appear as expected.
  • Set up the Gitea scaffolder actions and test template runs that create repositories in a non-production Gitea instance.
  • Validate catalog ownership fields, processors and sign-in resolvers together so discovered entities map to real users and groups.
  • Test failure paths, including unreachable Gitea, expired tokens and malformed catalog files, before go-live.

How we hand over

  • Document the integration configuration, credential rotation steps and the catalog file conventions your teams must follow.
  • Walk your platform and security engineers through template publishing, repository permissions and troubleshooting.
  • Deliver runbooks for upgrades of Backstage and the Gitea server, including the version checks to run before each change.
  • Provide a handover review so your team can operate the integration without DeployOpen involvement.

How we support

  • Offer ongoing support, upgrades and continuous testing for the integration as a retainer, if your organization wants it.
  • Re-test catalog discovery and scaffolder actions after Backstage releases and Gitea version changes.
  • Review access tokens, permissions and template changes during periodic maintenance checks agreed in the retainer.
  • Confirm any support response expectations in the written agreement rather than assuming them.

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.