Self-hosted GitHub Actions alternative for EU data residency

GitHub keeps EU data residency on Enterprise Cloud through GHE.com. Here is how self-hosted Gitea Actions, Forgejo Actions and Woodpecker CI keep logs, artifacts and caches in your own EU datacenter, and what that takes to run.

On this page

Why EU data residency pushes teams off GitHub Actions

GitHub's EU data residency option is GHE.com, and it is offered on Enterprise Cloud only. Self-hosted Gitea Actions, Forgejo Actions or Woodpecker CI can keep all CI data, including run logs, artifacts, caches and secrets, in your own EU datacenter under your own access controls and retention settings. Consider a regulated EU bank (illustrative) that must tell its supervisor where build logs, artifacts, caches and deployment secrets are stored at any moment. For that team, residency becomes a list of data stores it can name, locate and back up. A hosted service makes that list harder to produce because part of the control plane sits outside the organization's hands. The CircleCI January 4, 2023 incident report shows the stakes, since customers had to rotate secrets after an attacker exfiltrated environment variables and tokens from a hosted service.

Map each data type to a component before you choose a platform. In Woodpecker, the server holds pipeline records and uses SQLite by default, with PostgreSQL or MariaDB recommended for larger instances, so the database location and its backups define where build history lives. Agents run workflows and connect to the server over gRPC. On Kubernetes, each pipeline gets a temporary persistent volume claim, 10G and ReadWriteMany by default, which holds files shared between steps. That volume is where workspace data lands, so confirm its storage class sits inside your EU cluster. Gitea supports MySQL, PostgreSQL, SQLite and MSSQL, so the database engine and its host are part of the same inventory. For Gitea and Forgejo artifacts and caches, confirm in the current documentation where they are written and whether they can point to storage you control.

Three decisions follow. First, decide where secrets live and who can read them. GitHub's REST API returns Actions secret names without values, so each secret must be re-created in the new platform from its source system, and the store should sit inside the EU boundary with access limited by role. Second, set retention per data type, because hosted defaults such as GitHub Actions' 90 days may not match your own policy. Third, ask each vendor or project in writing where backups, telemetry and runner logs are sent and under which processing terms. DeployOpen can plan the data map, configure the platform inside your EU infrastructure and prepare the evidence an assessor will ask for, such as configuration records and access logs. DeployOpen prepares that evidence but does not issue audit reports, attestations or certifications; independent auditors and certification bodies do.

What EU data residency requires from a CI system

EU data residency for CI is not one setting. It covers where build records and artifacts sit, who can read secrets, where the engine and runners execute, and how data leaves or gets deleted. Each card below is a point to confirm in a hosted option and to design for in a self-hosted one.

Where logs, artifacts and caches live

Run logs, build artifacts and dependency caches are often the largest stores of build data, and hosted services set their own retention. GitHub Actions defaults to 90 days, CircleCI sets 30 days as both the default and the maximum, and Bitbucket Pipelines keeps artifacts for at most 14 days. In a self-hosted setup, you choose the storage location and retention yourself, so write down which EU datacenter holds each store and how long it is kept. Confirm that backups of these stores stay in the EU as well.

Where secrets sit and who reads them

Deployment secrets are the most sensitive data a CI system holds. GitHub's REST API returns Actions secret names without values, CircleCI states that variable values are not readable in its app after they are set, and Bitbucket secured variables can only be replaced or deleted. Because values cannot be exported, a migration means re-creating every secret. Under a self-hosted engine, you decide which vault or store holds them, which administrators can read them, and which projects can reach them.

Where the engine and runners execute

Residency depends on where the CI server, its database and every runner process data, not only on where the forge is hosted. A hosted CI service may run jobs in regions you do not control. With Woodpecker CI, the server, agents and any autoscaled cloud VMs are placed by you, so the agent pool and autoscaler should run only in approved EU locations. Ask which regions any hosted runner, plugin image registry or external action source uses.

Compromise exposure and incident response

A hosted CI provider holds secrets for every connected project, so its security incidents become your exposure. CircleCI's January 4, 2023 incident report told all customers to rotate secrets after an attacker exfiltrated environment variables, tokens and keys. Under self-hosting, the risk moves in-house, and your team must patch the server, restrict agent access and keep a tested rotation procedure. Confirm who you would notify and how quickly you could rotate every credential.

Exports and deletion on request

Data residency also covers how records leave and how they are erased. Hosted build history is subject to retention windows, so export logs and artifacts before they expire. Write the export format, the deletion steps for logs and caches, and the backup expiry for each store into the processing record. Ask the hosted vendor for its written deletion commitments, and for self-hosted systems, test that a deletion request removes data from backups as well.

