GitLab disaster recovery backup/restore CLI
Project description
gitlab-dr
gitlab-dr is a Python package and CLI for GitLab disaster recovery backup and restore operations.
Requirements
- Python
>=3.6 - GitLab admin Personal Access Token (PAT)
- Network access to the source/destination GitLab instances
gitonPATH(required when repo cloning is enabled, which is the default)
Install
pip install gitlab-dr
CLI execution
gitlab_dr --help
python -m gitlab_dr --help
Authentication and environment variables
All options can be supplied via environment variables instead of CLI flags. Tilde (~) expansion is supported in all path values.
| Variable | CLI flag | Description |
|---|---|---|
GITLAB_DR_URL |
--gitlab-url |
GitLab instance URL |
GITLAB_DR_TOKEN |
--token |
GitLab admin PAT |
GITLAB_DR_PASSWORD |
(prompted) | Password for encrypted archives |
GITLAB_DR_CLIENT_CERT |
--client-cert |
PEM client certificate path (mTLS) |
GITLAB_DR_CLIENT_KEY |
--client-key |
PEM client key path (mTLS) |
GITLAB_DR_CA_CERT |
--ca-cert |
Custom CA bundle path |
GITLAB_DR_URL and GITLAB_DR_TOKEN are required (either as env vars or CLI flags). GITLAB_DR_PASSWORD is read automatically when --encrypt is set, falling back to an interactive prompt if not set.
Usage
Backup
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--token "$GITLAB_DR_TOKEN"
Scope to a specific group or nested subgroup:
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--group my-group
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--group my-group/sub-group
Include full git repository contents as git bundles (default behaviour — pass --exclude-repo-clone to skip):
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip
Skip repository contents:
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--exclude-repo-clone
Encrypted backup (AES-256):
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--encrypt
When --encrypt is set, the CLI prompts for a password unless GITLAB_DR_PASSWORD is already set.
Directory backup
Use --backup-dir instead of --backup-file to write the backup as plain files in a directory rather than a zip archive. Encryption is not available in this mode.
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-dir /path/to/backup-dir \
--token "$GITLAB_DR_TOKEN"
This produces:
backup-dir/
backup.json ← group/project metadata, variables, merge requests
backup.log ← full run transcript
repos/
mygroup/
myproject.bundle ← git bundle (full history preserved)
--repos-as-files (for environment transformation workflows)
Pass --repos-as-files (with --backup-dir) to store each repository as plain checked-out files rather than a git bundle:
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-dir /path/to/backup-dir \
--repos-as-files
This produces:
backup-dir/
backup.json
backup.log
repos/
mygroup/
myproject/ ← plain working tree files, no .git directory
README.md
values.yaml
...
⚠️ WARNING: Git history is not preserved when using
--repos-as-files. On restore, each project will be created with a single initial commit containing the files at the time of backup. All prior commit history from the original repository will be lost. This warning is also printed to the terminal and written to the run log.
This mode is intended for workflows where you need to transform file contents between environments before restoring to a different GitLab instance — for example, using xsyncfar to apply find-and-replace rules across all IaC configuration files when migrating from production to a lab environment. Because every file in the backup directory is plain text, tools like xsyncfar can process both the metadata (backup.json) and the repository files in a single pass.
Typical workflow:
gitlab_dr --backup --backup-dir ./prod-backup --repos-as-files (from prod GitLab)
↓
xsyncfar (transforms prod strings → lab strings across all files)
↓
gitlab_dr --restore --backup-dir ./lab-backup --repos-as-files (to lab GitLab)
Restore from zip archive
gitlab_dr \
--restore \
--gitlab-url https://gitlab.target.example.com \
--backup-file /path/to/backup.zip \
--token "$GITLAB_DR_TOKEN"
Restore from directory
gitlab_dr \
--restore \
--gitlab-url https://gitlab.lab.example.com \
--backup-dir /path/to/backup-dir \
--token "$GITLAB_DR_TOKEN"
When restoring a --repos-as-files backup, each project's files are committed as a single initial commit and pushed:
gitlab_dr \
--restore \
--gitlab-url https://gitlab.lab.example.com \
--backup-dir /path/to/lab-backup \
--repos-as-files \
--token "$GITLAB_DR_TOKEN"
mTLS support
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--client-cert /path/to/client.crt.pem \
--client-key /path/to/client.key.pem
When repo cloning is enabled (the default), the client certificate and key are passed to git via GIT_SSL_CERT and GIT_SSL_KEY environment variables automatically.
To trust a custom CA:
gitlab_dr \
--backup \
--gitlab-url https://gitlab.example.com \
--backup-file /path/to/backup.zip \
--ca-cert /path/to/ca-bundle.pem
Backup scope
The backup captures recursively discovered groups/subgroups and contained projects, including:
- Group and project metadata
- Group and project CI/CD variables (including masked values — store the archive securely)
- Project merge requests
- Group member listings
- Git repository contents (all branches, tags, and refs as git bundles, or as plain files with
--repos-as-files) — pass--exclude-repo-cloneto skip repos entirely
CI/CD variable access
An admin PAT returns unmasked CI/CD variable values. If a project returns 403 for variables (common on archived projects or projects where the creator account has been removed), the tool automatically retries using Sudo impersonation — first as the project creator_id, then as each current owner/maintainer. If all candidates are exhausted the project is skipped with a warning rather than aborting the run.
⚠️ The backup archive will contain plaintext secrets. Use
--encrypt(zip mode) and protect the output appropriately.
Run log
After every backup a .log file is written alongside the archive (e.g. backup.zip → backup.log) containing the full run transcript including all warnings. The terminal summary lists only warnings; the log file contains everything.
Restore behaviour
Restore recreates missing groups/projects and reapplies variables and merge requests where possible. When --include-repos is used on restore, each project's git history is pushed to the target instance via git push --mirror. Failures on individual repositories are reported as warnings and do not abort the rest of the restore.
Empty repositories (no commits) are silently skipped during bundle creation.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gitlab_dr-0.3.1.tar.gz.
File metadata
- Download URL: gitlab_dr-0.3.1.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
318619432b8136511be9fc4543eb47198bab42c98ae7ebcf097905c515315ed5
|
|
| MD5 |
0e2a05af4f53e512015b54f29b47a12c
|
|
| BLAKE2b-256 |
54020a12f08b79dc74030a660efac4653ee2b5c0f9a1cc351c665d17b7ad97e8
|
Provenance
The following attestation bundles were made for gitlab_dr-0.3.1.tar.gz:
Publisher:
publish.yml on tkdpython/gitlab-dr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gitlab_dr-0.3.1.tar.gz -
Subject digest:
318619432b8136511be9fc4543eb47198bab42c98ae7ebcf097905c515315ed5 - Sigstore transparency entry: 1347952931
- Sigstore integration time:
-
Permalink:
tkdpython/gitlab-dr@cfedaa074988b42f61c93d483769c65bb0f3ea37 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cfedaa074988b42f61c93d483769c65bb0f3ea37 -
Trigger Event:
release
-
Statement type:
File details
Details for the file gitlab_dr-0.3.1-py3-none-any.whl.
File metadata
- Download URL: gitlab_dr-0.3.1-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73d82a279bfbd4e41e6f9f6eb8b54cd35b672cea5d7b5c35681ebf2b71ff5f27
|
|
| MD5 |
ae0c678a5d16a23b8b004aa2b6f5929d
|
|
| BLAKE2b-256 |
46d3edf369d198d994f245ec0a82b39b360492cd67b4061816236b8052b2e310
|
Provenance
The following attestation bundles were made for gitlab_dr-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on tkdpython/gitlab-dr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gitlab_dr-0.3.1-py3-none-any.whl -
Subject digest:
73d82a279bfbd4e41e6f9f6eb8b54cd35b672cea5d7b5c35681ebf2b71ff5f27 - Sigstore transparency entry: 1347952935
- Sigstore integration time:
-
Permalink:
tkdpython/gitlab-dr@cfedaa074988b42f61c93d483769c65bb0f3ea37 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cfedaa074988b42f61c93d483769c65bb0f3ea37 -
Trigger Event:
release
-
Statement type: