Ways to migrate self-hosted GitLab
Self-hosted GitLab can be migrated two ways: the official gitlab-backup mechanism, or a full copy of the Omnibus installation directories. The first method suits moving between GitLab versions, the second suits an as-is transfer to an identical version.
Before migrating, record the package version: the same version of gitlab-ce or gitlab-ee must be installed on both the old and the new server before restoring the backup.
Creating a backup with gitlab-backup create
This command creates an archive with repositories, the database, and uploads, but it does not include configuration or secrets:
gitlab-backup create BACKUP=2026_09_29
ls /var/opt/gitlab/backups/
Copy the archive file, named something like 2026_09_29_16.5.0_gitlab_backup.tar, to the new server with scp or rsync.
Migrating secrets and gitlab.rb
Without the /etc/gitlab/gitlab-secrets.json file, the restored GitLab instance cannot decrypt CI/CD tokens, user 2FA settings, or environment variables. Transfer both configuration files along with the backup:
scp /etc/gitlab/gitlab-secrets.json root@newserver:/etc/gitlab/
scp /etc/gitlab/gitlab.rb root@newserver:/etc/gitlab/
On the new server, apply the configuration with gitlab-ctl reconfigure before restoring the backup.
Restoring on the new server
Stop the data-writing services, leaving only the database and Redis running, then restore the archive:
gitlab-ctl stop puma
gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP=2026_09_29
gitlab-ctl restart
Check the command output for permission restoration errors — a common issue when the /var/opt/gitlab/backups directory was copied without preserving the git:git owner.
Migrating the Container Registry and CI/CD artifacts
Container Registry images are not included in the standard backup once local disk storage exceeds a certain size. Migrate the registry directory separately:
rsync -avz /var/opt/gitlab/gitlab-rails/shared/registry/ root@newserver:/var/opt/gitlab/gitlab-rails/shared/registry/
If GitLab runs in Docker containers, the procedure for migrating the containers and volumes themselves is covered in the article on migrating Docker containers between servers. For large registry directories, use the methods from the article on syncing servers with rsync — this lets you finish copying data without a repeated full transfer.
Verifying the migration
Run a service diagnostic and compare the number of projects and users:
gitlab-rake gitlab:check SANITIZE=true
gitlab-rails runner "puts Project.count"
Check that cloning a repository works over both SSH and HTTPS, that a CI pipeline runs, and that at least one user with 2FA enabled can log in — this is the most common source of problems when secrets were not migrated.
Summary: GitLab migration checklist
- Make sure the GitLab version on the new server matches the original.
- Create a backup with
gitlab-backup createand transfer the archive. - Copy
gitlab-secrets.jsonandgitlab.rbbefore restoring. - Restore the backup and migrate the Container Registry directory separately.
- Check repository cloning, the CI pipeline, and login with 2FA.
After switching DNS to the new server, go through the general post-migration checklist.