Migrate from GitHub Actions to Gitea Actions

Moving repositories and workflows from GitHub to a self-hosted Gitea with Gitea Actions: what carries over, what needs rework, and how to plan secrets, runners and cutover.

On this page

Migrate from GitHub Actions to Gitea Actions: what the move involves

The migration moves repositories to a self-hosted Gitea instance, rewrites workflows into the `.gitea/workflows/` directory and re-creates every secret by hand. Teams usually start this work at a renewal, after a runner or pricing change, or when data residency or lock-in makes hosted CI harder to justify. The repository move uses Gitea's built-in migration form, which asks for at least a GitHub username when issues and pull requests are included. Workflows are copied across largely unchanged, but secret values cannot be exported from GitHub, so each one must be entered again in Gitea from its source system. Runners are a separate step: Gitea Runner is installed and registered with an instance, organization or repository token, and the Gitea quick start recommends a separate machine and Docker isolation for jobs. The work is usually done by the platform or DevOps team that already owns the pipelines, often with an implementation partner for the forge, runner hosting and hardening. Effort depends mainly on how many repositories, how many reusable actions and how many secrets are involved, and on whether the organization also changes its identity, backup and access model. Gitea Actions is designed to be compatible with GitHub Actions wherever possible, but its documentation lists gaps. Actions such as actions/checkout may not work in SHA256 repositories or when Gitea runs on a subpath, and GitHub-only permission scopes, problem matchers and jobs.<job_id>.environment are not supported or are ignored. Confirm each gap against the current Gitea documentation before you commit a timeline, and run a pilot repository through every pipeline first.

Ask the partner for a written scope that lists repositories, workflows, runners, secrets, and the test and cutover criteria, since those drive cost more than the software does. The software is free to use, so the recurring costs are the servers, runner capacity, upgrades, backups and the staff who run them. Gitea also sells Gitea Enterprise and offers Gitea Cloud, so confirm with the vendor whether any of its features are needed before you decide on a self-managed setup.

Which GitHub Actions features map cleanly to Gitea Actions

This table maps common GitHub Actions features to Gitea Actions and marks each as clean, needs rework or gap, using only the incompatibilities Gitea documents. Read it as a starting checklist: confirm each workflow against the rows before you cut over, because a workflow that uses none of the gap items can often move with only path and secret changes.

FeatureStatus in Gitea ActionsWhat to do
Workflow YAML and file locationCleanPlace workflows in .gitea/workflows/ and keep the GitHub Actions syntax. Enable Actions in each repository's settings.
Triggers such as push and pull_requestCleanKeep event triggers as written. Test pull request runs from forks and confirm they behave as your team expects.
Checkout of the repositoryNeeds reworkactions/checkout may not work in SHA256 repositories or when Gitea runs on a subpath. Test both cases before relying on it.
Marketplace actions without a hostNeeds reworkUnqualified action references are fetched from github.com by default. Mirror required actions to the local instance and set DEFAULT_ACTIONS_URL if you need them served internally.
Pinned actions by owner and versionCleanReferenced actions resolve the same way as before once the source is reachable. Confirm the version tags or SHAs you pin exist on the host you use.
Token permission scopes for statuses, checks, deployments, id-token, security-events and pagesGapThese scopes are not supported. Remove them, move status reporting or deployment logic to another system, and replace OIDC token use with stored credentials.
Problem matchers and error annotationsGapProblem matchers and error annotations are ignored. Move failure reporting into plain log output or a separate reporting step.
jobs.<job_id>.environmentGapThis key is ignored. Use approval and promotion steps in your deployment tooling, and confirm how your release process depends on environment protection rules.

What can leave GitHub and what must be re-created

Moving from GitHub Actions to Gitea Actions splits into three groups: what Gitea imports, what you must re-enter by hand, and what you must export before GitHub's retention window closes. Work through the cards in order before you cut over, so no secret, log or integration is lost in the gap.

Repositories and history through the migration form

