Gitolite

주의사항: 이 절의 최신판은 항상 gitolite documentation에서 확인할 수 있다. 저자는 다른 참고 문서 없이 이 절만 읽고서도 Gitolite를 설치할 수 있도록 문서를 작성했다고 말했다. 이 절은 꼭 필요하지만 완벽하지 않고 Gitolite에 대한 방대한 문서를 대체할 수도 없다.

Git은 좀 더 꼼꼼한 접근 제어가 필요한 기업환경에서도 많이 쓰인다. 원래 이 요구 사항 덕분에 Gitolite가 만들어졌다. 그리고 오픈 소스 진영에서도 매우 유용하다는 것이 밝혀졌다. Fedora 프로젝트는 Gitolite를 사용하여 10,000개가 넘는 패키지 관리용 저장소의 권한을 제어한다. Fedora의 Gitolite가 아마도 가장 규모가 클 것이다.

Gitolite는 저장소뿐만 아니라 저장소의 브랜치나 태그에도 권한을 명시할 수 있다. 즉, 어떤 사람들은 refs(브랜치나 태그)에 Push할 수 있고 어떤 사람은 할 수 없게 하는 것이 가능하다.

설치하기

별도 문서를 읽지 않아도 유닉스 계정만 하나 있으면 Gitolite를 쉽게 설치할 수 있다. 이 글은 여러 가지 리눅스들과 솔라리스 10에서 테스트를 마쳤다. git, perl, openssh가 호환되는 ssh 서버가 설치돼 있으면 root 권한도 필요 없다. 앞서 사용했던 gitserver라는 서버와 그 서버에 gitolite 계정을 만들어 사용할 것이다.

Gitolite는 보통의 서버 소프트웨어와는 약간 다르다. ssh를 통해서 접근하지만, 서버의 모든 계정은 근본적으로 "Gitolite 호스트"가 될 수 있다. 그래서 설치하는 일은 소프트웨어 자체를 설치하는 일과 한 계정을 "Gitolite 호스트"로 설정하는 작업으로 나눌 수 있다.

Gitolite를 설치하는 방법은 모두 네 가지이다. Fedora나 Debian을 사용하고 있으면 RPM이나 DEB 패키지를 구해서 설치하거나 수동으로 설치할 수 있다. 이 방법들은 root 권한이 필요하다. 이 두 가지 모두 시스템의 모든 사용자를 각각 "Gitolite 호스트"로 만들 수 있다.

서버의 Root 권한을 얻을 수 없는 사용자는 자신의 계정에 설치할 수 있다. 서버에서 Bash 스크립트를 실행하여 Gitolite를 설치할 수 있다. 심지어 Windows 환경에서 msysgit에 들어 있는 bash에서도 실행된다.

이 글에서는 마지막 방법을 설명할 것이다; 다른 방법은 다른 문서를 참고하도록 한다.

우선 공개키로 서버에 접근할 수 있어야 한다. 그래야 서버로 로그인할 때 암호를 묻지 않는다. ssh-keygen로 만든 키가 이미 있으면 다음처럼 한다. 리눅스에서는 이 방법이 잘 될 테고 다른 OS라면 수동으로 이 작업을 해야 한다:

$ ssh-copy-id -i ~/.ssh/id_rsa gitolite@gitserver

이 명령은 Gitolite 계정의 암호를 물어보고서 이 공개키로 접근할 수 있도록 설정할 것이다. 이것은 설치 스크립트를 실행하는 데 꼭 필요하다. 그러니까 명령어를 실행할 때 암호를 물어보는지 다시 한번 확인해봐야 한다:

$ ssh gitolite@gitserver pwd
/home/gitolite

그리고 프로젝트 사이트에서 Gitolite를 Clone하고 "easy install" 스크립트를 실행한다(세 번째 인자는 gitolite-admin 저장소에서 사용할 사용자 이름이다):

$ git clone git://GitHub.com/sitaramc/gitolite
$ cd gitolite/src
$ ./gl-easy-install -q gitolite gitserver sitaram

이제 다 됐다. Gitolite를 서버에 설치했고 홈 디렉토리에 gitolite-admin라는 저장소를 만들었다. 이 저장소를 수정하고 Push해서 Gitolite 서버를 관리할 수 있다.