Where GitHub's EU residency option meets the constraint and where it does not

GitHub's EU residency option is GHE.com, which is available only on Enterprise Cloud. It is the hosted route to EU residency that GitHub offers, so it is the option most teams compare first. Residency depends on what GitHub commits to in your contract and documentation, so read those terms for each data category rather than assuming that the EU label covers everything.

  • Data categories: Confirm in writing which data sets (repository content, Actions logs, artifacts and caches) are stored in the EU region and which, if any, are processed elsewhere.
  • Hosted runners: Ask where GitHub-hosted runner jobs execute and whether job logs pass through other regions while they stream.
  • Self-hosted runners: Runners in your own EU datacenter keep build execution under your control, but the control plane and run metadata remain with GitHub.
  • Retention: Artifact and log retention is set in repository and organization settings, and the default artifact retention is 90 days, so confirm what your configuration keeps and for how long.
  • Secrets: The REST API returns Actions secret names without values, so any later move off the platform requires re-entering each secret.

Ask GitHub for the data location documentation for each category and the sub-processor terms before signing.

Gitea Actions, Forgejo Actions and Woodpecker CI compared for EU hosting

This table compares Gitea Actions, Forgejo Actions and Woodpecker CI on license, forge scope, GitHub Actions compatibility, support model and documented gaps. Read it as a shortlist filter: the first two options are forge-integrated CI, while Woodpecker can keep GitHub as the forge and run builds in your own EU datacenter. Confirm each row against the current project documentation before you decide.

CriteriaGitea ActionsForgejo ActionsWoodpecker CI
LicenseMIT (Gitea)GPL-3.0-or-later from v9.0 onward, MIT before thatApache-2.0 (documentation under CC BY-SA 4.0)
ScopeBuilt into the Gitea forge, which also covers Git hosting, code review and packagesBuilt into the Forgejo forge, with separate runnersCI/CD engine only; connects to GitHub, GitLab, Gitea, Forgejo, Bitbucket and Bitbucket Datacenter
GitHub Actions compatibilityDesigned to be compatible with GitHub Actions wherever possibleDesigned to be familiar to GitHub Actions users, not compatibleNot a GitHub Actions clone; uses YAML pipelines with container steps and Woodpecker plugins
Where logs and artifacts liveOn the Gitea instance you host in your EU datacenterOn the Forgejo instance and its runners in your EU datacenterOn the Woodpecker server and agents you host; confirm the forge keeps its own run data
Commercial support modelCommitGo, Inc. offers leadership and commercial support and sells Gitea EnterpriseNon-profit governance; Codeberg e.V. owns the domains, project governance stays independentOpen-source project; confirm any commercial support option directly with the maintainers
Documented gapsCompatibility is a design goal; confirm each workflow feature and permission scope you useWorkflows need small edits; the .forgejo/workflows path is preferred over .github/workflows fallbackPlugins may need adjustments; multiple forges on one server is still experimental
Operational footprintSingle forge to run, back up and upgrade, with a choice of MySQL, PostgreSQL, SQLite or MSSQLSingle forge to run, back up and upgrade, with a separate runner to register and secureServer, agents and a database (SQLite by default, PostgreSQL or MariaDB recommended for larger instances)
Best fit for EU hostingTeams that want to move Git hosting and CI into the same EU-hosted systemTeams that prefer a non-profit governance model and a GPL-licensed forgeTeams that must keep code on an existing forge and move only the builds in-house

How to deploy a self-hosted CI stack inside an EU datacenter