Gitea's built-in migration form can pull a repository from GitHub, and it can also bring across items such as issues and pull requests. Migrating those items requires at least a GitHub username, so confirm which account and token your team will use before starting. Run a test migration on one repository first, then compare commit counts, branches, tags and pull request numbers against the source.

Secrets must be re-entered

GitHub never returns Actions secret values. The REST API lists secret names only, so the values cannot be copied into Gitea. Inventory every secret name used by workflows, then have each owner supply the value again at the instance, organization or repository level in Gitea. Rotate any credential that deploys to production while you are re-entering it.

Run logs and artifacts need export first

Logs and artifacts are not migrated by the forge move and GitHub deletes them on a retention schedule. The default for GitHub Actions is 90 days, so export the records you must keep before that window closes. Decide which ones are audit evidence, store them in a location your retention policy covers, and record who approved the export.

DEFAULT_ACTIONS_URL for unhosted actions

Actions referenced without a host, such as actions/checkout, are downloaded from github.com by default. Set DEFAULT_ACTIONS_URL to self if you want those references served from your own Gitea instance instead. Check that every action your workflows use is mirrored or reachable, because a runner in a restricted network cannot fetch them from github.com.

Webhooks, runners and integrations

Webhooks, deploy keys, GitHub Apps and third-party integrations do not follow the repository and must be created again on the Gitea side. Register Gitea Runner with an instance, organization or repository token, and place it on a separate machine from the Gitea instance. List every external system that receives events from GitHub today, then confirm each one has a Gitea replacement before you disable the GitHub side.

Migration sequence from inventory to decommission

This sequence moves repositories and workflows from GitHub Actions to Gitea Actions in controlled stages, so each batch is proven before GitHub stops running it. The output is a decommissioned GitHub Actions estate with a documented record of what moved, what changed and what was re-created.

  1. Inventory repositories, workflows and actions

    The platform or DevOps lead lists every repository, every file under .github/workflows, and every action each workflow references, noting which actions are pinned to a host and which are referenced without one. Record the secrets, variables, environments and self-hosted runners attached to each repository, because secret values cannot be exported from GitHub and must be re-created later. The output is an inventory spreadsheet with one row per repository and an owner for each. The step is done when every active repository has a row and an owner has confirmed its workflows.

  2. Classify workflows against documented gaps

    Using the inventory, the team marks each workflow that uses GitHub-only permission scopes such as statuses, checks, deployments, id-token, security-events or pages, and each workflow that depends on problem matchers, error annotations or jobs.<job_id>.environment, since Gitea ignores these. It also flags actions/checkout use in SHA256 repositories or on a subpath deployment, which the Gitea documentation warns about. The output is a list of workflows grouped as ready, needs edits, or needs redesign. Confirm each flag against the current Gitea comparison documentation before the pilot starts.

  3. Stand up Gitea Runner outside the Gitea host

    The platform team installs Gitea Runner from a pre-built binary or Docker image on a separate machine from the Gitea instance, as the quick start recommends, and uses Docker to isolate jobs from one another and from the host. It registers the runner with a token at the scope the team chooses: repository, organization or instance. The output is a runner shown as online in Gitea with a documented host, OS, Docker version and token owner. Restrict who can register runners, since a runner executes whatever workflow code reaches it.

  4. Run a pilot repository end to end

    The team chooses one low-risk repository that has Actions enabled in its settings, places its workflow files in .gitea/workflows/, and runs a build and test pipeline on the registered runner. It then fixes the flagged edits, re-creates the repository secrets, and confirms that actions without a host are fetched from the location the instance is configured to use. The output is a passing pilot pipeline with its run log saved, plus a short list of every change made to the workflow. The pilot is complete when the same commit produces the same test results on both GitHub and Gitea.

  5. Run GitHub and Gitea in parallel

    For each batch of repositories, both pipelines run on every change while GitHub stays live and remains the system of record for deployment. Developers compare run results, artifacts and failure messages, and the team logs every mismatch with its cause and fix. The output is a parallel-run log per repository showing matching outcomes. Do not switch deployment credentials to Gitea until the parallel results match for the agreed period, which the team sets with its own change control process.

  6. Cut over repositories in batches

    The team moves repositories in batches, using Gitea's built-in migration form to bring over the Git data, and for issues and pull requests it supplies at least a GitHub username as the documentation requires. For each batch it turns off the GitHub workflow, confirms Actions is enabled in the Gitea repository settings, verifies the runner picks up jobs, and updates deployment pipelines and webhooks. The output is a cutover checklist signed off per batch, with rollback steps written down before the switch.

  7. Decommission GitHub Actions and archive records

    Once every batch is live on Gitea, the team disables remaining GitHub workflows, removes self-hosted GitHub runners, and revokes the tokens and secrets that no longer have a purpose. Before retention windows close, it exports run logs and artifacts that the team still needs for audit or incident work. The output is a decommission record listing each repository, its cutover date, the secrets re-created and the revoked credentials. Confirm your retention and evidence requirements with your compliance owner before deleting anything.

