IaC/CI CD Tool

GitLab Source Backup & Restore with rclone + Google Drive

Somaz 2026. 3. 26. 00:00
728x90
반응형

Overview

GitLab 소스를 Google Drive 공유 드라이브에 자동 백업하고, 필요 시 리스토어하는 방법을 정리한다.

 

`git clone --mirror` 를 사용하여 모든 브랜치, 태그, 커밋 히스토리를 포함한 완전한 백업을 생성하고, `rclone` 을 통해 Google Drive에 업로드한다. 리스토어 시에는 `git push --mirror` 로 원본과 동일한 상태를 복원할 수 있다.

[Backup Flow]
GitLab CI Pipeline (push / manual trigger)
  → git clone --mirror (all branches + tags + history)
  → tar compress
  → rclone copy → Google Drive (Shared Drive)

[Restore Flow]
Google Drive (Shared Drive)
  → rclone copy → local
  → tar extract
  → git push --mirror → GitLab repo

 

 

 

 

 

 


 

 

Prerequisites

 

 

1. rclone config

rclone config
# n (New remote)
# Name: Gitlab Backup
# Storage: drive (Google Drive)
# scope: drive (Full access)
# Configure this as a Shared Drive? → y → Select shared drive

 

 

설정 완료 후 확인

rclone config show
rclone lsd "Gitlab Backup:"

rclone config 파일 1개에 remote를 여러 개 등록할 수 있다. remote 1개에 공유 드라이브(team drive) 1개가 연결되며, 같은 Google 계정이면 token을 공유할 수 있다.

 
 
 
# rclone.conf example

[Design Docs]
type = drive
team_drive = aaaa1111bbbb
scope = drive
token = {"access_token":"...","refresh_token":"..."}

[Gitlab Backup]
type = drive
team_drive = cccc2222dddd
scope = drive
token = {"access_token":"...","refresh_token":"..."}

token의 `expires_in: 3599` (약 1시간)은 access_token 유효시간이다. rclone이 refresh_token으로 자동 갱신하므로 신경 쓸 필요 없다.

 

 

 

2. Push rclone image to Harbor

# Copy multi-arch image to local
skopeo copy --all docker://rclone/rclone:latest dir:///tmp/rclone-latest

# Push to Harbor
skopeo copy --all --dest-tls-verify=false \
  dir:///tmp/rclone-latest docker://harbor.example.com/library/rclone/rclone:latest

 

 

3. GitLab CI/CD Variables

Variable Type Description
GITLAB_BACKUP_RCLONE_CONFIG File rclone config file

rclone config show 값을 그대로 넣어주면 된다.

 

 

 

 

rclone config file content

[Gitlab Backup]
type = drive
scope = drive
team_drive = <SHARED_DRIVE_ID>
token = {"access_token":"...","refresh_token":"...","expiry":"..."}

 

 

 

 


 

 

 

Backup (.gitlab-ci.yml)

stages:
  - source-backup

variables:
  CONFIG: $GITLAB_BACKUP_RCLONE_CONFIG