This sequence moves CI state, runners, logs, artifacts and secrets into infrastructure you control in an EU datacenter, with a checked result at each stage so the residency claim can be verified before any production build runs.

  1. Confirm datacenter and sovereignty scope

    Before choosing software, write down which data is in scope: build logs, artifacts, caches, environment variables, deploy credentials and the forge's repository contents. Name the EU datacenter or cloud region, the operator who holds administrative access, and any sub-processors such as backup vendors or registries. Ask your compliance lead and legal team to confirm whether any non-EU support access is permitted. Done when the scope is a signed one-page document that your architects and auditors can both read.

  2. Choose the forge and CI engine

    Decide whether the forge moves with CI or stays where it is. Gitea Actions and Forgejo Actions keep Git hosting and CI on one self-hosted server, so logs and artifacts never leave the datacenter. Woodpecker CI can run beside an existing forge, including GitHub, but then webhooks and clone traffic still cross to that forge, so confirm that is acceptable under your scope. Check the workflow compatibility notes in the sibling comparisons before committing. Done when the choice and its residency consequences are recorded in your architecture decision record.

  3. Size and place the database

    Woodpecker uses SQLite by default, and the project recommends PostgreSQL or MariaDB for larger instances, so a production EU deployment should plan an external database inside the same datacenter. Gitea supports MySQL, PostgreSQL, SQLite and MSSQL, and Forgejo operates on its own database layer. Your platform team sizes capacity from expected build volume and confirms the database is replicated and backed up within the approved region. Done when the database host, version and location are documented and a test connection succeeds from the server.

  4. Deploy the server and runners

    Install the forge or Woodpecker server, then deploy agents on Docker or Kubernetes. For Woodpecker, the Kubernetes backend runs each step in a standalone pod and creates a temporary persistent volume claim for the pipeline, so confirm your cluster's storage class and its datacenter placement before deployment. Keep runners on hosts that have no route to production networks unless a deploy job needs one. Done when a test pipeline runs on an EU runner, the job log shows the expected host, and the runner pool is restricted to approved labels.

  5. Configure storage and retention for logs and artifacts

    Set where logs, artifacts and caches are written, and set retention for each. Hosted services in the GitHub Actions comparison keep artifacts for limited periods, so your self-hosted retention policy becomes an explicit decision rather than a vendor default. Point object or file storage at volumes in the EU datacenter, enable encryption at rest, and confirm that no CDN or external cache sits in the path. Ask your storage vendor to confirm where replicas are held. Done when a test artifact is stored in the approved location and the retention setting is recorded.

  6. Re-create secrets from a controlled source

    CI secrets generally cannot be exported from hosted platforms, so they must be re-entered from their original sources, such as a password manager, a cloud secrets store or a key management service located in the EU. Create secrets at the narrowest scope, such as per repository or per environment, and remove any that point at services you no longer use. Confirm that each secret is masked in logs. Done when a test job reads each required secret, and a record lists each secret's owner, scope and rotation date.

  7. Set up backups and upgrade windows

    Back up the server database, repository data, configuration and artifact storage to an EU location, then test one restore on separate infrastructure. Agree an upgrade window with engineering and security, and check the release cadence of your chosen project before scheduling. Forgejo publishes support windows for its stable and LTS releases, and GitLab publishes a monthly minor-release schedule, so align patch timing with those dates. Done when a restore test has completed successfully, and the upgrade calendar is approved by the owners of production deployments.

Where logs, artifacts and caches are stored in each setup

Before you choose between Gitea Actions, Forgejo Actions and Woodpecker CI for EU data residency, confirm where each one writes the data that GitHub Actions currently holds for you: the server database, runner working directories, artifact and cache storage, and container registries. In a self-hosted install, all of these can sit in your own EU datacenter, but only if you place each component there on purpose. The exact storage paths, the default database choice and any option to send artifacts or caches to external object storage change between projects and between releases, so check them against the documentation for the exact version you deploy.

Start with the server database. Woodpecker CI uses SQLite by default and recommends PostgreSQL or MariaDB for larger instances, according to its administration documentation, so a production deployment should put the database on an EU host you control. Gitea supports MySQL, PostgreSQL, SQLite and MSSQL. For Gitea Actions and Forgejo Actions, the job logs, workflow state and artifacts are stored by the forge server, so ask where the forge keeps its data directory and whether artifacts can be placed on separate storage. Confirm this with the Gitea documentation and the Forgejo Actions overview for your version, and record the answer in your data inventory.

Next, map the runners and the container layer. Runners execute each job in a working directory on the host or in a container, and that directory can hold source code, secrets injected at runtime and build output until the job ends. Woodpecker's Kubernetes backend creates a temporary persistent volume claim per pipeline, so ask which storage class backs it and where it lands. Container images pulled or pushed during builds go to a registry, which should also be in the EU, such as a self-hosted Harbor. Treat runner hosts as sensitive systems: encrypt their disks, restrict who can log in, and make sure cache directories are cleared or scoped to the right projects.

Evidence assessors ask for under a residency requirement

A residency requirement is only as strong as the records behind it. The cards below list the artifacts an assessor or internal audit will typically ask to see for a self-hosted CI stack, and each one shows where the evidence comes from. DeployOpen prepares this evidence, but independent auditors and certification bodies are the ones who issue any opinion.

Data flow map