How the migration changes by team size and starting point

A small team with a few repositories and simple workflows usually has the shortest path. The workflow files are few, the marketplace dependencies are often limited to checkout and setup actions, and the secret set is small enough to re-create by hand in one sitting. The main decision is whether to migrate the whole forge at once or move one repository first as a pilot.

  • Pilot one repository first: Migrate a single low-risk repository, run its workflows on Gitea Runner, and compare results before moving the rest.
  • Inventory secrets early: GitHub does not return secret values, so list every secret name now and plan to re-enter each value from its source system.
  • Check the `.gitea/workflows/` placement: Confirm that Actions is enabled in each repository's settings, because the quick start notes that it is not enabled per repository by default.
  • Keep the runner close to the team: Install Gitea Runner on a separate machine from the Gitea instance and use Docker to isolate jobs, as the quick start recommends.
  • Plan the rollback path: Keep the GitHub repository readable until the pilot passes, so a failed cutover does not leave the team without a build.

Before cutover, confirm that the pilot's workflows produce the same artifacts and test results as on GitHub, and that the people who own each secret can still supply the values.

What drives the cost and duration of this migration

The largest cost in this migration is usually staff time, and most of it is one-time. Someone has to inventory every workflow, list the marketplace actions each one calls, and decide which Gitea Actions incompatibilities to fix: the unsupported permission scopes such as id-token and security-events, the ignored jobs.<job_id>.environment key, and the problem matchers that no longer produce annotations. Repositories with many pipelines, custom actions or deployment approvals take longer. Re-creating secrets is also manual, because GitHub's REST API returns secret names without values, so each owner must re-enter values from their own password manager or vault.

Recurring costs sit on the infrastructure and the people who keep it running. The Gitea server needs compute, a database (MySQL, PostgreSQL, SQLite or MSSQL, depending on your standard), backups and monitoring. Gitea Runner should run on a separate machine from the Gitea instance, as the quick start recommends, and jobs run in Docker, so runner hosts and Docker capacity scale with peak concurrent jobs. Logs and artifacts grow without limit unless you set retention, and storage is a recurring line item. Plan for upgrades and security patching on the forge and each runner. Confirm the Gitea release line you will standardize on and who owns that cycle.

Gitea Enterprise, from CommitGo, Inc., and Gitea Cloud are commercial options. Gitea Enterprise adds SAML 2.0 service provider support, audit logging, IP allowlisting and mandatory two-factor authentication, and Gitea Cloud is a managed service. Neither price appears in the supplied sources, so request written quotes from the vendor and compare them with the internal staffing and hosting estimate for a self-managed install. Ask whether support covers Gitea Actions and the runner, and what response commitments apply. A typical scope agreed in writing with an implementation partner also depends on the number of repositories, workflows and runner pools, so confirm those counts during the inventory.