마지막 명령에는 중요한 정보가 많이 들어 있다. 이 명령을 처음 실행하면 키쌍이(keypair) 새로 만들어진다. 암호가 필요하면 입력하고 필요 없으면 그냥 엔터를 친다. 왜 키를 하나 더 만드는지, 그것을 어떻게 사용하는지는 Gitolite의 "ssh troubleshooing" 문서를 참고하라(이 문서가 필요할 때가 있다).

서버에는 기본적으로 gitolite-admintesting 저장소가 생성되고 필요하면 이 저장소를 다음과 같이 Clone한다(authorized_keys 파일에 공개키가 등록돼서 SSH 접근이 가능한 계정으로 Gitolite 계정에 접근하는 것):

$ git clone gitolite:gitolite-admin
$ git clone gitolite:testing

다른 계정으로도 이 저장소를 Clone할 수 있다:

$ git clone gitolite@servername:gitolite-admin
$ git clone gitolite@servername:testing

자신에게 맞게 설치하기

대부분의 사람은 기본설정으로 빠르게 설치하는 것으로 충분하지만, 자신에게 맞게 고쳐서 설치할 수 있다. -q 인자를 사용하면 설치 단계마다 상세한 정보를 보여주는 verbose 모드로 설치한다. 이 모드에서는 저장소의 경로 같은 것들을 바꿔서 설치할 수 있고 결국엔 서버가 사용하는 rc 파일이 수정된다. rc 파일은 주석이 정말 잘 달렸기 때문에 필요한 것이 있으면 언제든지 쉽게 수정할 수 있다. 이 파일에서 Gitolite의 고급 기능들을 켜고 끄는 등 다양한 설정을 하는 것이다.

설정 파일과 접근제어 규칙

설치가 완료되면 홈 디렉토리에 있는 gitolite-admin 저장소로 이동해서 저장소의 내용이 어떤 것들인지 한번 살펴보자:

$ cd ~/gitolite-admin/
$ ls
conf/  keydir/
$ find conf keydir -type f
conf/gitolite.conf
keydir/sitaram.pub
$ cat conf/gitolite.conf
#gitolite conf
# please see conf/example.conf for details on syntax and features

repo gitolite-admin
    RW+                 = sitaram

repo testing
    RW+                 = @all

gl-easy-install 명령을 실행했을 때 주었던 마지막 인자가 기억나는가? 그때 사용했던 sitaram은 gitolite-admin 저장소에 대한 읽기, 쓰기 권한을 모두 가지고 있고 공개키도 이미 등록돼 있다.

Gitolite의 설정 파일은 conf/example.conf 파일 안에 상세히 설명돼 있다. 여기에서는 중요한 부분에 대해서만 다룰 것이다.

사용자와 저장소의 그룹을 만들 수 있다. 이 그룹은 매크로와 비슷하다. 그룹을 만들 때는 그 그룹이 프로젝트의 그룹인지 사용자의 그룹인지 구분하지 않지만 사용할 때에는 다르다.

@oss_repos      = linux perl rakudo git gitolite
@secret_repos   = fenestra pear

@admins         = scott     # Adams, not Chacon, sorry :)
@interns        = ashok     # get the spelling right, Scott!
@engineers      = sitaram dilbert wally alice
@staff          = @admins @engineers @interns

그리고 ref 단위로 권한을 제어할 수 있다. 다음 예제를 보자. 인턴(interns)들은 int 브랜치에만 Push할 수 있고 engineers는 eng-로 시작하는 많은 브랜치들과 rc 뒤에 숫자가 붙는 태그들을 Push할 수 있다. 그리고 관리자는 모든 ref에 무엇이든지(되돌리기도 포함됨) 할 수 있다.

repo @oss_repos
    RW  int$                = @interns
    RW  eng-                = @engineers
    RW  refs/tags/rc[0-9]   = @engineers
    RW+                     = @admins

RWRW+ 뒤에 나오는 표현식은 정규표현식(regex)이고 의미는 Push하는 ref 이름의 패턴을 나타낸다. 그래서 우리는 refex라고 부른다. 물론 refex는 여기에 보여준 것보다 훨씬 더 강력하다. 하지만, 펄의 정규표현식에 익숙하지 않은 독자도 있으니 여기서 무리할 필요 없다.

그리고 이미 예상했겠지만 Gitolite는 refs/heads/라고 시작하지 않는 refex에 대해서는 암묵적으로 refs/heads/가 생략된 것으로 판단한다.

