깃티(gitea)로 사내용 깃헙(github) 구축하기
시작하며
우리팀은 수년 전에 도입한 SVN 기반 형상관리를 고수해왔는데, 1개월 전에 깃티(gitea) 기반의 사내용 깃헙을 구축하여 SVN을 대체하였다. 마이그레이션 과정에서 겪었던 일과 알게된 점 등을 정리하였으니, 비슷한 고민을 가진 사람들에게 참고가 되길 바란다.
깃(git) vs SVN(subversion)
깃과 SVN은 형상관리 툴이다. 쉽게 말하면, 소스코드 버전관리 툴이다. 둘은 상당한 차이가 있는데, SVN은 소스코드 리비전(revision)을 중앙집중화된 서버에 커밋(commit)한다면, 깃은 각 로컬에 각자의 개인화된 커밋 히스토리를 가지고 있고 일정 시점에 푸시(push)를 해서 중앙 서버에 업데이트 하는 점이 다르다. 이 밖에도 브랜치(branch)나 스테이징(staging) 등 기능적으로 많은 차이가 있다.
위와 같은 특징만 봐서는 깃의 장점을 느끼기 힘들다. 우리팀도 SVN가 쓸만했기에 깃의 필요성을 못 느끼고 있었다. 하지만 깃헙을 생각하면 이야기가 달라진다.
깃헙(github)?
깃이 형상관리 툴이라면, 깃헙은 깃 커뮤니티, 특히, 마이크로소프트에서 운영하는 플랫폼을 의미한다. 고유명사이지만 깃헙을 대체할 만한 단어가 떠오르지 않을 만큼 깃 플랫폼의 대명사가 되었다.
깃헙의 주요 기능을 살펴보면,
- 저장소(repository) 내에 소스코드, 소스트리, 히스토리 등을 친숙한 웹 UI로 볼 수 있다.
- readme.md 등 저장소에 대한 설명문을 마크다운(markdown) 기반으로 손쉽게 작성하여 게사할 수 있다.
- 이슈추적(issue tracking) 기능을 통해 저장소에서 발생한 이슈애 대해 소통을 강화하고, 기록 관리도 편해진다.
- 위키(wiki) 기능을 통해 저장소와 관련된 수 많은 정보들을 마크다운 기반으로 작성하여 공유할 수 있다.
이 밖에도 릴리즈(releases) 관리뿐만 아니라, 별점(star), 프로필(profile) 및 활동(activity) 등 다양한 커뮤니티 기능이 제공된다. 현재는 슬랙(slack) 메신저와 카카오톡, 구글 드라이브 등으로 소통을 하고 형상관리는 SVN 으로 별도로 이뤄졌다면, 깃헙 도입 이후에는 소통과 형상관리를 통합하여 할 수 있다는 장점이 있다. 그리고 저장소 대표 페이지에서 위 기능들을 통합 제공하고 있으므로, 저장소에 대한 정보의 소통이 강화된다. 메신저와 시너지도 큰데, 깃헙 이슈 페이지의 링크를 첨부하여 보내는 식이다.
구축형 vs 클라우드
사내용 깃헙을 도입하고자 할 때, 필요한 고민은 사내망에 구축할 지. 클라우드 솔루션을 이용할지 이다. 솔루션에 따라, 서비스 이용방식도 천차만별이나, 필자가 나름대로 정리한 바는 다음과 같다.
- 구축형 솔루션 : 깃랩(gitlab), 곡스(gogs), 깃티(gitea)
- 클라우드 솔루션 : 깃헙(github), 깃랩(gitlab), 빗버킷(bitbucket)
결론적으로 우리는 구축형을 택하게 됐다. 소스코드를 외부 저장소에 두면, 보안이 걱정돼서다. 그리고 클라우드는 사용량이 많아지면 유료 결제를 해야한다. 우린 무료를 선호한다.
깃티
솔루션은 깃티(gitea)를 선택했다. 가장 가벼운 솔루션이고, 고랭(golang)으로 개발되어 퍼포먼스가 뛰어나다. 깃랩은 대중적이지만 메모리를 2기가 이상 먹는다. 곡스는 깃티의 어머니 격의 솔루션인데, 매뉴얼이 불친절하고 도커(docker)로 구성하기가 어려웠다. 고민하는 동안, 구글링을 많이 해봤는데, 레딧(reddit)에서 깃티는 깃헙의 미래라고 이야기하는 글이 있었다. 그걸 보고 마음이 굳어져버렸다.
깃티 설치 및 구동
- 이 매뉴얼은 깃티에서 기본 제공하는 SQLite3 DB기반으로 설치했다.
- 우선, 워크스페이스에 gitea 폴더를 만들고 docker-compose.yml을 작성한다.
version: "2"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:latest
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
docker-compose up -d
로 깃티 서버를 구동한다. 대표적인 명령어는 다음과 같다.
docker-compose up -d // 구동
docker-compose down // 중단
docker-compose ps // 구동 정보 확인
docker-compose logs // 로그 확인
- 참고로 CIFS 등 네트워크 스토리지에 데이터를 두고 싶다면 docker-compose.yml에 아래와 같이 마운트(mount)를 해줘야 한다. 특히, nolock 옵션으로 잠금을 꼭 해제해야 한다.
...
volumes:
cifsgit:
driver: local
driver_opts:
type: cifs
o: vers=1.0,username={유저명},password={패스워드},uid=1000,gid=1000,nolock
device: //{드라이브IP주소}/{해당 폴더 경로}/data
services:
server:
image: gitea/gitea:latest
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- cifsgit:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
...
- http://localhost:3000로 접속하여 루트유저 가입을 하고 간단한 서버 설정을 한다. 기본설정으로 넘어가도 무방하다.
- 새 저장소를 생상하고 웹페이지 안내에 따라 최초 커밋과 푸시를 하면 깃티 이용을 위한 모든 준비는 끝이다.
아파치 웹서버를 이용한 https 설정
- 참고로 우리 팀은 아파치 웹서버를 이용해 https 설정을 했다. 깃 최신 버전에서는 https를 쓰지 않으면, 비밀번호 저장이 안 되는 등 불편하다. 인증서가 없으면, 발급 받아야한다.
- 아파치 웹서버 httpd.conf 설정은 아래와 같다.
<VirtualHost *:443>
ServerName "{깃티 도메인}:443"
ErrorLog "|/usr/bin/rotatelogs /{로그 경로}/gitea_ssl_error_log.%Y%m%d 86400 +540"
CustomLog "|/usr/bin/rotatelogs /{로그 경로/gitea_ssl_access_log.%Y%m%d 86400 +540" combined
JkLogFile "|/usr/bin/rotatelogs /{로그 경로/gitea_ssl_mod_jk.log.%Y%m%d 86400 +540"
SSLEngine on
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
ProxyPreserveHost On
ProxyRequests off
AllowEncodedSlashes NoDecode
ProxyPass / http://{깃티 서버 IP}:3000/ nocanon
ProxyPassReverse / http://{깃티 서버 IP}:3000/
</VirtualHost>
- {깃티 경로}/git/data/gitea/conf/app.ini 내에 서버 설정은 아래와 같다.
...
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = {깃티 도메인}
SSH_DOMAIN = {깃티 도메인}
HTTP_PORT = 3000
ROOT_URL = https://{실제 깃티 접속 URl}
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_CONTENT_PATH = /data/git/lfs
LFS_JWT_SECRET = ...
OFFLINE_MODE = false
PROTOCOL = http
...
SVN 마이그레이션
- 로컬 폴더에
svn checkout
을 통해 헤드 리비전(HEAD revision)을 받아준다. -
저장소 내에 .gitignore를 작성하여 깃에서 생략할 파일 목록을 만들어 준다
- 이 때,
.svn/
를 추가하여 svn 관련 파일을 생략한다. - 개발환경 별 .gitignore 예시 : https://github.com/github/gitignore
- 이 때,
- 깃티에서 새 저장소 버튼 클릭하여 저장소 생성하고 마이그레이션할 로컬 폴더에서 최초 푸시를 한다.
touch README.md
git init
git add .
git commit -m "first commit"
git remote add origin https://{깃티 URL}/{계정명}/{저장소명}.git
git push -u origin master
- 깃티 저장소 페이지의 결과를 확인한다. 불필요한 폴더나 파일이 있다면, .gitignore 에 추가하고 제거한다.
git rm -r {제거할 폴더 경로} // 폴더 제거 또는
git rm {제거할 파일 경로} // 파일 제거
git commit -m '{커멧 메시지}'
git push
한 달 사용후기
매우 만족스럽다. 설치도 간편하고, UI가 깃헙과 비슷하다. 웬만한 기능들은 지원한다. 리소스가 적게 들고 젠킨스(jenkins)와 연동도 잘 된다. 속도도 빠르다. 단점은 레퍼런스가 부족하다. 한글 레퍼런스는 더 부족하다.
부분 한글화를 지원한다.
참고 문헌
- 깃티 매뉴얼 : https://docs.gitea.io/en-us/