Effort drivers and how to keep each one down

This table lists the factors that change how much work a move from GitHub Actions to Gitea Actions takes, why each one matters, and one way to reduce it. Use it to scope a migration and to check that a written quote covers the drivers that apply to your estate.

DriverWhy it mattersHow to keep it down and what to ask for in a quote
Number of repositoriesEach repository needs its migration, Actions enabled in settings, a workflow directory and its own secret set, so effort grows with the count.Group repositories by shared workflow patterns and migrate pilot batches first. Ask the vendor to price repositories in tiers and to state what counts as one repository.
Marketplace actions referenced without a hostActions without a host are fetched from github.com unless DEFAULT_ACTIONS_URL is set to self, so each external dependency needs a review of network access and version pinning.Mirror the actions you rely on into the local instance and set DEFAULT_ACTIONS_URL deliberately. Ask for an inventory of every action reference and how each is resolved.
GitHub-only permission scopesGitea's comparison says statuses, checks, deployments, id-token, security-events and pages scopes are not supported, so workflows that depend on them need rework.Search workflows for these scopes before migration and redesign the affected jobs. Ask whether the quote includes rewriting these jobs and retesting their outputs.
Ignored features: problem matchers, annotations and environmentsProblem matchers, error annotations and jobs.<job_id>.environment are ignored, so review gates or annotated output that teams rely on will change.List which pull request annotations and environment-based approvals are in use and decide on replacements. Ask for the replacement approach to be written into the scope.
Secrets volumeGitHub's REST API returns Actions secret names without values, so every secret must be re-entered in Gitea by someone with the real value.Inventory secret names per repository and organization, remove unused ones, and confirm each owner. Ask who supplies values and how rotation is handled after cutover.
Artifact and log history to keepGitHub Actions defaults to 90 days of artifact retention, so history that is not exported is lost, and bulk export is limited by API rate limits.Decide which runs and artifacts must be kept, export them before retention expires, and archive them outside the forge. Ask for export scope and the rate-limit plan.
SHA256 repositories or subpath hostingGitea warns that actions such as actions/checkout may not work in SHA256 repositories or when Gitea runs on a subpath, which can block builds outright.Check repository object formats and the planned URL layout before design. Ask the vendor to confirm in a test build that checkout works on your configuration.
Docker and Kubernetes deploy stepsDeploy jobs need Gitea Runner with Docker or cluster access, and runners are recommended on a separate machine, so network paths and credentials multiply.Separate build runners from deploy credentials and isolate jobs with Docker. Ask what cluster access, service accounts and runner hosts the quote assumes.
Runner count and placementGitea Runner is registered with instance, organization or repository tokens, and each runner needs hosting, patching and capacity planning.Start with a small runner pool and scale by observed queue time. Ask who operates the runners after handover and what monitoring is included.

What usually goes wrong in a GitHub to Gitea Actions move

Most failed Gitea Actions cutovers are not caused by the workflow YAML itself. They come from GitHub-only features that fail quietly, from state that never leaves GitHub, and from infrastructure choices made during a rushed move. Each card below names one failure mode and the check that prevents it.

Permission scopes skipped silently

Gitea documents that GitHub-only permission scopes such as statuses, checks, deployments, id-token, security-events and pages are not supported. A workflow that requests them can appear to run while the step that needed the scope does nothing useful. Before cutover, grep every workflow for these scopes, move any status or deployment reporting to a step that does not depend on them, and run a test pull request to confirm each expected result appears.

Deploy jobs that depend on environments

Gitea documents that jobs.<job_id>.environment is ignored, so GitHub environment protection rules, required reviewers and environment-scoped secrets do not carry over. A deploy job can run without the approval gate the team relied on. Before cutover, list every deploy job that uses an environment, move the approval logic into the pipeline or the deployment platform, and rebuild the scoped secrets explicitly.

Checkout failing on SHA256 or subpath setups

