Article

How to upgrade self-managed GitLab safely: required stops, backups and rollback

How GitLab releases and patches work, why you cannot jump straight to the latest version, what to check and back up first, how to upgrade the Linux package, Docker and the Helm chart, and how to roll back if something goes wrong.

October 23, 2026
7 min read
How to upgrade self-managed GitLab safely: required stops, backups and rollback

On October 21, 2026 GitLab fixed CVE-2026-110264, a vulnerability with the maximum CVSS score of 10.0, and many self-managed GitLab administrators had to upgrade in a hurry. For some it was a five-minute patch. Others found their server two or three major releases behind, with no way to jump straight to the latest version. Here is how to upgrade GitLab without turning it into an outage: how releases work, what required upgrade stops are, what to prepare in advance and how to roll back if something goes wrong.

How GitLab ships versions

GitLab versions follow major.minor.patch, for example 19.5.1. A minor release ships every month on the third Thursday. A major release ships once a year, usually in May; GitLab 20.0 is scheduled for May 2027. Patch releases come out twice a month on Wednesdays, one in the week before the minor release and one in the week after. Critical vulnerabilities get unscheduled patches, as happened with CVE-2026-110264.

GitLab backports security fixes to the current stable release and the two previous monthly releases, which right now means 19.5, 19.4 and 19.3. Regular bug fixes go to the current release only. Hence a simple rule: if your GitLab is older than the last three minor versions, the next security patch may not reach you. For CVE-2026-110264 GitLab made an exception and shipped fixes back to 18.11, but you should not count on that every time.

Required stops: why you cannot jump straight to the latest version

An upgrade runs database migrations, and some of them assume that earlier ones have already completed. That is why the documentation defines required upgrade stops: versions you must pass through. Starting with GitLab 17.5 they fall on minor versions x.2, x.5, x.8 and x.11. For the 18 branch that means 18.2, 18.5, 18.8 and 18.11; for 19, it is 19.2, 19.5, 19.8 and 19.11. Older branches have their own lists, and some stops depend on your setup, for example ones that apply only to instances with many users or packages.

The process: upgrade to the first required stop after your current version, wait for background migrations to finish, move on to the next stop, and repeat until you reach the target. The Upgrade Path tool from the GitLab Support team calculates the exact route for your version. For example, going from 18.4 to 19.5 looks like 18.5 → 18.8 → 18.11 → 19.2 → 19.5, waiting for migrations at every step.

Preparation: what to do before the upgrade

  1. Find your current version. It is shown in the Admin area and on the /help page for administrators; on a Linux package server, also in the output of sudo gitlab-rake gitlab:env:info.
  2. Read the upgrade notes for every version on the route. They describe changes that need action: removed settings, new environment requirements, long-running migrations.
  3. Check background migrations. In the UI: Admin → Monitoring → Background migrations; the Queued and Finalizing tabs should be empty, with nothing under Failed. From the console on GitLab 18.9 and later, run sudo gitlab-rake gitlab:background_migrations:list; on 18.8 and earlier, sudo gitlab-rake gitlab:background_migrations:status. Since 19.5 there is also sudo gitlab-rake gitlab:background_migrations:wait, which waits for migrations to finish and suits scripts. Do not use finalize to check status: it is a repair tool for failed migrations.
  4. Take a backup. Run sudo gitlab-backup create on a Linux package install or docker exec -t <container> gitlab-backup create on Docker. Note that the backup does not include configuration. Save /etc/gitlab/gitlab-secrets.json and /etc/gitlab/gitlab.rb separately, and do not store them next to the backup. Without gitlab-secrets.json, GitLab cannot decrypt data in the database: CI/CD variables, tokens, two-factor settings. TLS certificates and SSH host keys are worth saving too.
  5. Check PostgreSQL. GitLab 18 requires PostgreSQL 16.5 or later, GitLab 19 requires 17 or later. If the database is external, such as a managed cloud service, you will have to upgrade it separately and in advance.
  6. Check your runners. The GitLab Runner major and minor version should match GitLab's. Backward compatibility between minor versions is guaranteed, but new features may need a newer runner. GitLab recommends upgrading runners to the target version along with the server.
  7. Rehearse on a copy. The best way to learn how long migrations take and where things break is to run the upgrade on a clone of production. Test restoring from backup there too: a backup you have never restored is a hope, not a plan.