특정 저장소의 모든 규칙을 한 곳에 모으지 않아도 괜찮다. 위에 보여준 oss_repos와 다른 설정이 마구 섞여 있어도 괜찮다. 다음과 같이 아주 제한적이고 특별한 규칙을 아무 데나 추가해도 좋다:

repo gitolite
    RW+                     = sitaram

이 규칙은 gitolite 저장소를 위해 지금 막 추가한 규칙이다.

이제는 접근제어 규칙이 실제로 어떻게 적용되는지 궁금할 것이다. 이제부터 그 내용을 살펴보자.

Gitolite는 두 단계로 접근을 제어한다. 첫 단계가 저장소 단계인데 접근하는 저장소의 ref 중에서 하나라도 읽고 쓸 수 있으면 실제로 그 저장소 전부에 대한 읽기, 쓰기 권한이 있는 것이다.

두 번째 단계는 브랜치나 태그 단위로 제어하는 것으로 오직 "쓰기" 접근만 제어할 수 있다. 어느 사용자가 특정 ref 이름으로 접근을 시도하면(W+같은) 설정 파일에 정의된 순서대로 접근 제어 규칙이 적용된다. 그 순서대로 사용자 이름과 ref 이름을 비교하는데 ref 이름의 경우 단순히 문자열을 비교하는 것이 아니라 정규 표현식을 만족하게 하는 것이다. 만족하는 것을 찾으면 정상적으로 Push되지만 찾지 못하면 거절된다.

"deny" 규칙을 꼼꼼하게 제어하기

지금까지는 R, RW, RW+ 권한에 대해서만 다뤘다. Gitolite는 "deny" 규칙을 위해서 - 권한도 지원한다. 이것으로 복잡도를 낮출 수 있다. -로 거절도 할 수 있기 때문에 규칙의 순서가 중요하다.

다시 말해서 engineers가 master와 integ 브랜치 이외의 모든 브랜치를 되돌릴 수 있게 하고 싶으면 다음과 같이 한다:

    RW  master integ    = @engineers
    -   master integ    = @engineers
    RW+                 = @engineers

즉, 접근제어 규칙을 순서대로 찾기 때문에 순서대로 정의해야 한다. 첫 번째 규칙은 master나 integ 브랜치에 대해서 읽기, 쓰기만 허용하고 되돌리기는 허용하지 않는다. master나 integ 브랜치를 되돌리는 Push는 첫 번째 규칙에 어긋나기 때문에 바로 두 번째 규칙으로 넘어간다. 그리고 거기서 거절된다. master나 integ 브랜치 이외의 모든 ref에 대한 모든 Push는 첫 번째와 두 번째 규칙에는 만족하지 않고 마지막 규칙으로 허용된다.

파일 단위로 Push를 제어하기

브랜치 단위로 Push를 제어할 수 있지만 수정한 파일단위로도 제어할 수 있다. 예를 들어 Makefile을 보자. Makefile 파일에 의존하는 파일은 매우 많고 보통 꼼꼼하게 수정하지 않으면 문제가 생긴다. 그래서 아무나 Makefile을 수정하게 둘 수 없다. 그러면 다음과 같이 설정한다:

repo foo
    RW                  =   @junior_devs @senior_devs

    RW  NAME/           =   @senior_devs
    -   NAME/Makefile   =   @junior_devs
    RW  NAME/           =   @junior_devs

이 내용은 conf/example.conf에도 자세히 설명돼 있다.

Personal 브랜치

Gitolite는 또 "Personal 브랜치"라고 부르는 기능을 지원한다. 이 기능은 실제로 "Personal 브랜치 네임스페이스"라고 부르는 것이 더 적절하다. 이 기능은 기업에서 매우 유용하다.

Git을 사용하다 보면 코드를 공유하려고 "Pull 해주세요"라고 말해야 하는 일이 자주 생긴다. 그런데 기업에서는 절대 인증하지 않은 접근을 허용하지도 않는 데다가 아예 다른 사람의 컴퓨터에 접근할 수 없다. 그래서 공유하려면 중앙 서버에 Push하고 나서 Pull해야 한다고 다른 사람에게 말해야만 한다.

중앙집중식 VCS에서 이렇게 마구 사용하면 브랜치 이름이 충돌할 확률이 높다. 그때마다 관리자는 추가로 권한을 관리해줘야 하기 때문에 관리자의 노력이 쓸데없이 낭비된다.

