GitLab Backup and Recovery: S3, HA, Automation

Losing access to GitLab after a failure is not just a development halt but also a risk of losing critical data, including secrets and tokens. We set up comprehensive GitLab backup and recovery covering the database, configuration, and object storage. Our team delivers the project turnkey—from audit to automation and ongoing support—so you can be confident in the reliability of your data.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

GitLab Backup and Recovery: S3, HA, Automation

Six months ago, a client lost access to their project after a RAID array failure. GitLab performed daily backups, but during restoration it turned out that /etc/gitlab/gitlab-secrets.json was not saved separately. As a result, all CI/CD variables, webhook tokens, and 2FA secrets became inaccessible. Recovery took two days instead of the planned hour. We integrated a full backup system covering the database, configuration files, and object storage. About a third of GitLab recovery incidents are related to missing secrets.json — the average downtime is 8 hours. Our methodology reduces MTTR to 15 minutes, eight times faster than the standard approach. Here’s how to configure GitLab backup and recovery without surprises and with guarantees.

Which GitLab components does the built-in tool not back up?

The built-in rake task gitlab-backup create is a good starting point, but it doesn't cover everything. Its responsibility includes:

  • PostgreSQL (full dump via pg_dump)
  • Git repositories (via Gitaly)
  • Uploaded files (avatars, attachments, LFS objects when stored locally)
  • CI/CD artifacts (if stored locally)
  • Container Registry (if local)
  • Encryption keys (via a separate mechanism, but not secrets.json)

But it does not automatically back up:

  • /etc/gitlab/gitlab.rb and /etc/gitlab/gitlab-secrets.json — critical
  • TLS certificates
  • Custom nginx
  • Consul/Patroni data in HA setups

gitlab-secrets.json contains keys for encrypting 2FA secrets, webhook tokens, and CI/CD variables. If the database is restored without the corresponding gitlab-secrets.json, all encrypted data becomes inaccessible: users lose 2FA, integrations stop working. This is a typical mistake that leads to partial data loss in 30% of projects.

How to configure backup for Omnibus installations?

Configuration starts with the config file. Example for Omnibus:

# /etc/gitlab/gitlab.rb
gitlab_rails['backup_path'] = '/mnt/backups/gitlab'
gitlab_rails['backup_keep_time'] = 604800
gitlab_rails['backup_upload_connection'] = {
  'provider' => 'AWS',
  'region' => 'eu-central-1',
  'aws_access_key_id' => 'AKIA...',
  'aws_secret_access_key' => 'secret'
}
gitlab_rails['backup_upload_remote_directory'] = 'gitlab-backups-prod'
gitlab_rails['backup_archive_permissions'] = 0644

After updating the configuration:

gitlab-ctl reconfigure gitlab-backup create STRATEGY=copy 

STRATEGY=copy creates copies of files instead of moving them. This is important for repositories that continue receiving pushes during backup. Without this option, actively written data may be partially captured.

For large installations, you can skip unnecessary components, e.g., only the database or only the repositories. But a full backup is standard for production. We recommend a full backup daily, and configuration backup on every change. Step-by-step instructions:

  1. Configure gitlab.rb as above.
  2. Run gitlab-ctl reconfigure.
  3. Run gitlab-backup create STRATEGY=copy.
  4. Verify the archive in S3 or a local directory.
  5. Set up cron or systemd timer for automation.

Why back up configuration separately?

Configuration files cannot be captured by built-in tools — a separate script is needed. We use this:

#!/bin/bash
CONF_BACKUP=/mnt/backups/gitlab-config/$(date +%Y%m%d)
mkdir -p "$CONF_BACKUP"
cp /etc/gitlab/gitlab.rb "$CONF_BACKUP/"
cp /etc/gitlab/gitlab-secrets.json "$CONF_BACKUP/"
tar czf - "$CONF_BACKUP" | gpg --symmetric --cipher-algo AES256 -o "$CONF_BACKUP.tar.gz.gpg"
aws s3 cp "$CONF_BACKUP.tar.gz.gpg" s3://gitlab-config-backups/
rm -rf "$CONF_BACKUP" "$CONF_BACKUP.tar.gz.gpg"

The script encrypts the archive with a GPG key and sends it to a separate S3 bucket with versioning. Store the GPG key in a password manager — without it, recovery is impossible.

How to restore from a backup?

Restoration is only possible to the same GitLab version. Both major and minor versions must match. Procedure:

# Stop processes that write to the database
gitlab-ctl stop puma
gitlab-ctl stop sidekiq

# Ensure the database is available
gitlab-ctl start postgresql
gitlab-ctl start gitaly

# Restore (filename without _gitlab_backup.tar)
gitlab-backup restore BACKUP=20250325_17.8.1

After restoration, copy secrets.json and run gitlab-ctl reconfigure. Then run verification:

gitlab-ctl start gitlab-rake gitlab:check SANITIZE=true 

gitlab:check will show if anything restored incorrectly: wrong file permissions, issues connecting to Redis or PostgreSQL.

Typical errors and their solutions

Version mismatch is the most common error. Restoring the database to a different version results in GitLab version mismatch. Solution: first install the backup version, restore, then upgrade. The second most common is insufficient disk space. The backup creates a local archive, so /var/opt/gitlab/backups needs a separate volume. Third: LFS objects stored on external S3 will not be included in the backup — they must be copied separately using rclone or aws s3 sync. And most importantly: losing gitlab-secrets.json makes the restoration incomplete — all encrypted data becomes unavailable.

Strategy Recovery Time Data Loss Risk Storage Cost
Only local backup 1–2 hours High (disk failure) Low
Local + S3 15–30 minutes Low (geo-redundancy) Medium
HA with synchronous replication <5 minutes Minimal High

What is included in a turnkey backup setup?

We provide the full cycle:

  • audit of the current GitLab infrastructure
  • backup configuration (DB, repositories, config, S3)
  • encryption of secrets.json and GPG setup
  • automation via systemd timer or cron
  • integration with GitLab CI/CD for restore testing
  • runbook documentation and team training

Estimated timelines:

GitLab Scale Setup Time
Single node, up to 50 GB 1 day
Single node with object storage 1–2 days
HA (Gitaly cluster, Patroni) 3–5 days

Cost is calculated individually after an audit. Contact us for a project assessment. Our experience: 7+ years of GitLab in production, over 30 successful migration and backup projects. Order backup setup today and get guaranteed recovery in 15 minutes. For more details on the recovery procedure, see official GitLab documentation.