Restoring GitLab backups: version and edition rules

A GitLab restore only works when the target matches the backup's version and edition, and the secrets file is in place. This page explains how to plan restores around those rules and test them before you need them.

On this page

Why GitLab restores fail on version and edition mismatches

A GitLab restore only works when the target instance runs the same GitLab version and the same edition (Community or Enterprise) as the instance that produced the backup, and when the gitlab-secrets.json file from that same installation is restored with it. Teams hit this rule during incident recovery, when a server rebuild is forced by hardware or OS failure, and when they move an instance to new infrastructure. In each case the person running the restore is often working from memory or from a half-documented runbook, which is where mismatches start. The Linux package, the Helm chart, the GitLab Operator and Docker installs all depend on the matching package or image version, so the restore target has to be prepared from the backup's version, not from whatever is newest.

Plan the restore target before anything is lost. Record the exact GitLab version, edition and package or image tag for every backup, store the version metadata alongside the archive, and keep the matching installer available in a location you control, since you may not be able to download it during an outage. For air-gapped or offline environments, this package mirror is part of the recovery plan, not an afterthought. Install the matching version on the new host, confirm the edition, then restore gitlab-secrets.json before running the restore so encrypted database values can be read. A restore that skips the secrets file can appear to succeed and still leave CI variables, two-factor secrets and runner tokens unusable.

Treat the restore procedure as something you test, not something you read. Run a restore into a scratch environment on a schedule, using a backup taken from production and the same version pinning your recovery would use, then check repositories, users, CI variables and container registry access. Keep the GitLab backup and restore documentation as the authoritative reference for each release, and confirm steps against it before every test, because restore prerequisites change between versions. Ask your vendor or implementation partner to walk through the version pinning, secrets handling and test evidence in writing before you rely on the plan for an incident or migration.

The restore sequence: packages, secrets, then data

This sequence rebuilds a self-managed GitLab instance on a target host that matches the source version and edition, so the restored data loads onto a compatible application and the encrypted values it depends on come back intact.

  1. Record the source version and edition

    Before any restore, the operator records the exact GitLab version, the edition (Community or Enterprise) and the installed package build from the source instance, and stores them alongside the backup archive. Confirm them by reading the version from the running instance and matching it against the package metadata, not from memory or a ticket. The step is done when the version string, edition and backup timestamp are written in the restore runbook and the backup file name matches that timestamp.

  2. Mirror the matching package into your own repository

    The team places the exact package for the recorded version and edition in an internal package repository or artifact store that the target network can reach, since an air-gapped or locked-down environment may not reach public mirrors during an incident. Keep the package checksum with it. Confirm the mirrored file's checksum matches the value published for that build before anyone relies on it. Also confirm that your restore procedure will not pull a newer minor or patch release by accident during installation.

  3. Install the same version and edition on the target

    On the target host, the operator installs the same GitLab version and edition from the internal mirror, using the installation method the team has standardized on. The restore target must match the source exactly, because the backup format and database schema are tied to that release. Do not run the instance yet. The check is that the installed version and edition, read from the package, match the values recorded in step one.

  4. Restore gitlab-secrets.json and gitlab.rb first

    Before restoring data, the operator copies the source gitlab-secrets.json and the gitlab.rb configuration file onto the target, keeping file ownership and permissions. Without the secrets file, encrypted database values such as CI variables, tokens and two-factor secrets cannot be read after the data returns. Compare the SHA-256 checksum of the restored secrets file with the checksum recorded on the source host. The step is done when the checksums match exactly.

  5. Restore the backup archive

    The operator runs the backup restore task against the archive from the recorded backup, after stopping the services that write to the database as the restore procedure directs. Restore only the archive that matches the recorded version and edition, and keep the original archive untouched. The step is done when the restore task completes without errors and its output names the expected backup timestamp. Confirm the archive's version metadata matches the target before running it.

  6. Run reconfigure and start services

    The operator runs the reconfigure command so the restored gitlab.rb is applied to the target, then restarts GitLab and checks that all components report healthy. Review the reconfigure output for warnings about missing secrets or changed settings before moving on. The step is done when the instance starts cleanly and the component status check shows no failing services.

  7. Verify login, clone and pipeline behavior

    The team confirms functional restore with a named test account logging in through the restored authentication settings, a clone of a representative repository over HTTPS and SSH, and a read of a recent issue or merge request. They also confirm that a CI variable or runner registration still works, which tests that the secrets file was restored correctly. Record the results in the runbook. The restore is complete when these checks pass, and any failed check is investigated before users are switched to the target.