The upgrade: Linux package, Docker and Helm

Linux package (Omnibus). Package managers install the latest version by default, so when upgrading through stops you need to pin the version: sudo apt update && sudo apt install gitlab-ee=<version>-ee.0 on Debian and Ubuntu, or sudo dnf install gitlab-ee-<version>-ee.0.el9 on RHEL-compatible systems; use gitlab-ce for Community Edition. The package backs up the database automatically before installing a new version, but that does not replace your own full backup. You can enable maintenance mode and pause CI/CD for the duration.

Docker. Stop and remove the container (docker stop gitlab, docker rm gitlab), pull the image for the target version (docker pull gitlab/gitlab-ee:<version>-ee.0) and start it again with the same volumes for configuration, logs and data. GitLab runs the migrations on first start. With Docker Compose, change the image tag in docker-compose.yml, then run docker compose pull and docker compose up -d. The latest tag is a bad idea in production: it makes skipping a required stop far too easy.

Helm chart on Kubernetes. Chart versions are numbered differently from GitLab versions, so check the version mappings table. Export your current values with helm get values gitlab > gitlab.yaml, then run helm upgrade gitlab gitlab/gitlab --version <chart version> -f gitlab.yaml. The chart documentation recommends going one minor version at a time: skipping releases can apply database schema changes in the wrong order.

Can you avoid downtime

GitLab supports zero-downtime upgrades only for multi-node installations with a load balancer and highly available Consul, PostgreSQL and Redis. In this mode you upgrade strictly one minor version at a time, and components in a set order: Consul, PostgreSQL, PgBouncer and Redis first, then Gitaly and Praefect, and Rails and Sidekiq last. Components without high availability are still upgraded with downtime. For single-server GitLab, downtime is unavoidable: plan a maintenance window and warn your team. How long it takes depends on the database size and the migrations, which is exactly why a rehearsal on a copy pays off.

Checks after the upgrade

  • sudo gitlab-rake gitlab:check checks configuration and services.
  • sudo gitlab-rake gitlab:doctor:secrets checks that encrypted data in the database can be decrypted with the current secrets.
  • By hand: users can sign in, projects and issues load, git clone and git push work, a pipeline runs, runners pick up jobs, and images can be pushed to and pulled from the registry.
  • The new version's background migrations must finish before the next step on the route.
  • Back up the configuration again: gitlab-secrets.json can change after an upgrade.

If you need to roll back

You cannot roll GitLab back just by reinstalling the old package: the migrations have already changed the database. A rollback needs a database backup made on the exact version and edition you are going back to. For a Linux package install: stop Puma and Sidekiq, remove the current package, install the previous version, run sudo gitlab-ctl reconfigure and restore the backup. That is why you take a backup right before every step on the route, not just once at the start.

In short

  1. Upgrade regularly: if you stay within the last three minor versions, security patches take minutes.
  2. If you have fallen behind, calculate the route in the Upgrade Path tool and pass every required stop, waiting for background migrations.
  3. Before every step, take a backup, plus gitlab-secrets.json and gitlab.rb separately.
  4. Keep an eye on PostgreSQL and runner versions.
  5. Rehearse on a copy and keep a rollback plan.

We maintain self-managed GitLab and CI/CD for our clients' projects. We will calculate the upgrade route, rehearse it on a copy, upgrade production with a backup and a rollback plan, check runners and pipelines, and set up regular upgrades so the next critical patch takes minutes, not a weekend.

Sources: GitLab release and maintenance policy, upgrade paths, plan your upgrade, background migrations, backing up GitLab, installation requirements, GitLab Runner, upgrading the Linux package, upgrading Docker instances, upgrading the Helm chart, zero-downtime upgrades, rolling back.

How we can help

-5%
Special Offer
Extra discount with promo code on any project
FIRST5
Get Discount

Related posts

Call the AI assistant