Gitolite는 모든 개발자가 "personal"이나 "scratch" 네임스페이스를 가질 수 있도록 허용한다. 이 네임스페이스는 refs/personal/<devname>/* 라고 표현한다. 자세한 것은 doc/3-faq-tips-etc.mkd의 "Personal 브랜치" 절을 참고한다.

"와일드카드" 저장소

Gitolite는 펄 정규표현식으로 저장소 이름을 표현하기 때문에 와일드카드를 사용할 수 있다. 그래서 assignments/s[0-9][0-9]/a[0-9][0-9] 같은 정규표현식을 사용할 수 있다.

rc 파일에 $GL_WILDREPOS = 1로 설정하면 이 기능을 사용할 수 있다. 게다가 새로운 권한 모드인 "C"를 사용할 수 있게 된다. 이것은 해당 사용자가 와일드카드가 있는 정규표현식에 만족하는 저장소를 만들 수 있는 권한을 부여하는 것이다. 사용자가 저장소를 만들면 자동으로 사용자를 소유자로 만든다. 이 소유자는 R과 RW 권한이 필요한 사람들에게 권한을 부여할 수 있다. 이 기능은 doc/4-wildcard-repositories.mkd에 자세히 설명돼 있다.

그 밖의 기능들

마지막으로 알고 있으면 유용한 것들이 있다. Gitolite에는 많은 기능이 있고 자세한 내용은 "Faq, Tip, 등등"의 다른 문서에 잘 설명돼 있다.

로깅: 누군가 성공적으로 접근하면 Gitolite는 무조건 로그를 남긴다. 관리자가 한눈파는 사이에 되돌리기(RW+) 권한을 가진 망나니가 "master" 브랜치를 날려버릴 수도 있다. 이 경우 로그 파일이 구원해줄 것이다. 이 로그 파일을 참고하여 버려진 SHA를 빠르고 쉽게 찾을 수 있다.

Git이 설치된 경로에 자유롭다: 이것은 정말 편리하고 유용한 기능이다. Gitolite는 Git을 $PATH 안에 찾을 수 있도록 설치하지 않아도 된다. 생각하는 것보다 자주 이럴 필요가 있다. 회사나 호스팅 업체는 시스템 전체에 영향이 끼쳐지도록 설치하지 못하게 한다. 그래서 결국엔 계정 디렉토리에 설치해야 한다. 그리고 클라이언트 쪽 에서 어떤 이유로 표준 위치에 git을 설치하지 못할 수도 있다. Gitolite를 verbose 모드로 설치하면 "rc" 파일의 "$GIT_PATH"를 수정할 수 있다. 그 외 클라이언트에서 해야 할 일은 전혀 없다.

접근 권한 보여주기: 만약 어떤 서버에서 작업을 시작하려고 할 때 필요한 것이 무엇일까? Gitolite는 해당 서버에 대해 접근할 수 있는 저장소가 무엇인지, 어떤 권한을 가졌는지 보여준다:

    hello sitaram, the gitolite version here is v1.5.4-19-ga3397d4
    the gitolite config gives you the following access:
         R     anu-wsd
         R     entrans
         R  W  git-notes
         R  W  gitolite
         R  W  gitolite-admin
         R     indic_web_input
         R     shreelipi_converter

권한 위임: 조직 규모가 크면 저장소에 대한 책임을 여러 사람이 나눠 가지는 게 좋다. 여러 사람이 각자 맡은 바를 관리하도록 할 수 있다. 그래서 주요 관리자의 업무가 줄어들기에 병목현상이 적어진다. 이 기능에 대해서는 doc/ 디렉토리에 포함된 Gitolite 문서를 참고하라.

Gitweb 지원: Gitolite는 몇 가지 방법으로 Gitweb을 지원한다. Gitweb을 사용할 저장소가 무엇인지 명시할 수 있다. 그리고 Gitolite 설정 파일에서 "owner"와 "description" 항목을 Gitweb으로 가져올 수 있다. Gitolite 설정 파일을 HTTP 인증 설정 파일로 컴파일할 수 있고 Gitweb은 이 HTTP 인증 파일로 접근을 제어할 수 있다. 그래서 Gitweb과 Gitolite은 같은 접근 규칙을 사용할 수 있다.

미러링: Gitolite의 미러는 여러 개 만들 수 있어서 주 서버가 다운 돼도 변경하면 된다.