Restore target options and when each fits

This table compares the GitLab install methods you might use as a restore target and the situations each suits. Read each row against your own platform standards, then confirm method-specific restore steps with GitLab before you commit to a layout.

Restore targetWhat it suitsRestore considerationsConfirm before choosing
Linux packageTeams running GitLab on VMs or bare metal who want the most mature install pathBundles PostgreSQL, Redis and Sidekiq, so the restored host carries the same package version as the backup sourceExact package pinning and the restore sequence for your version
Helm chartTeams that already run Kubernetes and want GitLab components as cluster workloadsStateful services and storage classes need their own restore plan, separate from the chart releaseWhether your chosen backup method supports the chart and how the chart version maps to your backup
GitLab OperatorKubernetes teams that prefer operator-managed lifecycle and upgradesRestore steps depend on how the operator manages the custom resource and its data volumesOperator-specific restore documentation and version compatibility with the backup archive
DockerSmaller or test instances where a container image is the standard deployment unitImage tag must match the backup's GitLab version and edition exactly, including volume mappingImage tag, edition and volume layout required for restore
Source installationOrganizations with strict build control that need to compile every component themselvesHighest manual effort to keep component versions aligned with the backupDependency versions and the exact restore procedure for your build
Same host rebuildRecovery after host failure where the original hostname and network identity can returnRestores onto a clean install of the same version and edition, then needs the original secrets file in placeWhether the original OS and package versions are still available to reinstall
New host rebuildMigration to new hardware, a new cloud account or a new network zoneHostnames, certificates and runner registration change, and the external URL must be set before restoreDNS, TLS and runner re-registration steps for the new address
Cloud Native Hybrid layoutLarge deployments where stateless components run on Kubernetes and PostgreSQL and Redis run on VMs or managed servicesStateful services are restored outside the cluster, then stateless components are pointed at themWhich database and Redis restore procedures apply to your managed or VM services

When a restore needs an upgrade and how upgrade stops affect it

When the backup was taken from the same GitLab version and edition as the target instance, the restore is the simplest case. The packages on the rebuilt server must match the version recorded when the backup was made, so no upgrade step is needed after the restore. This is the case most teams should rehearse first, because it isolates the restore procedure from upgrade behavior.

  • Pin the exact package version: Record the full version string of the source instance and install the same package on the target before restoring anything.
  • Match the edition: Community Edition packages cannot restore Enterprise Edition data, so confirm the edition on both sides.
  • Restore secrets before data: The gitlab-secrets.json file must be in place before the restore runs, or encrypted data will not be readable.
  • Keep the configuration aligned: Compare gitlab.rb on the target with the source so that external URL and storage settings match.
  • Reconfigure and check after restore: Run the reconfigure and health checks, then confirm a sample of projects, pipelines and users.

Before relying on this path, confirm the restore steps and version requirements for your exact release in the GitLab backup and restore documentation.

What to test before an incident or migration

A restore that finishes without errors can still leave people locked out and pipelines idle. The six areas below check the restored system from the outside in, so each one catches a different failure that a successful restore command would miss.

Scheduled test restore

Restore the latest backup archive into an isolated environment on the same GitLab version and edition as production, on a fixed schedule. Record the restore duration and the GitLab version reported after the restore. A backup you have never restored into a clean host is an assumption, not a recovery option. Confirm the package version matches exactly, because a mismatch fails the restore before any data is checked.