A diagram showing every path that repository content, job logs, artifacts, caches, secrets and runner traffic take between the forge, the CI server, the runners and any external service. It answers the first question an assessor asks: where does data leave the EU boundary, if at all? Check that webhooks, container image pulls, action or plugin downloads and telemetry are all on the map, including the ones that go to github.com or public registries during a build.

Storage location inventory

A list of each store that holds CI data, with its host, region, datacenter, encryption status and owner. For Gitea Actions, Forgejo Actions or Woodpecker CI this usually covers the database (SQLite, PostgreSQL, MySQL or MSSQL for Gitea), object storage for logs and artifacts, cache volumes and runner disks. Confirm the actual location of each one in your environment rather than relying on the project defaults.

Secret access control records

Evidence of who can create, read, rotate and delete CI secrets, and which runners and workflows can use them. Hosted services do not let you export secret values, so your own records of who set each secret and when become part of the residency story. Ask for role assignments, approval records for secret changes and a list of runner groups that can reach production credentials.

Admin role and access reviews

Records of who holds administrator rights on the forge, the Woodpecker server, the agents and the underlying Kubernetes or VM hosts, plus the periodic reviews that confirmed those rights were still needed. Assessors often weigh these reviews more heavily than the role list itself. Keep them dated and signed, and tie them to your identity provider groups where possible.

Retention and deletion configuration

The settings that control how long logs, artifacts and caches survive, and the procedure that removes them at end of life. Hosted CI defaults differ, and a self-hosted stack sets its own values, so the configuration file or admin setting is the evidence. Include a test showing that an expired artifact is actually removed from storage, not just hidden in the interface.

Backup and restore test records

Logs of scheduled backups of the CI database, object storage and configuration, along with records of at least one restore test that brought the service back in an EU location. A backup held outside the residency boundary can break the requirement, so the backup target belongs in the inventory too. Ask your provider to confirm the restore steps for each component.

Questions buyers ask before moving CI into an EU datacenter

What does a self-hosted CI move cost compared with GitHub Enterprise Cloud data residency?

The cost depends on which components you pay for and who runs them, and no single figure applies to every organization. A self-hosted setup has recurring costs for the servers or Kubernetes capacity in your EU datacenter, storage for logs, artifacts and caches, backups, upgrades, and the staff time to operate the CI server, agents and forge. The software itself is free to license: Gitea and Forgejo are open source, and Woodpecker CI is licensed under Apache-2.0. Commercial data residency through GHE.com is a subscription, so compare its annual fee against your own run cost, including the hours your platform team spends. Ask any vendor or partner for a written scope and a quote that lists each component separately, so you can see what recurs and what is one-time.

How long does it take to move CI into our own EU datacenter?

No duration applies to every environment, so treat any timeline as something to agree in writing after scoping. The main drivers are the number of repositories and pipelines, how many workflows depend on marketplace actions or GitHub-specific features, how much build history you must export before retention expires, the number of runners and the target platform (Docker or Kubernetes), and whether the forge itself moves or stays on GitHub. Teams that keep GitHub as the forge and add Woodpecker CI usually have a smaller first step than teams that also migrate Git hosting. DeployOpen plans and fixes the scope before work starts, and most engagements are fixed-scope.

What must our organization provide before a CI migration starts?

You need to provide access and decisions, not just budget. Typically this includes the EU datacenter or cloud account where the platform will run, network rules for webhooks and runner-to-server traffic, identity integration for users, a list of repositories and workflows in scope, the secrets inventory with owners, and the compliance requirements that the new platform must support. You should also name the people who approve changes, define the retention periods for logs and artifacts, and confirm where backups will be stored. Ask your provider to list these inputs in the written scope so gaps are found before cutover.

Can our internal platform team run a self-hosted CI migration alone?

An internal team can do it alone if it has skills in Git forge administration, container runtimes, runner operations and CI pipeline design, and if it has time for the work beside its existing duties. Gitea Actions and Forgejo Actions aim to be familiar to GitHub Actions users, but Forgejo Actions is documented as not compatible with GitHub Actions, so expect some workflow edits. Woodpecker CI can run beside GitHub, which lets a small team move builds first. Be realistic about ongoing operations: the server, agents, database, plugins and upgrades recur every year. A partner can plan, implement, harden and document the platform, then support it under a retainer if you want the work handed over.

How do we move CI secrets to a self-hosted platform?

You generally cannot export existing CI secret values from GitHub, so you must re-create them on the new platform. The GitHub REST API returns Actions secret names without their values, which means you need the original sources, such as the vault, cloud account or service owner, to supply each value again. Make an inventory of every secret, its scope and its consuming pipelines, then rotate credentials as you move them so the old values stop working. Store the new values in a secrets manager or the CI engine's secret store, restrict them by repository and branch, and confirm that logs do not print them. Plan the rotation schedule with the security team before cutover.