Gitea warns that actions/checkout may not work in SHA256 repositories or when Gitea runs on a subpath. Teams that host Gitea behind a path prefix or use SHA256 object format find their first pipeline fails at the checkout step. Confirm your object format and URL layout on a test repository before migrating production code, and if needed, test a plain git clone step as a fallback.

Actions resolved from the wrong host

Actions referenced without a host are downloaded from github.com unless the DEFAULT_ACTIONS_URL setting points to the Gitea instance. A build can depend on github.com at run time, which matters for air-gapped or restricted networks and for reproducibility. Decide the setting deliberately, mirror required actions to the local instance, and pin versions so a runner with no outbound access fails in a visible place.

Secrets missing after cutover

GitHub's REST API returns Actions secret names without their values, so secrets cannot be exported for import into Gitea. A workflow that reads a missing secret may fail late, or may skip a step if it uses a default value. Build an inventory of every secret name from the repository and organization settings, re-enter each value from the system that owns it, and confirm each one with a dry run before the first production deploy.

Build artifacts lost to retention

GitHub Actions defaults to 90 days of artifact retention, so older build outputs, test reports and release bundles may be gone or inaccessible when teams need them most. Gitea does not inherit that history. Before the cutover date, download the artifacts and logs your audit or release process depends on, store them in your own object store, and record where each one was copied.

Runners sharing the Gitea host

Gitea recommends running Gitea Runner on a separate machine from the Gitea instance and using Docker to isolate jobs. Installing the runner on the same host as the forge lets a malicious or buggy job reach repository data, tokens and the database. Plan separate runner machines, use container isolation for jobs, and register runners with repository or organization scope rather than a broad instance token where possible.

Questions buyers ask before moving from GitHub Actions to Gitea Actions

How long does a migration from GitHub Actions to Gitea Actions take?

No duration is fixed by the platform itself, so the timeline depends on the work around it. The main drivers are how many repositories and workflows you have, how many use marketplace actions that need a replacement or a fetch path, how many secrets must be re-created by hand, and whether you also move issues, pull requests and releases. Gitea's built-in migration form can copy repository content and, with at least a GitHub username, items such as issues and pull requests. Ask any implementation partner for a written scope that lists repositories, workflows and secrets, and confirm the timeline against that list rather than against a generic estimate.

How much effort does the internal team need for a Gitea Actions move?

Effort falls into three groups: moving Git hosting, adapting workflows, and standing up runners. Hosting effort covers the migration form, repository settings and access rules. Workflow effort covers placing files in the .gitea/workflows/ directory, enabling Actions in each repository, and fixing the documented differences, such as GitHub-only permission scopes like statuses, checks, deployments, id-token, security-events and pages, which Gitea does not support. Runner effort covers installing Gitea Runner on a machine separate from the Gitea instance, using Docker to isolate jobs, and registering it with a token. Your team should expect to review every workflow, because the differences are only documented in general terms.

Can our internal team run the migration without an outside partner?

A team with Git administration, CI and container experience can do the work, and Gitea is designed to be compatible with GitHub Actions wherever possible. The harder parts are the ones that need judgment: deciding which workflows to rewrite, validating behavior where Gitea's compatibility notes say something may not work, such as actions/checkout in SHA256 repositories or on a subpath, and hardening the runner. If your team lacks time or recent experience with these areas, a fixed-scope engagement from DeployOpen can plan, implement and document the move with deliverables agreed in writing before work starts. Ask for a written scope either way.

Which GitHub Actions features do not carry over to Gitea Actions?

Gitea documents several gaps that you must plan for before cutover. GitHub-only permission scopes such as statuses, checks, deployments, id-token, security-events and pages are not supported. Problem matchers and error annotations are ignored, and jobs.<job_id>.environment is ignored, so any deployment approval or environment protection logic in your workflows needs a different home. Actions referenced without a host are fetched from github.com unless the [actions] DEFAULT_ACTIONS_URL setting points to the Gitea instance, so you should decide where those actions will come from. Review your workflows against Gitea's comparison page and test each one on a staging instance.