Secrets and configuration validation

Confirm that gitlab-secrets.json and gitlab.rb from the same point in time are in place before the first start of the restored instance. Without the matching secrets file, encrypted database values such as two-factor secrets and CI variables cannot be read, and the instance may appear healthy while those features fail. Check that the external URL and SSH settings point at the new environment.

Repository and CI pipeline checks

After the restore, clone a sample of repositories across projects, groups and storage shards, and confirm that branches, tags and merge request history are present. Trigger one pipeline per representative project to confirm that the .gitlab-ci.yml definitions, variables and artifacts resolve. Repository data alone does not prove the pipelines that depend on it still run.

Authentication and sign-in

Test sign-in with each method your users rely on, including SAML, LDAP, OmniAuth providers and two-factor authentication, using test accounts with the same group memberships as production. Confirm that SCIM-provisioned users and group sync still map to the right roles. A restored instance that loads but rejects every corporate login is one of the most common outcomes of a rushed recovery.

Runner reconnection and registration

Check that existing runners reconnect to the restored instance and that new runners can register with a fresh token. Confirm that runner and GitLab major and minor versions remain aligned, since a runner built for a different version may fail in ways that look like network problems. Test one job on each executor type you operate, including autoscaling executors that depend on cloud credentials.

Attachments, artifacts and timed run-book review

Open a sample of issue attachments, job artifacts, LFS objects and package or registry items, and confirm checksums where your storage supports them. Items kept in object storage may not be in the backup archive at all, so confirm where each category lives. Then run the recovery run book start to finish with a stopwatch and the people who will execute it, and record every step that needed guessing.

Why restoring secrets first prevents a broken instance

Restore the secrets file before you restore any data. The gitlab-secrets.json file holds the keys that GitLab uses to encrypt certain database values, including two-factor authentication secrets, CI/CD variables and some integration tokens. The database backup stores those values in encrypted form, so a restore that brings back the data but not the matching keys leaves the instance running with values it cannot decrypt. The failure often appears late, when a user, pipeline or integration hits a broken value, which makes it easy to misdiagnose as a data problem. Plan the order so the secrets file, gitlab.rb and the installed package version are in place before the database import begins.

The same order applies to the rest of a full rebuild. gitlab.rb carries the settings that the package reads at reconfigure time, such as the external URL and storage paths, so it must match the source instance's layout before you run reconfigure. SSH host keys matter for Git over SSH: if they change, developer clients will warn about a changed host identity, so keep the original host keys with the rest of the configuration. TLS certificates and private keys belong in the same restore set. Confirm with your own team which of these files your instance uses and where each is stored, because the list depends on how you deployed it.

The detailed procedure for backing up and restoring these files, including file permissions and where to store copies, is covered in the sibling topic on backing up GitLab secrets and configuration. For this topic, the decision is sequencing: confirm that the secrets and configuration backups exist and match the archive you plan to restore, then include a secrets-restore step in every restore rehearsal. A rehearsal that skips this step will not show the failure you are trying to prevent.

Security and operational considerations for restore media

Backup archives and the secrets file are the two items that let a restore succeed or expose your data. The cards below cover how to protect them, who may run a restore, and where to test before an incident. Together they turn the version and edition rules into a controlled procedure.

Protect archives and the secrets file

A GitLab backup archive holds repositories, database content and other instance data, and the secrets file holds keys that decrypt data stored in the database. Store both under encryption and restrict read access to a small group of administrators, and keep the two in separate locations so one leak does not expose everything. Confirm with your backup tooling how encryption is applied, since it is not a default you can assume. Check that copies made off-site follow the same rules.

Keep restore packages in a trusted repository

A restore must run on the exact GitLab version and edition that created the backup, so the installation package for that version is part of the recovery evidence. Mirror the packages you need into a repository you control, record the version string next to each backup, and verify package checksums before installing. Without a local copy, a restore can stall if the public package location is unavailable during an incident.

Separate the test environment from production

