GitLab 서버 이사
정석은 이렇다
NAS의 한계를 벗어나 전용 서버로. 백업부터 복원, 도메인 전략까지 — 아무도 눈치채지 못하게 끝내는 마이그레이션의 정석.
NAS에서 GitLab을 돌리면 안 되는 이유
시놀로지 NAS에서 Docker로 GitLab을 돌리는 것은 한국 중소/스타트업에서 흔한 패턴이다. 초기에는 잘 돌아간다. NAS는 이미 사무실에 있고, Docker 패키지 하나 설치하면 끝이니까. 하지만 팀이 커지고 프로젝트가 늘면 한계에 부딪힌다. 그리고 그 한계는 대부분 동시에 온다.
메모리 벽
GitLab은 유휴 상태에서도 약 2.2GB RAM을 점유한다. NAS 기본 2GB로는 부팅조차 위태롭다. GitLab 공식 최소 권장은 8 vCPU, 16GB RAM(1,000 유저 기준). DS220+의 2코어/2GB는 사실상 데모 수준이다.
DSM 7.0 지원 중단
시놀로지가 DSM 7.0에서 GitLab 패키지를 3rd-party로 분류하고 지원을 중단했다. Docker로 직접 설치해야 하므로 유지보수 난이도가 급상승한다. 업데이트도, 트러블슈팅도 전부 수동이다.
성능 저하
데이터가 쌓이면 CI/CD 파이프라인이 느려지고, 접속이 끊기고, 502 에러가 빈번해진다. NAS의 ARM 또는 저전력 x86 CPU로는 GitLab의 Ruby on Rails + PostgreSQL + Redis 스택을 감당하기 어렵다.
NAS는 파일 서버다. Git 서버가 아니다.
전용 서버(4코어+ x86, 16GB+ RAM)로의 이전은 올바른 판단이다. 문제는 "어떻게" 옮기느냐다. 마이그레이션 방법을 잘못 고르면 데이터가 날아가고, 도메인 전략을 잘못 잡으면 개발자 전원이 remote를 다시 설정해야 한다. 이 글에서 정석을 다룬다.
마이그레이션 3가지 방법
gitlab-backup (공식 권장)
GitLab 공식 문서가 권장하는 방법이다. gitlab-backup create 명령 하나로 리포지토리, 이슈, 머지 리퀘스트, CI/CD 파이프라인 설정, 위키, 스니펫을 포함한 거의 모든 데이터를 tar 파일로 묶는다. 단, gitlab.rb(설정 파일)와 gitlab-secrets.json(암호화 키)은 별도로 복사해야 한다. 이 두 파일이 없으면 2FA 토큰, CI/CD 변수 등 암호화된 데이터를 복호화할 수 없다.
Docker 볼륨 직접 이전
Docker Compose로 GitLab을 운영 중이라면 볼륨 자체를 tar로 묶어 옮기는 방법도 있다. /srv/gitlab/ 디렉토리에 config, data, logs가 모두 들어 있으므로, 이 디렉토리만 아카이브하면 된다. GitLab 내부 백업 메커니즘을 거치지 않으므로 구조가 단순하다.
docker compose down으로 컨테이너를 중지한 뒤 아카이브한다.
프로젝트 Export/Import
GitLab 웹 UI에서 프로젝트별로 Export 파일을 생성하고, 신규 서버에서 Import하는 방법이다. 소수의 프로젝트만 선택적으로 옮길 때 유용하지만, 프로젝트가 수십 개를 넘으면 수작업이 비현실적이다. 그룹 단위 Export/Import는 Premium 라이선스 이상에서만 지원한다.
세 가지 방법의 특성을 비교하면 다음과 같다. 대부분의 경우 gitlab-backup이 정답이다.
도메인은 어떻게 할 것인가
마이그레이션에서 가장 많은 논쟁이 벌어지는 지점이다. 서버를 옮기면 IP가 바뀐다. 그런데 개발자들의 git remote에는 도메인(또는 IP)이 박혀 있다. CI/CD webhook, Container Registry, Slack 알림 — 전부 URL을 물고 있다. 도메인을 어떻게 처리하느냐에 따라 마이그레이션의 체감 난이도가 결정된다.
DNS만 바꾸기 (권장)
가장 단순하고 안전한 방법이다. git.prost.team 도메인은 그대로 유지하되, DNS A 레코드의 IP만 신규 서버로 변경한다. 개발자는 아무것도 할 필요가 없다. git remote, CI/CD, webhook, Container Registry URL이 전부 그대로 작동한다.
장점
개발자 작업 0건. 모든 remote, CI/CD, webhook, Container Registry가 그대로 작동한다. 롤백도 간단하다 — DNS를 원래 IP로 되돌리면 끝이다. 마이그레이션 당일 30분이면 전파가 완료된다.
단점
prost.team 도메인의 DNS 관리 권한이 필요하다. 도메인 자체를 변경하려는 목적(리브랜딩 등)이 있다면 이 방법으로는 해결되지 않는다. 또한 IP 직접 접속으로 운영 중인 경우 별도 처리가 필요하다.
도메인 변경 (병행 운영)
도메인 변경이 불가피하다면, 최소 2주간의 병행 운영 기간이 필요하다. 개발자들이 git remote를 변경하고, CI/CD 파이프라인을 수정하고, webhook URL을 업데이트해야 한다. 한 명이라도 놓치면 push가 실패한다. 병행 기간 없이 하루 아침에 바꾸는 것은 사고를 부르는 지름길이다.
-
T-4주
마이그레이션 계획 공지. 신규 도메인 안내, 변경 일정 공유.
-
T-2주
개발자에게 remote 변경 스크립트 배포. 신 서버 테스트 환경 오픈.
-
T-1주
양쪽 도메인 모두 접근 가능 상태 확인. 병행 운영 시작.
-
T-3일
최종 리마인더. remote 미변경 개발자 개별 연락.
-
T-day
금요일 저녁 마이그레이션 실행. 주말 동안 안정화 기간 확보.
-
T+1일
관리자 팀 검증. push/pull/CI 파이프라인 정상 작동 확인.
-
T+1주
구 도메인 301 리디렉트 설정. 웹 접근은 자동 전환.
-
T+2주
안정화 확인 후 구 서버 read-only 유지. 즉시 폐기하지 않는다.
리버스 프록시
구 NAS에 nginx를 설치해 구 도메인으로 들어오는 요청을 신 도메인으로 리디렉트하는 방법이다. 웹 UI 접근은 해결된다. 하지만 SSH 기반 git 명령은 HTTP 리디렉트를 따르지 않는다. git clone, push, pull에서 SSH URL을 쓰는 개발자는 여전히 수동으로 remote를 변경해야 한다. 근본적 해결이 아니라 임시 조치에 가깝다.
가장 좋은 마이그레이션은 아무도 모르게 끝나는 마이그레이션이다.
결론은 명확하다. 도메인을 바꿀 필요가 없다면 Option A(DNS만 변경)가 압도적으로 유리하다. 개발자가 해야 할 일이 문자 그대로 0건이다. 도메인 변경이 불가피하다면 Option B의 타임라인을 따르되, 구 도메인에서 신 도메인으로의 301 리디렉트와 병행 운영 기간을 반드시 확보한다.
4주 마이그레이션 플랜
마이그레이션 방법(gitlab-backup)과 도메인 전략(DNS A 레코드 변경)을 확정했다고 가정하고, 4주 플랜을 정리한다. 실행은 반드시 금요일 저녁에 시작하고, 토요일에 검증하고, 월요일에 지원하는 패턴을 따른다.
계획 수립 + 공지
마이그레이션 방법 결정, 도메인 전략 확정. 전사 공지: "아직 아무것도 바뀌지 않습니다." 연동 서비스 인벤토리 작성(Slack webhook, Jira 연동, CI Runner, Container Registry, Pages 등).
기술 준비
신 서버 세팅(OS, Docker, 동일 GitLab 버전 설치). 테스트 백업/복원 1회 실행. 연동 서비스별 마이그레이션 체크리스트 확정. DNS TTL을 300초로 변경.
리허설
스테이징 환경에서 전체 과정 시뮬레이션. 백업 생성 소요 시간, 전송 시간, 복원 시간 측정. 개발자 자발적 테스트 참여 — 신 서버에서 clone, push, CI 실행 확인.
-
금 18:00
유지보수 모드 진입. GitLab을 maintenance mode로 전환. 전사 Slack 알림.
-
금 18:30
최종 백업 생성.
gitlab-backup create+ 설정 파일 복사. -
금 19:00
백업 파일 신 서버 전송. rsync로 진행 상태 모니터링.
-
금 20:00
신 서버에서 복원 실행.
gitlab-backup restore+ check + doctor:secrets 검증. -
금 21:00
DNS A 레코드 변경. TTL 300초 기준, 5~30분 내 전파 완료.
-
금 22:00
관리자 접속 확인. 웹 UI, git clone, push 테스트. 문제 없으면 퇴근.
-
토 10:00
전체 검증. CI/CD 파이프라인 실행, webhook 동작 확인, Container Registry 접근 테스트.
-
월 09:00
개발자 출근 후 지원 대기. 문제 발생 시 즉시 대응. 구 서버는 1주간 read-only 유지.
- 구/신 서버의 GitLab 버전 일치 확인. 마이너 버전까지 동일해야 한다.
- gitlab-secrets.json 복사 여부 확인. 빠뜨리면 2FA, CI 변수, Runner 토큰이 전부 무효화된다.
- DNS TTL 변경은 최소 48시간 전에 실행. 기존 TTL이 높으면(24시간 등) 전파에 시간이 걸린다.
- 복원 후 gitlab:check와 gitlab:doctor:secrets 두 검증 명령을 반드시 실행한다.
- 구 서버를 최소 1주간 유지한다. 즉시 폐기하면 롤백이 불가능하다.
- SSL 인증서(Let's Encrypt 등)를 신 서버에서 재발급해야 한다. 인증서는 이전되지 않는다.
가장 좋은 마이그레이션은
아무도 모르게 끝나는 마이그레이션이다
DNS A 레코드 하나면 개발자는 아무것도 할 필요가 없다. 인프라의 존재 이유는 개발자가 코드에만 집중할 수 있게 하는 것이다.