How do we move secrets from GitHub Actions to Gitea?

Secret values cannot be exported from GitHub. GitHub's REST API returns Actions secret names without values, so you can list which secrets existed but must obtain each value from its owning system and enter it again in Gitea. Make an inventory of secret names, identify the systems that issue each credential, and decide whether to rotate them during the move. Because hosted CI services hold deployment secrets for every connected project, rotation at cutover also reduces the risk of carrying over credentials you no longer trust. Confirm with your security team which secrets belong at the instance, organization or repository level in Gitea.

Do we need Gitea Enterprise to run Gitea Actions in production?

Gitea is MIT licensed and its built-in CI/CD, Gitea Actions, is part of the core product, so the open-source edition is the starting point. Gitea Enterprise, sold by CommitGo, Inc., adds SAML 2.0 service provider support, audit logging, organization-level branch protection inheritance, IP allowlisting, mandatory two-factor authentication and dependency scanning. Whether you need any of these depends on your identity, audit and access control requirements, not on Actions itself. Check the feature list on the Gitea Enterprise page against your internal policies before deciding.

How do we confirm the Gitea version and support terms for our environment?

Start by checking the release you plan to deploy against the go-gitea/gitea releases page, which lists current versions and their dates. Gitea Actions has been enabled by default since Gitea 1.21.0, but each repository still needs Actions enabled in its settings, so confirm that setting in your own instance. Ask your vendor or the provider you choose for the support terms in writing, including which versions receive security fixes, what response you can expect, and whether Gitea Cloud or a self-hosted install fits your data residency needs. Record the version, the runner version and the database you run (MySQL, PostgreSQL, SQLite or MSSQL) in your change record so upgrades can be planned.

What does the migration cost, and what recurs after it?

The main costs are one-time migration labor, the servers for the Gitea instance and the separate runner machines, and the storage that holds repositories, artifacts and logs. Recurring costs are the servers, backups, upgrades, monitoring and the staff time that runs them. Gitea's software license is MIT, so software licensing is not the cost driver, but support contracts and Gitea Enterprise features are optional recurring costs. Cost rises with the number of repositories, the number of concurrent jobs and how often you upgrade. Ask any provider for a quote that separates one-time work from recurring operations.

How DeployOpen scopes and runs a Gitea Actions migration

DeployOpen is a Chainscore Labs company that plans, implements, integrates, hardens, backs up and documents self-hosted open-source platforms inside the client's own infrastructure. For a move from GitHub Actions to Gitea Actions, that means the Gitea instance, its database, the Gitea Runner hosts, the backup routines and the network paths between them run in your cloud account, data center or isolated network. Most engagements are fixed-scope, so the repositories in scope, the workflows to convert, the runner pools, the secrets to re-create and the acceptance checks are written down and agreed before work starts. Each of those items is a decision you should make early, because they determine the size of the work more than any single tool does.

The work usually starts with an inventory phase. Someone needs to list every repository that has a .github/workflows directory, every action referenced without a host, every job that uses a GitHub-only permission scope or an environment key, and every workflow that relies on problem matchers or error annotations, since the Gitea comparison documents those as unsupported or ignored. Secrets are inventoried by name only, because GitHub's API does not return their values. A pilot phase then moves one or two representative repositories end to end, including the GitHub migration form run, the DEFAULT_ACTIONS_URL decision, and a runner registration on a machine separate from the Gitea instance. The pilot results set the scope and the acceptance criteria for the rest of the work.

Ongoing support, upgrades and continuous testing are available as retainers after cutover, and they are priced separately from the migration itself. Quotes follow from the written scope. DeployOpen does not publish a price list, so the useful request to make is for a quote that itemizes the inventory, pilot, migration, runner setup, hardening, backup configuration, documentation and any retainer, with the assumptions behind each line. Ask which items are one-time and which recur, and who operates the runners and upgrades after handover.

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.