Restore tests should run on an isolated host that cannot send email, trigger runners, or reach production integrations. Disable outbound webhooks and mail delivery in the test copy, and use separate credentials for any connected service. This prevents a rehearsal from changing live projects, pipelines or user notifications, and it gives you a safe place to check the restored data before anything is cut over.

Log restore activity as change evidence

Every restore attempt should leave a record: who started it, which backup and version were used, which configuration files changed, and whether the instance passed its checks afterward. Keep these records with your change management system so auditors and incident reviewers can trace what happened. Ask your team which logs capture the restore commands and where they are retained before you rely on them.

Limit who can run restores

Restoring an instance overwrites data and can expose it to whoever holds the backup, so restore rights should sit with a named, small group of administrators. Require a second person to approve the backup selection and target version before a production restore begins. Review that access list on a fixed schedule and after staff changes, because a restore is one of the most sensitive operations an administrator can perform.

Roll out restore configuration changes gradually

The GitLab hardening guidance is a work in progress and recommends applying changes gradually rather than all at once. Apply this to restore configuration as well: change one setting at a time in the test copy, confirm the instance still starts and passes checks, then promote the change to production. Record each step so that if a restored instance behaves differently, you can identify which change caused it.

Restoring GitLab backups: questions teams ask before hiring help

Can a GitLab Free backup be restored onto a Premium instance?

A backup restores onto the same GitLab version and the same edition it came from, so the answer depends on the rule you follow rather than on the tier you pay for. Moving a backup between editions is a separate migration task, not a restore step. Premium is listed at 29 US dollars per user per month billed annually on the GitLab pricing page, but a license change does not alter the rule for restoring a backup. Confirm the exact upgrade procedure for your source and target editions in the GitLab backup and restore documentation before you plan the move.

What determines the cost and effort of planning restore tests?

The main drivers are the number of GitLab nodes, the size of the database and Git data, whether repositories and artifacts sit in object storage, and how many environments must be rehearsed. A single-node instance with local storage is a small exercise. A multi-node reference architecture with Gitaly, PostgreSQL and Redis needs a plan for each component. Fixed-scope work is quoted from a written scope that lists the environments, the restore targets and the evidence you want to keep. DeployOpen does not publish a price list, so ask for a quote that names each deliverable.

How long does a GitLab restore take, and what drives the duration?

Restore duration depends on the backup size, the speed of the storage and network it reads from, the number of repositories, and whether the restore must reconfigure and reconcile services afterward. Restore time is the variable you measure in your own environment, because no duration is published for every instance. Rehearse the restore on hardware that resembles production, time each step, and record the result. The GitLab backup and restore documentation describes the steps that you should time.

What does a restore project need from our internal team?

Expect to provide access to the source and target environments, a named owner for the gitlab-secrets.json and gitlab.rb files, the current backup inventory, and someone who can approve maintenance windows. Your team also decides which version and edition the restored instance must run, because that choice comes before any restore step. Internal staff should review the runbook and sign off on the evidence from each rehearsal. Ask the provider which of these tasks they perform and which stay with your team.

Can our own engineers run test restores without outside help?

Yes, a team with Linux administration experience can run test restores if it keeps the same GitLab version and edition, restores the secrets file first, and records each step. The work is repeatable, so a team can build a checklist and rehearse it on a regular schedule. Outside help is most useful when the instance is large, uses object storage or Geo, or when the restored system must pass a compliance review. Compare the internal effort against the scope you would otherwise buy, and confirm the upgrade stops with the GitLab upgrade paths documentation if the target version differs from the backup.

How does the restore procedure change for a different install method?

The restore rules stay the same, but the commands and file locations change with the install method. The Linux package, the Helm chart, the GitLab Operator, Docker and source installs each handle services and configuration differently. Restoring onto Kubernetes also requires a stateful layer outside the cluster, because the reference architectures do not support PostgreSQL or Redis inside Kubernetes. Check the GitLab installation methods page and confirm each step against the method you run before you write the runbook.