source-backup:
  stage: source-backup
  image: rclone/rclone:latest
  interruptible: true
  retry:
    max: 1
    when:
      - runner_system_failure
      - unknown_failure
      - data_integrity_failure
    exit_codes:
      - 137
  variables:
    GIT_STRATEGY: none
  before_script:
    - apk add --no-cache git
  script:
    - git clone --mirror http://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git repo.git
    - tar czf /tmp/${CI_PROJECT_NAME}_${CI_COMMIT_SHORT_SHA}_$(date +%Y%m%d_%H%M%S).tar.gz repo.git
    - rclone copy /tmp/*.tar.gz "Gitlab Backup:${CI_PROJECT_NAME}/" --progress --config $CONFIG
    # Clean up old backups (keep latest 10)
    - rclone lsf "Gitlab Backup:${CI_PROJECT_NAME}/" --config $CONFIG | sort | head -n -10 | while read f; do
        rclone deletefile "Gitlab Backup:${CI_PROJECT_NAME}/$f" --config $CONFIG;
      done
  tags:
    - build-image
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - if: '$CI_PIPELINE_SOURCE == "push"'

 

Key Points

  • `GIT_STRATEGY: none` — CI 기본 clone(shallow)을 비활성화한다. CI 기본 clone은 `--depth 1` 로 현재 브랜치의 최신 커밋만 가져오기 때문에 전체 백업에 적합하지 않다.
  • `git clone --mirror` — 모든 브랜치 + 태그 + 전체 커밋 히스토리를 클론한다. push 안 된 로컬 브랜치는 포함되지 않는다.
  • 최근 10개 백업만 유지하고 나머지는 자동 삭제한다.
  • 백업할 리포마다 동일한 `.gitlab-ci.yml` 을 넣으면 `${CI_PROJECT_NAME}` 등 변수가 자동으로 해당 리포에 맞게 적용된다.
  • `rclone/rclone:latest` 이미지는 Alpine 기반으로 git이 포함되어 있지 않아 `before_script` 에서 `apk add --no-cache git` 으로 설치한다.

 

 

Backup file structure on Google Drive

Gitlab Backup (Shared Drive)
├── my-project/
│   ├── my-project_abc1234_20260320_120000.tar.gz
│   ├── my-project_def5678_20260321_150000.tar.gz
│   └── my-project_efc199d_20260323_072951.tar.gz
├── another-project/
│   └── another-project_ghi9012_20260323_080000.tar.gz
└── ...

 

 

 

 

 


 

 

 

 

Restore (gitlab-restore.sh)

리스토어 스크립트는 Google Drive에서 백업을 다운로드하고 압축 해제 후 로컬 또는 GitLab 리포로 복원한다. 원본 리포와의 비교 기능도 포함되어 있다.

 

Script

 

 

Usage

 

Restore latest backup to local

./gitlab-restore.sh my-project

 

Restore latest backup to GitLab repo

./gitlab-restore.sh my-project git@gitlab.example.com:group/restore-repo.git

GitLab에 빈 리포를 먼저 생성해야 한다. Protected Branch가 설정되어 있으면 Settings → Repository → Protected Branches에서 force push를 허용해야 한다.

 

Select specific backup

./gitlab-restore.sh -s my-project
 
 
[1/6] Listing backups
---
  1) my-project_abc1234_20260320_120000.tar.gz
  2) my-project_def5678_20260321_150000.tar.gz
  3) my-project_efc199d_20260323_072951.tar.gz
---
Select backup number to restore (1-3):

 

 

Restore and compare with original repo

./gitlab-restore.sh -d ~/gitlab-project/my-project my-project
 
 
[6/6] Comparing with: ~/gitlab-project/my-project
---
  Commits:  IDENTICAL
  Branches: IDENTICAL
  Tags:     IDENTICAL
---

 

 

Combined options

# Select + compare
./gitlab-restore.sh -s -d ~/gitlab-project/my-project my-project

# Select + restore to GitLab + compare
./gitlab-restore.sh -s -d ~/gitlab-project/my-project my-project git@gitlab.example.com:group/restore-repo.git

# Custom remote + config + work directory
./gitlab-restore.sh -r "Gitlab Backup" -c ~/.config/rclone/rclone.conf -w /tmp/restore my-project

 

 

Options

Option Description Default
-s, --select Select backup from list Latest backup
-d, --diff <path> Compare with local repo after restore Disabled
-r, --remote <name> rclone remote name Gitlab Backup
-w, --work-dir <path> Working directory /tmp/gitlab-restore
-c, --config <path> rclone config file path rclone default
-h, --help Show help -

 

 

환경변수로도 설정 가능하다.

REMOTE="Gitlab Backup" WORK_DIR=/tmp/restore ./gitlab-restore.sh my-project

 

 

Execution Flow

[1/6] Listing backups        ← Fetch backup list from Google Drive
[2/6] Downloading backup     ← Download selected backup file
[3/6] Extracting archive     ← Extract tar.gz + display branches/tags
[4/6] Restoring              ← Local clone or git push --mirror to GitLab
[5/6] Restore complete
[6/6] Comparing              ← (Optional) Compare with original repo

 

 

Notes

  • `refs/pipelines/*` 관련 에러는 GitLab 내부 파이프라인 메타데이터로 push가 거부되는 것이 정상이며 소스 복원에 영향 없다. 스크립트에서 자동으로 감지하고 무시한다.
  • `--mirror` 는 서버에 push 된 내용만 백업한다. push 안 된 로컬 브랜치는 포함되지 않으므로 비교 시 차이가 날 수 있다.
  • bare repo(`repo.git`)는 소스 파일이 직접 보이지 않는다. 로컬에서 작업하려면 `git clone repo.git` 으로 워킹 디렉토리를 생성해야 한다.

 

 

 


 

 

 

마무리

이 구성으로 GitLab 소스의 자동 백업과 리스토어가 가능해진다. 백업은 CI 파이프라인에서 push마다 자동으로 실행되고, 리스토어는 스크립트 하나로 Google Drive에서 다운로드 → 복원 → 검증까지 처리할 수 있다.

 

백업할 리포가 여러 개라면 각 리포에 동일한 `.gitlab-ci.yml` 을 넣으면 된다. `${CI_PROJECT_NAME}` 등 predefined 변수가 자동으로 리포별 경로를 생성하기 때문에 별도 수정 없이 동작한다.

 

rclone의 Google Drive 연동은 한번 설정하면 token이 자동 갱신되므로 유지보수가 거의 필요 없다. 공유 드라이브를 사용하면 팀 단위로 백업을 관리할 수 있고, 필요 시 `rclone remote` 를 추가하여 다른 공유 드라이브로 확장할 수 있다.

 

 

 

 

 

 


Reference

 

 

 

 

 

Somaz | DevOps Engineer | Kubernetes & Cloud Infrastructure Specialist

728x90
반응형