Moving self-managed GitLab to a new server or cloud without losing a cutover window
Moving a self-managed GitLab to new hardware, a new cloud account or a new network is a sequenced backup, restore and DNS switch with a planned freeze. The effort depends on three things: the size of the instance, the volume of Git data, and how many integrations, runners, webhooks and scripts point at the GitLab URL. This page covers Linux package installs that follow GitLab's documented new server procedure. If you run the Helm chart, the GitLab Operator or a Docker install, the steps and data locations differ, and you should confirm the procedure for your install method before planning dates.
The documented procedure blocks CI/CD job requests with an NGINX rule, enables maintenance mode where your edition supports it, disables Sidekiq cron jobs and waits for background queues to drain. Only then do you take a gitlab-backup and restore it on the new server, and only after that do you switch DNS or the load balancer. Plan the freeze around that order. Confirm with your team which runners, external systems and inbound mail routes will be idle during the window, because jobs and messages that arrive mid-freeze can be queued, lost or processed twice.
For large instances, the procedure suggests moving Git and object data directly with tools such as rsync or volume snapshots instead of relying only on the backup archive. The documentation warns that running the old and new servers at the same time can cause uncoordinated processing, such as both servers ingesting incoming email. Decide in advance how the old server will be stopped or disabled, who signs off on the DNS change, and how you will verify the cutover with a restored copy before the old server is decommissioned. Ask your team to confirm each of these points against the GitLab migrate to a new server documentation for the version you run.
Which parts of a GitLab instance move with the backup and which need separate handling
This table compares each component of a Linux package GitLab instance against the standard backup, the separate transfer it may need, and what to reconfigure on the new host. Read the middle columns first to plan the copy, then use the last column as a checklist before you switch DNS. Confirm the backup scope for your exact version in the backup and restore documentation, because the procedure does not cover every item.
| Component | Standard backup | Separate handling | On the new host |
|---|---|---|---|
| Database contents | Covered by gitlab-backup | None needed when the backup is taken and restored at the same version | Restore with gitlab-backup restore, then run reconfigure and check the health of the services |
| Git repositories | Included in the backup task | For large instances, the procedure suggests rsync or volume snapshots of the Git data | Confirm paths, ownership and permissions match the new install before restoring |
| Uploads and attachments | Included in the backup task (confirm for your version) | Move directly only if your storage layout is unusual or very large | Check that the storage paths in gitlab.rb point to the restored data |
| CI/CD variables | Stored in the database, so covered by the backup | Values are encrypted with the secrets file, so the secrets file must move too | Verify that variables decrypt after restore; if they do not, the secrets file is the first suspect |
| gitlab-secrets.json | Not part of the database backup; confirm in your version's docs | Copy to the new host before reconfigure, keeping the same contents | Place it in the configuration directory and keep ownership and permissions consistent |
| gitlab.rb and related configuration | Not part of the backup task | Copy and reconcile by hand; confirm the list of files for your version | Update the external URL, email settings and storage settings for the new host |
| Runner registrations and runner hosts | Runner hosts sit outside the GitLab backup | Runners keep their own configuration files and must be able to reach the new URL | Update the GitLab URL in each runner configuration and confirm the jobs still pick up |
| Object storage, registries and packages | Depends on where data is stored; confirm for your version | External object storage stays in place, so only the connection settings change | Reconfigure endpoints and credentials, then test uploads and pulls before the cutover |
| External integrations and incoming email | Integration settings in the database are covered; external systems are not | Update webhooks, OAuth redirect URIs and mail routing to the new hostname | Disable incoming email on the old host so the two servers do not both process messages |
Which documented tools move the data
The gitlab-backup create and gitlab-backup restore tasks are the documented way to move the database and most application metadata. The archive covers PostgreSQL data, project and group metadata, issues, merge requests, CI/CD records and uploads, and it is restored onto a server running the same GitLab version. The backup does not include everything you need to run the instance. It leaves out gitlab.rb, gitlab-secrets.json and SSH host keys, and it is not a substitute for copying large repository data when the instance is big. Plan the restore as a rehearsal on the new server before the production run.
- Version match: The restore target must run the same GitLab version that produced the archive. Confirm the exact version with your upgrade plan before you start.
- Scope: Ask whether the backup includes repositories, uploads, and object storage content for your instance, since these have separate options and sizes.
- Timing: The backup runs while the source is quiesced. Measure duration on a copy of your data, not on assumptions.
- Verification: After restore, check project counts, a sample of merge requests and a clone of a large repository.
- Ownership: Confirm file permissions on the restored data directories before starting services.
Before relying on the archive, confirm which components your instance uses and which ones the backup skips in your installed version.
For large instances, the documented procedure suggests moving Git repositories and object data directly with tools such as rsync or volume snapshots instead of pushing them through the backup archive. This shortens the copy window when repository storage is many times the size of the database. The copy has to be consistent with the metadata in the restored database, so it runs only while writes are stopped. Snapshot-based copies depend on your storage platform's ability to take crash-consistent snapshots of the data volumes.
- rsync passes: Run a first pass while the source is live to reduce the final delta, then a final pass with writes stopped.
- Volume snapshots: Use them where the hypervisor or cloud provider supports consistent snapshots of the GitLab data volume.
- Object storage: Artifacts, LFS objects and uploads may live in object storage. Confirm whether they are moved with the copy or stay where they are.
- Permissions and ownership: Preserve file ownership and modes so the GitLab services can read the data after the move.
- Limits: A direct copy does not validate the database. Pair it with the restore check above.
Ask your storage team to confirm snapshot consistency and to test one restore before the cutover.
Some state lives outside the backup and must be carried across by hand. The main files are /etc/gitlab/gitlab.rb for configuration, /etc/gitlab/gitlab-secrets.json for encryption keys, and SSH host keys that let clients trust the server after the move. Without gitlab-secrets.json, data encrypted in the database, such as CI/CD variables, two-factor secrets and tokens, cannot be decrypted on the new server. The secrets file must match the one that was active when the backup was made, so do not generate a new one on the target.
- gitlab.rb: Copy it and review external URL, storage paths and SMTP settings for the new host.
- gitlab-secrets.json: Copy it exactly, and keep a protected offline copy of the original.
- SSH host keys: Carry them across so Git over SSH clients do not see a changed host fingerprint.
- TLS and certificates: Plan certificate installation for the new host name before DNS changes.
- Other tools: Record any custom Nginx, mail or monitoring settings that are not managed by
gitlab.rb.
Before cutover, compare checksums of the secrets file on both servers and confirm that the restored instance decrypts a known CI/CD variable.
How the cutover runs from inventory to decommission
The documented sequence moves a Linux package GitLab to new infrastructure by freezing inbound work, taking a consistent backup, restoring it on the target, and only then sending users to the new host. Each step closes with a check, so the team knows when it is safe to move on.
Inventory the instance and confirm versions
Record the current GitLab version, edition, installed components, the gitlab.rb and gitlab-secrets.json files, external services such as object storage or a separate database, and every integration that sends traffic or email to the instance. Confirm the target host runs the same GitLab version, because restores only go into a matching release. Owner: the GitLab administrator with the platform team. Done when the inventory is written down and the target version matches the source.
Rehearse the restore on the target
Install the same GitLab version on the new server, then restore a recent backup from a copy of the source instance. Run the rehearsal end to end, including logins, a Git clone over SSH and HTTPS, and a sample pipeline on a test runner. Record every manual step the rehearsal needed so the production run contains no surprises. Done when a restored test copy passes these checks and the steps are written into a runbook.
Block CI job requests at the proxy
Add an NGINX rule on the existing server that rejects CI/CD job API requests from runners, so no new jobs start during the move. Runners already executing jobs may still finish, so the team should check which jobs are running before continuing. Owner: the team that manages the reverse proxy. Done when a test request to the job endpoint is refused and the active job list is known.
Enable maintenance mode and disable Sidekiq cron
Turn on maintenance mode where your edition supports it so users cannot push changes, then disable Sidekiq cron jobs so scheduled background work stops creating new tasks. Check the instance settings to confirm that maintenance mode is active and that writes are blocked. Done when a test push is refused and the cron schedule shows no active background jobs.
Wait for Sidekiq queues to drain and take a backup
Watch the Sidekiq queues until they empty, since a backup taken while jobs are still running can capture inconsistent state. Then run gitlab-backup create on the source and store the archive, along with gitlab-secrets.json and gitlab.rb, in a location the new server can reach. For large instances, plan the Git and object data copy separately, as described in the next step. Done when queues are empty and the backup archive and secrets files are verified on the target side.
Move large Git data and restore on the new server
For large instances, copy repository and object data directly with a tool such as rsync or by using volume snapshots, rather than pushing it through the backup archive alone. Then restore the backup on the new server, reconfigure the instance, and run the health checks. Confirm that repositories open, the database migrations completed, and background jobs run on the new host. Done when the restored instance passes its checks and a sample clone matches the source commit.
Switch DNS or the load balancer and avoid parallel processing
Point the DNS record or load balancer target to the new server only after the restore is verified. Keep the old host out of live traffic and incoming email from that moment, because the documented procedure warns that running both servers at once can cause uncoordinated processing, such as two systems ingesting the same email. Re-enable CI job requests and confirm runners reach the new instance. Done when users, runners and mail routing all reach only the new server.
Decommission the old host after a agreed period
Keep the old server in a stopped state for a period the team agrees in advance, so a rollback path exists, then remove its mail routing, runner registrations, backups jobs and DNS records. Archive its final backup and configuration under your retention policy. Confirm with the business owners and your compliance lead before deletion. Done when the old host is retired, its data is retained as your policy requires, and the runbook is updated for the next move.
What drives the effort and duration of the move
This table lists the factors that change how much work a server or cloud move of self-managed GitLab involves, who carries each piece, and what to ask a partner to quote. Read each row as a question to answer about your own instance before requesting a fixed-scope proposal, since no duration is set until the inventory is complete.
| Driver | Why it changes effort | Who pays and what to ask for |
|---|---|---|
| Repository and object data size | Git repositories, LFS, uploads and artifacts set how long the copy takes and whether rsync or volume snapshots are practical during the window. | Your team supplies storage and transfer capacity. Ask the partner to quote the data inventory, copy method and a rehearsal copy. |
| Database size | The backup and restore of PostgreSQL data drives restore time, and large restores need validation before DNS changes. | Your team covers database capacity on the new host. Ask for the restore rehearsal steps and the checks used to confirm data integrity. |
| Number of CI runners | Each runner may need re-pointing to the new URL, and runners that stay online can pick up jobs during the cutover if they are not paused. | Runner ownership usually sits with your platform team. Ask the partner to list every runner, its executor and the re-registration or URL change needed. |
| Inbound webhooks and integrations | Chat, issue tracker, Kubernetes and secrets integrations point at the old address and must be updated or verified after the switch. | Integration owners in your teams confirm endpoints. Ask for an inventory of webhooks and a test plan for each one. |
| Email ingestion | If incoming email reaches both servers, work can be processed twice, so mail routing must be switched in step with DNS. | Your mail team owns MX and relay changes. Ask the partner to define the mail cutover order and who signs off. |
| Geo or high availability topology | Geo secondaries, Gitaly Cluster, Patroni or Redis Sentinel each add nodes to stop, reconfigure and verify. | Platform engineering covers the topology. Ask for a per-component runbook and whether the replica rebuild is in scope. |
| Custom gitlab.rb and secrets | Non-default settings, external object storage and the secrets file must be carried over exactly or the restored instance will not start cleanly. | Your team provides the current configuration files. Ask the partner to diff the configuration and document every change made. |
| Cutover window your business accepts | A shorter window requires more preparation, rehearsal and parallel validation, which raises the work done before the move. | Business owners set the window. Ask the partner how the plan scales to that window and what is done in advance. |
Why switching DNS without double processing matters
The DNS or load balancer switch is the point where a GitLab move can go wrong without anyone noticing. If the old and new servers both accept traffic for the same hostname, work gets processed twice or lands on the wrong host. Incoming email is the clearest case: the migration guidance warns that when old and new servers run at once, both can ingest the same mail, and the same risk applies to pipelines that a push or webhook triggers on each instance. Webhooks sent to the wrong host can also update external tools with data from a server that no longer holds the current state. Before the cutover, the team should map every inbound path (SMTP, webhooks, API clients, runners, and any service that calls the instance) so they know what must stop on the old server and what must start on the new one.
A planned freeze reduces this risk because it stops new state from being written to the old server before the backup is taken. The migration procedure blocks CI/CD job requests with an NGINX rule, enables maintenance mode where the edition supports it, disables Sidekiq cron, and waits for queues to drain before running gitlab-backup. The restore on the new server must then be verified, for example by checking projects, users, and a test pipeline, before anything points to it. Only after that check should the team make one deliberate DNS or load balancer change. Keep the old server stopped or unreachable for inbound traffic, not merely idle, until the new server is confirmed. Confirm each of these steps, including the exact NGINX rule, maintenance mode availability, and Sidekiq commands, against the GitLab version you run, because the procedure and its commands can differ between releases.
What usually goes wrong during a GitLab server move
Most failed GitLab moves come from a small set of avoidable mistakes: missing secrets, mismatched versions, stale runner and DNS settings, and copies taken while data is still changing. Each risk below pairs with a prevention step you can plan, rehearse and verify before the cutover window.
Secrets file left behind
The gitlab-secrets.json file holds the keys that encrypt database values such as CI/CD variables, two-factor secrets and runner tokens. A backup restores the data but not these keys, so encrypted fields become unreadable on the new server. Copy the secrets file with the backup, keep the original gitlab.rb settings, and confirm that stored CI/CD variables still decrypt after the restore.
Backup and target version mismatch
A backup can only be restored onto a GitLab instance running the same version it was taken from. Install the target server at the exact version of the source, restore there, and only then upgrade in the required stops. Rehearse the full restore on a copy of the server first so version and package problems surface before the production window.
Runners still pointed at the old URL
Runners store the URL of the instance they were registered to, so after the move they may keep polling a server that no longer serves jobs, or fail to report results. List every runner, confirm its registered URL and token, and re-register any runner that points at the old address. Keep Runner versions aligned with the new GitLab version and test one job per runner group before declaring the cutover complete.
CI jobs starting mid-backup
If pipelines keep starting while the backup runs, jobs can write to repositories and databases after the snapshot was taken, leaving the restore inconsistent. Block CI/CD job requests with an NGINX rule before maintenance begins, disable Sidekiq cron jobs, and wait for background queues to drain. Confirm the queues are empty before you start the backup so the backup captures a settled state.
Rsync copies taken during writes
Copying Git and object data with rsync while the instance is still writing produces repositories that are half updated or missing recent pushes. Freeze writes first, then run a final incremental sync or volume snapshot after the drain step. Compare repository counts and sizes on both servers, and run a sample of clones to confirm the copied data is complete.
Stale DNS and double processing
Users, runners and webhooks may keep reaching the old server because of cached DNS records, and running both servers at once can cause duplicate work such as both ingesting incoming email. Lower the record TTL before the window, switch DNS or the load balancer only after the restore is verified, and shut down or disable services on the old server. Ask your DNS team to confirm the TTL in advance.
Questions teams ask before moving GitLab themselves or hiring help
What does it cost to move self-managed GitLab to a new server?
The cost depends on the written scope, not on a list price. DeployOpen does not publish a price list, and a quote follows from the agreed scope. The main cost drivers are the size of the instance and its Git and object data, the number of runners and integrations that must be re-pointed, how many environments need a rehearsal, and whether the target is a single virtual machine, a cloud account or a multi-node layout. Ask the quote to separate the planning and rehearsal work, the cutover window work, and any post-move checks. Ask whether a second rehearsal is included if the first one exposes problems, and what happens if the cutover date moves.
How long does a GitLab server move take, and what slows it down?
The active cutover window is the period when the instance is unavailable for writes, and it is the part teams most need to control. Duration is driven by how long the backup and restore take, which grows with repository count, database size and the volume of uploaded artifacts and attachments. Moving large Git and object data with rsync or volume snapshots can shorten the restore step, but it adds verification work. Queue draining also takes longer on busy instances with many running CI jobs. Confirm with the vendor and your own environment how long a backup and restore take on a copy of your data before setting a window.
What must our team provide before a GitLab migration starts?
A move needs decisions and access from your side before any work begins. Typically this includes administrative access to the current instance and the target host or cloud account, network paths between the two, DNS or load balancer ownership, and a named person who can approve the cutover. You also need a maintenance window agreed with the teams that use GitLab, and a list of who is notified when CI job requests are blocked. Agree on sign-off criteria in writing: which projects must pull, which pipelines must run, and who confirms that the restored instance is correct. Ask the proposal to list these inputs explicitly.
Can our own administrators run the GitLab move procedure themselves?
Yes, a team with Linux and GitLab administration experience can follow the documented procedure, and many do. The documented sequence blocks CI/CD job requests with an NGINX rule, enables maintenance mode where the edition supports it, disables Sidekiq cron, waits for queues to drain, takes a gitlab-backup, restores it on the new server and then switches DNS or the load balancer. The hard parts are less about the commands and more about coordination: stopping incoming email from reaching two servers, keeping secrets such as gitlab-secrets.json intact, and confirming that the restore matches the running version. Ask whether your admins have done a restore before, and whether they can staff a window in which two people are watching the cutover.
What happens to runners and integrations during a GitLab server move?
Runners and integrations are the most common source of surprises after a move, because they hold addresses, tokens and certificates that point at the old server. Check every registered runner, whether it uses the shell, Docker or autoscaling executor, and confirm that it can reach the new URL. Review webhooks, container registry settings, external issue trackers, secrets managers and Kubernetes cluster connections, and plan how each will be re-validated. Keep runner and GitLab versions aligned with the documented guidance. Ask the proposal to include a runner check and a list of integrations, each with an owner who confirms it works after the switch.
Why run a rehearsal before the production GitLab cutover?
A rehearsal runs the same backup and restore on a copy of your data, on target infrastructure that matches production as closely as practical. It shows how long the restore takes, whether the target version and configuration match, whether runners and integrations reconnect, and whether any step in the procedure fails on your data. Problems found in a rehearsal are cheaper to fix than problems found during an agreed window. A rehearsal also gives your team a timed run-sheet and a rollback point. Ask whether the rehearsal results are written up, and whether the production window is only scheduled after the rehearsal passes.
Does a GitLab move need a security or compliance review?
A move changes where secrets, backups and access logs live, so it should be reviewed like any change to a system of record. Confirm who can read backup archives during transfer and at rest, how the gitlab-secrets.json file and other secrets are protected on the new host, and whether firewall and network rules are recreated rather than copied blindly. Keep the change record, rehearsal results and sign-off in a place your auditors can reach. DeployOpen prepares systems, controls and evidence for compliance assessments, but independent auditors issue any assessment result. Ask the proposal how change evidence is captured.
How to verify the new GitLab before decommissioning the old host
Keep the old host running and reachable until every check below passes on the new host. The old server is your rollback path, and it should not be shut down, wiped or have its disks reused until the cutover is signed off. Run the checks against the new instance first through a test hostname or a hosts-file override, then repeat the critical ones after DNS or the load balancer has moved, because clients, cached records and runners may reach the new host by different paths.
Start with sign-in and access. Confirm that administrators and a sample of ordinary users can sign in through the same authentication method they used before, whether that is local passwords, LDAP, SAML or another provider, and that two-factor settings and SSH keys carried over. Then check project and repository access: clone and push over both HTTPS and SSH, confirm group membership and permissions match the old instance, and open several large repositories, merge requests and wikis. Create a test project and run a pipeline on it to confirm that CI/CD configuration, CI/CD variables, and the runner connection all work end to end. Confirm the container registry and package registry with a test push and pull if you use them, since their storage paths are a common gap.
Check the paths that the new host has to receive. Send a test webhook from a project and confirm the target system receives it, and confirm that outbound webhooks and integrations point at the new address. Send and receive email through the instance if incoming email or notifications are part of your workflow, and make sure the old host is not also processing mail. Finally, run a gitlab-backup create on the new host and confirm it completes, because a working backup is the proof that your recovery plan still holds. Confirm the exact checks, commands and configuration keys against the documentation for your installed version before you sign off.
How DeployOpen scopes and delivers the move
DeployOpen is a Chainscore Labs company that plans, implements and supports self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. The cards below describe how a move of self-managed GitLab is scoped in writing, priced from that scope and supported after cutover.
Who we are
DeployOpen is a Chainscore Labs company. We plan, implement, harden, back up, upgrade, document and support self-hosted open-source platforms in the infrastructure you control, including cloud accounts, data centers and air-gapped networks. For a GitLab move, that means the work happens on your servers and storage, under your change control, and the instance never leaves your environment. Ask who on our team will hold the runbook and who has access to your environment during the move.
Fixed-scope agreement
Most engagements are fixed-scope, so the scope, deliverables and timeline are agreed in writing before work starts. For a server move, the written scope should name the source and target hosts, the GitLab version on both sides, the data volumes to move, the DNS or load balancer change, the runner fleet that must be paused, and the acceptance checks. Ask what is excluded, such as runner rebuilds or Geo reconfiguration.
Quote follows the scope
DeployOpen does not publish a price list. A quote follows from the written scope, so the cost moves with the size of the Git and object data, the number of nodes, the cutover window and any extra work such as an upgrade stop during the same change. Ask for the quote to split one-time migration work from any recurring support. Compare it with the internal effort your team would need for the rehearsal and the cutover.
Retainers after cutover
Ongoing support, upgrades and continuous testing are available as retainers. After a move, the common needs are patch and minor release follow-up, backup restore testing, runner version alignment and monitoring of the new host. Agree in writing which tasks are covered, the response expectations and how required upgrade stops are handled, so the post-move instance is not left without an owner.
What we will not claim
DeployOpen prepares systems, controls and evidence for compliance assessments, but it does not issue audit reports, attestations or certifications. Independent auditors and certification bodies do that work. DeployOpen is also not an official partner or reseller of GitLab. When a cutover must be recorded as a change under a control framework, ask us for the evidence we will produce and confirm with your assessor which records they accept.