Do restore tests need to repeat after every GitLab upgrade?

Yes, the restore should be rehearsed again after any version change, configuration change or change to the backup tooling. A backup made on one version cannot be restored onto a different version under the same-version rule, so the rehearsal must match the version you run today. Plan the retest into your upgrade calendar, and check the GitLab maintenance policy for the current stable release schedule. Ask any provider to include a retest in the written scope when upgrades are part of the engagement.

How DeployOpen plans and tests GitLab restores

DeployOpen starts every restore plan by fixing three facts about the instance: the exact GitLab version that wrote the backup, the edition and tier in use, and the install method (Linux package, Helm chart, GitLab Operator, Docker or source). The same-version, same-edition rule means the restore target must run the identical GitLab version and edition as the source, so the plan records the installed package version on both sides and confirms that the replacement host can be pinned to it. Install method matters because it changes where the configuration, secrets and data live and which commands rebuild them. Where the source is on a Kubernetes-based install, the plan also notes that stateful components such as PostgreSQL and Redis are not run inside Kubernetes in the reference architectures, so the restore path must reach those services on their own hosts or managed services. Ask your team to confirm the exact version and edition in writing before any restore is scheduled.

Test restores run in an isolated environment inside the client's own infrastructure, built from the same package version as production and kept off the production network. The first test restores gitlab-secrets.json and gitlab.rb before any data, because an instance restored without its matching secrets file can lose access to encrypted database values. Only after that does the test restore the backup archive, then checks sign-in, repository clones, CI variables, container registry access and background job health. Each test records how long each step took, which steps needed manual intervention and which backup ID was used, so the run book reflects measured behavior rather than assumptions. Artifacts, LFS and uploads stored in object storage are restored from the storage provider's versioning or replication, not from the archive, so the test also confirms that path.

The run book is the deliverable that makes the test repeatable by people who were not in the room. It lists the version and edition pins, the install method commands, the order of secrets and configuration restoration, the verification checklist and the rollback point. It also states which upgrade stop applies if the target version must move forward after restore, since required upgrade stops mean a restored instance cannot simply jump to a later release. DeployOpen delivers the run book as part of a fixed-scope engagement with the scope and deliverables agreed in writing first, and retests it after each GitLab upgrade or change in install method. Ask any partner for the test environment design, the version pins they will use and the checklist they will hand over, and confirm the requirement for matching packages with your own change process before an incident forces the question.

How DeployOpen scopes, delivers and supports GitLab restore planning

DeployOpen plans, implements, documents and supports self-hosted open-source platforms inside your own infrastructure, including cloud accounts, data centers and air-gapped networks. For GitLab restores, that means matching the restore target to the backup's GitLab version and edition, planning the package versions, and proving the procedure works in a test environment before an incident or migration.

How we scope

  • Inventory the running GitLab version, edition, install method and every node that holds state before choosing a restore target.
  • Record which GitLab package versions, secrets files and configuration files must be retained alongside each backup archive.
  • Agree the written scope in advance, including which restore scenarios are covered and which environments will be used for testing.

How we build

  • Prepare a restore runbook that installs the matching package version and edition before any data is restored.
  • Restore into a separate, isolated test instance, starting with gitlab-secrets.json and gitlab.rb, then the backup archive.
  • Verify restored projects, users, CI/CD settings and runner registration against a checklist agreed in the scope.

How we hand over

  • Deliver the restore runbook, version and edition matrix, and a record of each test restore with its results.
  • Walk your operations and platform team through the procedure so they can repeat it without DeployOpen present.
  • Document the upgrade stops your instance must pass through, so backup and restore plans stay aligned with later upgrades.

How we support

  • Offer ongoing support, upgrades and continuous testing as a retainer, when your environment needs regular restore verification.
  • Re-test restores after each GitLab upgrade, edition change or change to the secrets or storage configuration.
  • Confirm with your team the support model, response expectations and retention periods before work starts, as these are set in the written agreement.

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.