# gitbackup - Backup your GitHub, GitLab, Bitbucket, and Forgejo repositories Code Quality [![Go Report Card](https://goreportcard.com/badge/github.com/amitsaha/gitbackup)](https://goreportcard.com/report/github.com/amitsaha/gitbackup) [![.github/workflows/ci.yml](https://github.com/amitsaha/gitbackup/actions/workflows/ci.yml/badge.svg)](https://github.com/amitsaha/gitbackup/actions/workflows/ci.yml) # Commerical Support As of February 2026, [Common Loop Works Pty Ltd](https://abr.business.gov.au/ABN/View?id=49688912389), a software development, machine learning and cloud advisory company, founded by [Amit Saha](https://au.linkedin.com/in/echorand) supports commercial development and support of `gitbackup`. Contact us for any custom on-prem or cloud deployment, new feature requests or expedite any bug fixes. # User guide - [gitbackup - Backup your GitHub, GitLab, Bitbucket, and Forgejo repositories](#gitbackup---backup-your-github-gitlab-and-bitbucket-repositories) - [Introduction](#introduction) - [Installing `gitbackup`](#installing-gitbackup) - [Docker image](#docker-image) - [Using `gitbackup`](#using-gitbackup) - [GitHub Specific oAuth App Flow](#github-specific-oauth-app-flow) - [OAuth Scopes/Permissions required](#oauth-scopespermissions-required) - [Bitbucket](#bitbucket) - [GitHub](#github) - [GitLab](#gitlab) - [Forgejo](#forgejo) - [Security and credentials](#security-and-credentials) - [Configuration file](#configuration-file) - [Examples](#examples) - [Backing up your GitHub repositories](#backing-up-your-github-repositories) - [Backing up your GitLab repositories](#backing-up-your-gitlab-repositories) - [GitHub Enterprise or custom GitLab installation](#github-enterprise-or-custom-gitlab-installation) - [Backing up your Bitbucket repositories](#backing-up-your-bitbucket-repositories) - [Backing up your Forgejo repositories](#backing-up-your-forgejo-repositories) - [Specifying a backup location](#specifying-a-backup-location) - [Cloning bare repositories](#cloning-bare-repositories) - [GitHub Migrations](#github-migrations) - [Building](#building) ## Introduction ``gitbackup`` is a tool to backup your git repositories from GitHub (including GitHub enterprise), GitLab (including custom GitLab installations), Bitbucket, or Forgejo. ``gitbackup`` currently has two operation modes: - The first and original operating mode is to create clones of only your git repository. This is supported for GitHub, Gitlab, Bitbucket, and Forgejo. - The second operating mode is only available for GitHub where you can create a user migration (including orgs) which you get back as a .tar.gz file containing all the artefacts that GitHub supports via their Migration API. If you are following along my [Linux Journal article](https://www.linuxjournal.com/content/back-github-and-gitlab-repositories-using-golang) (published in 2017), please obtain the version of the source tagged with [lj-0.1](https://github.com/amitsaha/gitbackup/releases/tag/lj-0.1). ## Installing `gitbackup` Binary releases are available from the [Releases](https://github.com/amitsaha/gitbackup/releases/) page. Please download the binary corresponding to your OS and architecture and copy the binary somewhere in your ``$PATH``. It is recommended to rename the binary to `gitbackup` or `gitbackup.exe` (on Windows). If you are on MacOS, a community member has created a [Homebrew formula](https://formulae.brew.sh/formula/gitbackup). ### Docker image Docker images are published to [GitHub Container Registry](https://github.com/amitsaha/gitbackup/pkgs/container/gitbackup) on every release: ```bash docker pull ghcr.io/amitsaha/gitbackup: ``` Replace `` with the desired release tag (e.g. `0.9.1`). The container runs as a non-root user (`nonroot`, UID `65532`). HTTPS cloning (`-use-https-clone`) is recommended inside containers because it requires no SSH key management. #### Linux On Linux, Docker runs natively so container UIDs map directly to host UIDs. Before mounting a backup directory, grant write access to UID `65532`: ```bash mkdir -p /data/gitbackup chown 65532:65532 /data/gitbackup ``` Run with HTTPS cloning (recommended): ```bash docker run --rm \ -e GITHUB_TOKEN= \ -v /data/gitbackup:/backup \ ghcr.io/amitsaha/gitbackup: \ -service github -backupdir /backup -use-https-clone ``` If you need SSH cloning, make a copy of your private key readable by UID `65532` and mount it: ```bash cp $HOME/.ssh/id_rsa /tmp/gitbackup_id_rsa chown 65532 /tmp/gitbackup_id_rsa chmod 600 /tmp/gitbackup_id_rsa docker run --rm \ -e GITHUB_TOKEN= \ -v /data/gitbackup:/backup \ -v /tmp/gitbackup_id_rsa:/home/nonroot/.ssh/id_rsa:ro \ -v $HOME/.ssh/known_hosts:/home/nonroot/.ssh/known_hosts:ro \ ghcr.io/amitsaha/gitbackup: \ -service github -backupdir /backup ``` #### macOS Docker Desktop for Mac runs containers inside a Linux VM and translates volume mounts through its filesystem layer (VirtioFS). Because of this translation, the container UID (`65532`) is mapped automatically — you do **not** need to `chown` the host directory. Paths use the same Unix syntax as Linux. ```bash mkdir -p $HOME/gitbackup docker run --rm \ -e GITHUB_TOKEN= \ -v $HOME/gitbackup:/backup \ ghcr.io/amitsaha/gitbackup: \ -service github -backupdir /backup -use-https-clone ``` SSH cloning on macOS requires the same key-ownership step as Linux. Although VirtioFS handles write permissions for the backup directory automatically, `git` performs a strict ownership check on the SSH private key inside the container — the key file must be owned by the user running inside the container (UID `65532`). Host UIDs on macOS are unrelated to container UIDs, so the ownership must be set explicitly on a copy of the key: ```bash cp $HOME/.ssh/id_rsa /tmp/gitbackup_id_rsa chown 65532 /tmp/gitbackup_id_rsa chmod 600 /tmp/gitbackup_id_rsa docker run --rm \ -e GITHUB_TOKEN= \ -v $HOME/gitbackup:/backup \ -v /tmp/gitbackup_id_rsa:/home/nonroot/.ssh/id_rsa:ro \ -v $HOME/.ssh/known_hosts:/home/nonroot/.ssh/known_hosts:ro \ ghcr.io/amitsaha/gitbackup: \ -service github -backupdir /backup ``` #### Windows Docker Desktop for Windows (WSL2 backend recommended) translates volume mounts through the WSL2 VM, so no `chown` is needed on the host directory. Use PowerShell syntax for environment variables and paths: ```powershell # PowerShell New-Item -ItemType Directory -Force "$env:USERPROFILE\gitbackup" docker run --rm ` -e GITHUB_TOKEN=$env:GITHUB_TOKEN ` -v "${env:USERPROFILE}\gitbackup:/backup" ` ghcr.io/amitsaha/gitbackup: ` -service github -backupdir /backup -use-https-clone ``` If you prefer Command Prompt: ```cmd mkdir %USERPROFILE%\gitbackup docker run --rm ^ -e GITHUB_TOKEN=%GITHUB_TOKEN% ^ -v "%USERPROFILE%\gitbackup:/backup" ^ ghcr.io/amitsaha/gitbackup: ^ -service github -backupdir /backup -use-https-clone ``` SSH cloning on Windows requires your SSH key to be accessible from WSL2 or Docker Desktop. The recommended approach is to store your key under WSL2 and mount it using a WSL path, or use HTTPS cloning to avoid SSH key management altogether. ## Using `gitbackup` ``gitbackup`` requires a [GitHub API access token](https://github.com/blog/1509-personal-api-tokens) for backing up GitHub repositories, a [GitLab personal access token](https://gitlab.com/-/user_settings/personal_access_tokens) for GitLab repositories, an Atlassian account email plus an [API token](https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/) (or [app password](https://bitbucket.org/account/settings/app-passwords/)) for Bitbucket repositories, or a [Forgejo access token][https://docs.codeberg.org/advanced/access-token/] for Forgejo. You can supply the tokens to ``gitbackup`` using ``GITHUB_TOKEN``, ``GITLAB_TOKEN``, or ``FORGEJO_TOKEN`` environment variables respectively, and the Bitbucket credentials with ``BITBUCKET_EMAIL`` (or ``BITBUCKET_USERNAME`` for legacy app-password setups) and either ``BITBUCKET_TOKEN`` or ``BITBUCKET_PASSWORD``. Bitbucket additionally requires ``BITBUCKET_WORKSPACES`` (comma-separated workspace slugs) because Atlassian removed the cross-workspace listing APIs on April 14, 2026. ### GitHub Specific oAuth App Flow Starting with the 0.6 release, if you run `gitbackup` without specifying `GITHUB_TOKEN`, it will prompt you to complete a oAuth flow to grant the necessary access: ``` $ ./gitbackup -service github -github.repoType starred Copy code: then open: https://github.com/login/device ``` Once your authorize the app, `gitbackup` will retrieve the token, and also store it in your operating system's keychain/keyring (using the [99designs/keyring](https://github.com/99designs/keyring) package - thanks!). Next time you run it, it will ask you for the keyring password and retrieve the token automatically. ### OAuth Scopes/Permissions required #### Bitbucket **API tokens** (recommended): - `read:user:bitbucket` - `read:workspace:bitbucket` - `read:repository:bitbucket` **App passwords** (deprecated, disabled after June 9, 2026): - `Account:Read` - `Repositories:Read` **Note:** Bitbucket has deprecated app passwords. Use [API tokens](https://support.atlassian.com/bitbucket-cloud/docs/api-tokens/) instead by setting the ``BITBUCKET_TOKEN`` environment variable. #### GitHub - `repo`: Reading repositories, including private repositories - `user` and `admin:org`: Basically, this gives `gitbackup` a lot of permissions than you may be comfortable with. However, these are required for the user migration and org migration operations. #### GitLab - `api`: Grants complete read/write access to the API, including all groups and projects. For some reason, `read_user` and `read_repository` is not sufficient. #### Forgejo The following permissions are required: - `read:repository` - `read:user` ### Security and credentials When you provide the tokens via environment variables, they remain accessible in your shell history and via the processes' environment for the lifetime of the process. By default, SSH authentication is used to clone your repositories. If `use-https-clone` is specified, private repositories are cloned via `https` basic auth and the token provided will be stored in the repositories' `.git/config`. ### Configuration file **Note:** Migration-related flags (``-github.createUserMigration``, ``-github.listUserMigrations``, etc.) are CLI-only and not supported in the config file. Instead of passing all options as CLI flags, you can use a ``gitbackup.yml`` configuration file. The config file is stored in the OS-specific configuration directory: - **Linux:** ``$XDG_CONFIG_HOME/gitbackup/gitbackup.yml`` or ``~/.config/gitbackup/gitbackup.yml`` - **macOS:** ``~/Library/Application Support/gitbackup/gitbackup.yml`` - **Windows:** ``%AppData%/gitbackup/gitbackup.yml`` To create a default configuration file: ```lang=bash $ gitbackup init ``` To create it at a custom location: ```lang=bash $ gitbackup init --config /path/to/gitbackup.yml ``` This creates a ``gitbackup.yml`` with default values that you can edit: ```yaml service: github githost_url: "" backup_dir: "" ignore_private: false ignore_fork: false use_https_clone: false bare: false github: repo_type: all namespace_whitelist: [] gitlab: project_visibility: internal project_membership_type: all forgejo: repo_type: user ``` To validate your configuration file (checks field values and required environment variables): ```lang=bash $ gitbackup validate ``` To see available options for a subcommand: ```lang=bash $ gitbackup init --help $ gitbackup validate --help ``` The config file is automatically loaded at runtime from the default location. CLI flags override config file values, so you can use the config file for your base settings and override individual options as needed: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -ignore-fork ``` To use a config file at a custom location: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -config /path/to/gitbackup.yml ``` Secrets (tokens, passwords) are not stored in the config file — they are always provided via environment variables. ### Examples Typing ``-help`` will display the command line options that `gitbackup` recognizes: ``` $ gitbackup -help Usage of ./gitbackup: -backupdir string Backup directory -bare Clone bare repositories -forgejo.repoType string Repo types to backup (user, starred) (default "user") -githost.url string DNS of the custom Git host -github.createUserMigration Download user data -github.createUserMigrationRetry Retry creating the GitHub user migration if we get an error (default true) -github.createUserMigrationRetryMax int Number of retries to attempt for creating GitHub user migration (default 5) -github.listUserMigrations List available user migrations -github.namespaceWhitelist string Organizations/Users from where we should clone (separate each value by a comma: 'user1,org2') -github.repoType string Repo types to backup (all, owner, member, starred) (default "all") -github.waitForUserMigration Wait for migration to complete (default true) -gitlab.projectMembershipType string Project type to clone (all, owner, member, starred) (default "all") -gitlab.projectVisibility string Visibility level of Projects to clone (internal, public, private) (default "internal") -ignore-fork Ignore repositories which are forks -ignore-private Ignore private repositories/projects -service string Git Hosted Service Name (github/gitlab/bitbucket/forgejo) -use-https-clone Use HTTPS for cloning instead of SSH ``` #### Backing up your GitHub repositories To backup all your own GitHub repositories to the default backup directory (``$HOME/.gitbackup/``): ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github ``` To backup only the GitHub repositories which you are the "owner" of: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -github.repoType owner ``` To backup only the GitHub repositories which you are the "member" of: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -github.repoType member ``` Separately, to backup GitHub repositories you have starred: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -github.repoType starred ``` Additionally, to backup only the GitHub repositories under 'user1' and 'org3': ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -github.namespaceWhitelist "user1,org3" ``` #### Backing up your GitLab repositories To backup all projects you either own or are a member of which have their [visibility](https://docs.gitlab.com/ce/api/projects.html#project-visibility-level) set to "internal" on ``https://gitlab.com`` to the default backup directory (``$HOME/.gitbackup/``): ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup -service gitlab ``` To backup only the GitLab projects (either you are an owner or member of) which are "public" ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup -service gitlab -gitlab.projectVisibility public ``` To backup only the private repositories (either you are an owner or member of): ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup -service gitlab -gitlab.projectVisibility private ``` To backup public repositories which you are an owner of: ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup \ -service gitlab \ -gitlab.projectVisibility public \ -gitlab.projectMembershipType owner ``` To backup public repositories which you are an member of: ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup \ -service gitlab \ -gitlab.projectVisibility public \ -gitlab.projectMembershipType member ``` To backup GitLub repositories you have starred: ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup -service gitlab \ -gitlab.projectMembershipType starred \ -gitlab.projectVisibility public ``` #### GitHub Enterprise or custom GitLab installation To specify a custom GitHub enterprise or GitLab location, specify the ``service`` as well as the the ``githost.url`` flag, like so ```lang=bash $ GITLAB_TOKEN=secret$token gitbackup -service gitlab -githost.url https://git.yourhost.com ``` #### Backing up your Bitbucket repositories Atlassian removed the cross-workspace listing endpoints on April 14, 2026. There is no supported way to enumerate the workspaces a user belongs to programmatically, so you must list them explicitly via ``BITBUCKET_WORKSPACES``. To backup all your Bitbucket repositories to the default backup directory (``$HOME/.gitbackup/``): Using an API token (recommended): ```lang=bash $ BITBUCKET_EMAIL= BITBUCKET_TOKEN=token BITBUCKET_WORKSPACES=ws1,ws2 gitbackup -service bitbucket ``` Using an app password (deprecated, disabled after June 9, 2026): ```lang=bash $ BITBUCKET_USERNAME=username BITBUCKET_PASSWORD=password BITBUCKET_WORKSPACES=ws1,ws2 gitbackup -service bitbucket ``` #### Backing up your Forgejo repositories The `forgejo` service backs up `codeberg.org` by default. To back up all your Codeberg repositories to the default directory (``$HOME/.gitbackup/``): ```lang=bash $ FORGEJO_TOKEN=access_token gitbackup -service forgejo ``` To back up a different Forgejo instance, specify `githost.url`: ```lang=bash $ FORGEJO_TOKEN=access_token gitbackup -service forgejo -githost.url https://git.yourhost.com ``` To back up starred repositories instead of those you have access to, specify `forgejo.repoType`: ```lang=bash $ FORGEJO_TOKEN=access_token gitbackup -service forgejo -forgejo.repoType starred ``` #### Specifying a backup location To specify a custom backup directory, we can use the ``backupdir`` flag: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -backupdir /data/ ``` This will create a ``github.com`` directory in ``/data`` and backup all your repositories there instead. Similarly, it will create a ``gitlab.com`` directory, if you are backing up repositories from ``gitlab``, a ``bitbucket.com`` directory if you are backing up from Bitbucket, and a ``codeberg.org`` (or your custom host) directory if you are backing up from Forgejo. If you have specified a Git Host URL, it will create a directory structure ``data/host-url/``. #### Cloning bare repositories To clone bare repositories, we can use the ``bare`` flag: ```lang=bash $ GITHUB_TOKEN=secret$token gitbackup -service github -bare ``` This will create a directory structure like ``github.com/org/repo.git`` containing bare repositories. #### GitHub Migrations `gitbackup` starting from the 0.6 release includes support for downloading your user data/organization data as made available via the [Migrations API](https://docs.github.com/en/rest/reference/migrations). As of this release, you can create an user migration (including your owned organizations data) and download the migration artefact using the following command: ``` $ ./gitbackup -service github -github.createUserMigration -ignore-fork -github.repoType owner 2021/05/14 05:05:27 /home/runner/.gitbackup/github.com doesn't exist, creating it 2021/05/14 05:05:35 Creating a user migration for 129 repos 2021/05/14 05:05:46 Waiting for migration state to be exported: 0xc0002a6260 2021/05/14 05:06:48 Waiting for migration state to be exported: 0xc000290070 .. 2021/05/14 05:33:44 Waiting for migration state to be exported: 0xc0001c2020 2021/05/14 05:34:46 Downloading file to: /home/runner/.gitbackup/github.com/user-migration-571089.tar.gz 2021/05/14 05:35:00 Creating a org migration (FedoraScientific) for 19 repos 2021/05/14 05:35:03 Waiting for migration state to be exported: 0xc000144050 .. 2021/05/14 05:39:05 Downloading file to: /home/runner/.gitbackup/github.com/FedoraScientific-migration-571098.tar.gz .. 2021/05/14 05:46:16 Downloading file to: /home/runner/.gitbackup/github.com/practicalgo-migration-571103.tar.gz ``` You can then integrate this with your own scripting to push the data to S3 for example (See an example workflow via scheduled github actions [here](https://github.com/amitsaha/gitbackup/actions/workflows/backup.yml)). ## Building If you have Go 1.25.x installed, you can clone the repository and: ``` $ go build ``` The built binary will be ``gitbackup``.