Do we need GitHub Enterprise Server or GHE.com for EU data residency?

The right fit depends on whether you need the GitHub service itself to be in the EU or you need the CI runtime and its stored data in your own datacenter. GitHub offers EU data residency on Enterprise Cloud through GHE.com, which suits teams that accept GitHub operating the service. GitHub Enterprise Server runs GitHub Actions with self-hosted runners in your infrastructure, and GitHub's documentation describes getting started with it for self-managed installs. If you want full control over logs, artifacts and caches in your own EU datacenter with open-source components, Gitea Actions, Forgejo Actions or Woodpecker CI fit better. Confirm the data location of each store with the vendor in writing before you decide.

Where do logs, artifacts and caches live after a self-hosted move?

In a self-hosted setup, logs, artifacts and caches are stored wherever you configure them, which is the main reason teams choose this path for residency. Plan one storage location per data type inside your EU datacenter, such as a database for run metadata, object storage for artifacts and logs, and a volume or cache store for dependencies. Set retention periods that match your policy, since hosted services keep artifacts for limited periods that you cannot always extend. Confirm with your engineers how each open-source engine handles these stores, and test restores as part of acceptance.

What to confirm with GitHub and your own teams

Before you sign off on an EU-hosted CI design, put a written question to GitHub for each product in scope: GitHub Enterprise Cloud with data residency (GHE.com), GitHub Enterprise Server, and standard GitHub.com with Actions. Ask which data classes stay in the EU region, specifically workflow run logs, artifacts, caches, secrets metadata and audit logs, and where support access, telemetry and backups for those classes are processed. Ask whether the commitment covers hosted runners as well as the control plane, and whether any sub-processor outside the EU can touch that data. Get the answer in the contract or data processing terms, not in a sales call. Note that the retention windows for artifacts and logs are set by the service and vary by product, so confirm the default and the maximum you can configure for your tenant.

Next, establish what a build reaches over the network. Workflows that use actions referenced from github.com, or container images pulled from public registries, fetch code and binaries during the build, so the EU question extends to those dependencies. Ask your platform team to list every external uses: reference and every image pull in the pipelines in scope, and decide whether they are mirrored into your EU network or pinned to a reviewed digest. For Gitea Actions, Forgejo Actions or Woodpecker CI, confirm where the action and plugin sources are fetched from in your configuration and whether that fetch can be blocked or redirected to a local mirror. Treat any unlisted fetch as a residency finding until it is closed.

Finally, name the people who will own the runners, the backups and the secret store. Decide which staff members can administer the CI server, rotate runner registration tokens and restore a database, and who is on call when a runner pool stops picking up jobs. Ask internal teams how many hours of this work they can absorb each month, and whether a retainer or fixed-scope engagement with an implementation partner covers the gap. Confirm that encryption keys for the CI database and any object storage used for artifacts are held in your own key management system, and that restore tests have been run in the EU datacenter. Without named owners and a tested restore, the residency design holds on paper only.

How DeployOpen deploys self-hosted CI under a residency constraint

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source CI platforms inside the client's own infrastructure, including EU datacenters and cloud accounts. For a residency requirement, we start by mapping where logs, artifacts, caches and secrets would be stored, then build the CI platform so that data stays where the client's policy requires.

How we scope

  • Written scope lists the forge, CI engine, runner model and the EU locations where logs, artifacts and caches will be stored.
  • Scope records which secrets, deployment targets and repositories move, and which stay on the current hosted service during transition.
  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

How we build

  • We install and configure the chosen forge or CI engine in the client's own EU environment, with runners placed on infrastructure they control.
  • We configure storage for artifacts and caches, retention periods and access controls so data residency settings are explicit and testable.
  • We run security testing against the pipeline, runners and secret handling before the platform takes production builds.

How we hand over

  • Handover documentation covers the storage locations, backup routines, runner registration steps and the secret re-creation procedure.
  • We prepare the controls and evidence that the client's own auditors will review, without issuing audit reports or certifications ourselves.
  • Operators receive runbooks for upgrades, runner scaling and restoring pipeline state, sized to the environment agreed in scope.

How we support

  • Ongoing support, upgrades and continuous security testing are available as retainers after handover.
  • Retainers can cover tracking of forge and CI releases, including the support windows published by the project, and planned upgrades.
  • Ask for a written quote built from the agreed scope, which should itemize platform work, testing, documentation and any retainer.

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.