SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-13

셀프 호스팅 Git 서버 추천: Forgejo, Gitea, cgit 비교

1GB RAM VPS에서 운영 가능한 셀프 호스팅 Git 서버를 비교합니다. SSH 베어 리포지토리부터 cgit, Forgejo, Gitea, GitLab까지 메모리 사용량과 서버 사양을 분석하여 프로젝트 규모에 맞는 최적의 선택지를 제안합니다.

어떤 셀프 호스팅 Git 서버를 운영해야 하는가

셀프 호스팅 Git 서버는 단일 제품이 아니며, VPS의 RAM(random access memory) 용량에 따라 운영 가능한 버전이 결정됩니다. Git은 자체 데몬이 필요하지 않습니다. 베어 리포지토리(bare repository)와 SSH(secure shell) 계정만 있으면 가장 작은 사양의 서버에서도 즉시 작동하는 서버가 됩니다. 그 이상의 모든 선택지는 그 옆에서 함께 실행할 웹 애플리케이션을 선택하는 것이며, 단계가 올라갈 때마다 작은 VPS가 감당하기 어려운 메모리 자원이 소모됩니다.

선택지는 네 단계로 나뉩니다. 첫째, 기존에 실행 중인 서비스 외에 추가로 리스닝하는 프로세스 없이 SSH를 통해 사용하는 베어 리포지토리 방식입니다. 둘째, 데이터베이스 없이 빠르게 읽기 전용 웹 뷰를 제공하는 cgit입니다. 셋째, 계정, 이슈, 풀 리퀘스트 기능을 모두 갖추고 수백 메가바이트의 메모리를 사용하는 Forgejo 또는 Gitea입니다. 넷째, 다른 선택지보다 훨씬 큰 서버 사양을 요구하는 GitLab입니다.

수행해야 할 작업의 성격에 따라 결정한 뒤, 현재 사용 중인 요금제의 메모리 사양과 비교하여 확인하십시오.

각 옵션에 실제로 필요한 RAM 용량

이 프로젝트들 중 하드웨어 사양을 공개하는 곳은 두 곳뿐입니다. 공개된 수치는 보장된 값이 아니라 최소 사양으로 간주해야 하며, 실제 인스턴스가 실행되면 systemd-cgtop 또는 ps -o rss= -C forgejo를 사용하여 직접 측정하십시오.

ChartRAM the projects document, official docs, August 2026
The data behind this chart
[
  {
    "label": "Gitea, small team",
    "ram_gb": 1
  },
  {
    "label": "GitLab, memory constrained",
    "ram_gb": 8
  },
  {
    "label": "GitLab, single node baseline",
    "ram_gb": 16
  }
]

Gitea는 소규모 팀과 프로젝트에 일반적으로 충분한 사양으로 2개의 CPU 코어와 1 GB의 RAM을 명시하고 있으며, 소규모 작업 부하에는 Raspberry Pi 3로도 충분하다고 언급합니다. GitLab은 단일 노드 설치의 기본 사양으로 16 GB를, 자체 문서에서 메모리 제약 환경이라고 부르는 최소 사양으로 8 GB를 제시합니다. Forgejo는 하드웨어 요구 사항을 전혀 공개하지 않습니다. Forgejo는 Gitea의 포크(fork)이며 동작 방식도 유사하므로, Gitea의 수치가 참고할 수 있는 가장 근접한 가이드입니다.

1 GB VPS에서 이것이 의미하는 바는 다음과 같습니다. 베어 리포지토리와 cgit은 상주 서비스를 실행하지 않으므로 여유 있게 구동됩니다. Forgejo나 Gitea는 SQLite 환경에서 소규모 팀을 지원하며 실행될 수 있지만, 이는 문서화된 최소 사양에 머물러 있는 상태이므로 해당 서버에서 PostgreSQL과 CI(지속적 통합) 러너는 실행하지 마십시오. 웹 인터페이스가 오류 메시지 없이 사라진다면 sudo dmesg -T | grep -i oom을 실행하여 Out of memory: Killed process 1181 (forgejo)과 같은 줄이 있는지 확인하십시오. 이는 커널의 OOM(Out of Memory) 킬러가 해당 프로세스를 종료했음을 의미합니다. 1 GB 서버에서 GitLab을 구동하는 것은 튜닝의 문제가 아닙니다. 애초에 실행 자체가 불가능합니다.

Tier 0: SSH를 통한 베어 리포지토리

Git은 별도로 시작해야 할 네트워크 데몬이 없습니다. SSH를 통한 git push는 원격지에서 일반적인 Unix 프로세스로서 git-receive-pack을 실행하므로, 키를 사용하여 접근할 수 있는 모든 계정은 이미 Git 리모트가 됩니다. 리포지토리 전용 계정을 하나 생성하고, 리포지토리는 해당 계정의 홈 디렉터리 외부에 배치하십시오. Ubuntu 24.04에서는 새로운 홈 디렉터리의 모드가 0750으로 설정되어, 나중에 추가하는 웹 뷰어가 해당 디렉터리 내부를 읽을 수 없기 때문입니다.

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \
  --group --disabled-password --home /home/git git
sudo install -d -m 0755 -o git -g git /srv/git
sudo -u git git init --bare /srv/git/project.git

--bare는 작업 복사본이 없는 리포지토리를 생성하며, 이는 서버가 유지해야 하는 형태입니다. 작업 복사본이 있는 리포지토리로 푸시를 시도하면 refusing to update checked out branch: refs/heads/main 오류와 함께 거부되며, 이는 이 계층에서 가장 흔히 발생하는 실수입니다.

이제 해당 계정에 키를 등록하고 리포지토리를 클론합니다.

sudo -u git install -d -m 700 /home/git/.ssh
sudo -u git tee -a /home/git/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop
EOF
sudo -u git chmod 600 /home/git/.ssh/authorized_keys
git remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin main

성공적인 첫 푸시는 * [new branch] main -> main으로 끝납니다. git@vps.example.com: Permission denied (publickey)로 끝나는 경우 인증이 되지 않은 것이므로, sudo journalctl -u ssh -n 20을 사용하여 서버 로그를 확인하십시오. Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys라는 메시지가 포함된 줄이 있다면 파일 모드가 잘못된 것입니다. sshd는 다른 사용자가 쓰기 권한을 가진 키 파일을 무시하기 때문입니다.

그런 다음 해당 계정의 셸 접근 권한을 제거합니다.

command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" git

git-shell은 Git이 SSH를 통해 보내는 몇 가지 명령만 허용합니다. 따라서 이제 대화형 로그인을 시도하면 프롬프트 대신 메시지가 출력되며 중단됩니다.

fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.

이것이 서버의 전부입니다. 데이터베이스도 없고, 업그레이드할 웹 프로세스도 없습니다. 포기해야 할 것은 코드 저장소 서비스가 제공하는 모든 기능입니다. 브라우징, 이슈 트래커, 풀 리퀘스트, 사용자별 권한 설정이 없습니다. 해당 파일에 등록된 모든 키는 git 사용자가 소유한 모든 리포지토리를 읽고 쓸 수 있습니다.

1단계: cgit은 데이터베이스 없이 웹 뷰를 제공합니다

cgit은 C 언어로 작성된 CGI(Common Gateway Interface) 프로그램입니다. 웹 서버는 요청이 들어올 때마다 이 프로그램을 실행하며, 저장소를 디스크에서 직접 읽어오므로 자체적인 상태를 저장하지 않습니다. Ubuntu 24.04의 universe 구성 요소에서 이 패키지를 제공합니다.

sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgit

/etc/cgitrc에서 저장소 디렉터리를 지정하십시오:

root-title=Git on example.com
css=/cgit.css
logo=/cgit.png
cache-size=1000
cache-root=/var/cache/cgit
snapshots=tar.gz zip
scan-path=/srv/git

scan-path은 해당 디렉터리를 탐색하여 발견한 모든 저장소를 나열하므로, 새로운 bare 저장소를 생성해도 별도의 설정 없이 자동으로 나타납니다. cache-size는 캐시된 페이지의 개수이며, 이 값이 0이면 캐싱 기능은 비활성화된 상태로 유지됩니다. Debian 및 Ubuntu 패키지에 기본 설정이 포함되어 있을 수 있으므로, 설정을 추가하기 전에 /etc/cgitrc에 이미 작성된 내용을 먼저 확인하십시오.

각 항목에는 저장소의 description 파일 첫 번째 줄이 표시되므로, 새로 생성된 bare 저장소는 Unnamed repository; edit this file 'description' to name the repository.로 나타납니다. 저장소마다 다음 명령을 실행하여 이를 수정하십시오:

echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/description
nginx 사이트 파일 및 확인 방법
server {
    listen 80;
    server_name git.example.com;
    root /usr/share/cgit;

    try_files $uri @cgit;

    location @cgit {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param QUERY_STRING $args;
        fastcgi_param HTTP_HOST $server_name;
        fastcgi_pass unix:/run/fcgiwrap.socket;
    }
}
sudo systemctl enable --now fcgiwrap.socket
sudo nginx -t && sudo systemctl reload nginx
systemctl show fcgiwrap.socket -p Listen

root /usr/share/cgitcgit.csscgit.png을 일반 파일로 제공하며, try_files은 나머지 모든 요청을 /usr/lib/cgit/cgit.cgi의 CGI로 전달합니다. /var/log/nginx/error.logconnect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) 오류가 발생하며 502 페이지가 뜬다면, 소켓 유닛이 실행 중이지 않거나 다른 경로에서 대기 중인 것입니다. systemctl show 줄을 확인하면 실제 사용 중인 경로를 알 수 있습니다.

구축하기 전에 알아두어야 할 두 가지 제한 사항이 있습니다. cgit은 읽기 전용이며 로그인 기능을 제공하지 않으므로, scan-path 하위의 모든 내용은 공개됩니다. 비공개 저장소는 해당 디렉터리에 두지 않거나, 사이트 전체에 HTTP 기본 인증을 적용하십시오. 또한 CGI는 웹 서버 사용자의 권한으로 실행되므로, 해당 사용자가 /srv/git 경로를 탐색하고 각 저장소를 읽을 수 있는 권한이 있어야 합니다. 접근할 수 없는 디렉터리는 오류 대신 빈 인덱스로 표시됩니다.

Tier 2: 이슈 및 풀 리퀘스트를 위한 Forgejo 또는 Gitea

Forgejo와 Gitea는 동일한 개념을 공유합니다. 사용자, 조직, 이슈, 풀 리퀘스트, 릴리스, 패키지 레지스트리 및 내장 CI 시스템을 갖춘 웹 포지 서비스를 단일 Go 바이너리로 제공합니다. 바이너리와 SQLite만 있으면 설치가 완료되므로 GitLab을 실행할 수 없는 저사양 하드웨어에서도 원활하게 작동합니다. 아래의 Compose 파일은 Forgejo 공식 문서에서 제공하는 예시이며, 2026년 8월 기준의 이미지 태그를 사용합니다.

networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:16
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '3000:3000'
      - '222:22'
docker compose up -d
docker compose ps
curl -sI http://127.0.0.1:3000 | head -1

curl 명령을 실행하면 HTTP 상태 라인이 출력되어야 합니다. 초기 설정을 마치기 전에는 /install로 리다이렉트될 수 있는데, 이는 서비스가 정상적으로 실행 중임을 의미합니다. 만약 컨테이너가 즉시 종료된다면, 일반적으로 소유권 문제일 가능성이 큽니다. ./forgejo 디렉터리는 USER_UID에 지정된 UID(사용자 ID) 소유여야 하며, 그렇지 않으면 프로세스가 데이터 디렉터리에 쓰기 작업을 수행할 수 없습니다. VPS에서의 Docker Compose 문서에서 해당 파일 구조와 볼륨 소유권 규칙을 상세히 다룹니다.

설정 페이지에서 입력하는 두 가지 항목이 클론 URL의 정상 작동 여부를 결정합니다. Compose 파일에서 호스트 포트 222를 컨테이너의 포트 22로 매핑하므로 SSH 포트는 반드시 222여야 하며, 도메인 이름은 사용자가 실제로 입력할 주소와 일치해야 합니다. 이 설정이 잘못되면 모든 저장소 페이지에서 제공하는 클론 명령어가 복사해서 사용하는 모든 사용자에게 실패하게 됩니다. 설정 이후에는 app.ini 파일의 [server] 섹션에서 SSH_PORT, SSH_DOMAIN, ROOT_URL 항목으로 수정할 수 있습니다.

공개 인스턴스로 운영하려면 웹 포트를 루프백 주소('127.0.0.1:3000:3000')에만 바인딩하고, 그 앞에 nginx를 배치하여 TLS(전송 계층 보안)를 적용하십시오. Gitea 역시 동일한 방식으로 gitea/gitea 이미지를 사용하거나, 하나의 systemd 유닛과 하나의 app.ini 파일을 사용하는 단일 바이너리 형태로 설치할 수 있습니다. 2026년 8월 기준 Gitea의 현재 안정화 릴리스는 1.27.1입니다.

가능한 한 SQLite를 계속 사용하는 것을 권장합니다. 인스턴스를 단일 프로세스와 단일 파일로 유지할 수 있으며, 별도의 관리 서비스 없이도 재부팅 후 즉시 복구됩니다. PostgreSQL은 여러 사용자가 동시에 데이터를 기록할 때 유리합니다. SQLite는 쓰기 작업을 직렬화하므로, CI 작업이 길게 실행되어 쓰기가 빈번하게 발생하면 성능 저하가 생길 수 있기 때문입니다. 두 프로젝트 모두 기존 인스턴스를 나중에 PostgreSQL로 이전하는 기능을 지원하므로, 지금의 결정이 영구적인 것은 아닙니다.

Forgejo와 Gitea: 실제 차이점은 무엇인가

두 프로젝트는 뿌리를 공유합니다. Gitea는 2016년 Gogs에서 포크되었습니다. 2022년 말, Gitea 도메인과 상표권에 대한 통제권이 Gitea Ltd라는 기업으로 넘어갔고, 이에 반발한 여러 메인테이너가 Codeberg와 함께 Forgejo를 시작했습니다. Forgejo는 독일에 등록된 비영리 협회인 Codeberg e.V.에서 배포하며, 2024년에 라이선스를 MIT에서 GPLv3(GNU 일반 공중 사용 허가서 버전 3)로 변경했습니다. Gitea는 MIT 라이선스를 유지하며 상업적 지원을 바탕으로 개발되고 있습니다.

일상적인 사용 관점에서 기능은 거의 비슷합니다. 하지만 두 서비스 간의 전환 경로는 그렇지 않습니다. 2025년 1월에 출시된 Forgejo v10.0이 Gitea 데이터베이스를 직접 가져올 수 있는 마지막 버전이었으며, 이마저도 Gitea v1.22 이하 버전에서만 가능했습니다. 2026년 8월 기준 Gitea는 1.27.1 버전이므로, 현재 운영 중인 Gitea 인스턴스를 Forgejo로 직접 전환하는 공식적인 방법은 없습니다. 데이터를 채우기 전에 하나를 선택해야 하며, 이후의 이동은 내보내기 및 다시 가져오기 과정으로 처리해야 합니다.

선택을 위한 간단한 기준은 다음과 같습니다. 거버넌스가 중요하거나 프로젝트가 비영리 단체에 머물기를 원한다면 Forgejo를 운영하십시오. 더 큰 설치 기반과 상업적 지원 옵션을 원한다면 Gitea를 선택하십시오. 두 프로젝트 모두 오픈 소스로 유지되며 자주 릴리스됩니다. Forgejo는 3개월마다 안정적인 릴리스를, 매년 LTS(장기 지원) 릴리스를 배포합니다. 2026년 8월 기준 v16.0.2가 최신 버전이며 v15.0.6이 LTS 버전입니다.

Tier 3: GitLab을 실행하기 위한 최소 비용

GitLab CE는 일반적인 소프트웨어와는 다른 범주에 속합니다. 하나의 인스턴스는 웹 애플리케이션을 위한 Puma, 백그라운드 작업을 위한 Sidekiq, PostgreSQL, Redis, 저장소 접근을 위한 Gitaly, 그리고 앞단에서 동작하는 nginx 등 여러 서비스가 협력하는 구조입니다. Omnibus 패키지는 이들을 한꺼번에 설치하므로 설치는 간편하지만, 요구되는 최소 메모리 사양은 높습니다.

GitLab의 요구사항 페이지에 따르면 단일 노드 설치 시 16 GB RAM과 8 vCPU를 기본 사양으로 권장하며, 메모리가 제한된 환경이라도 최소 8 GB는 필요하다고 명시되어 있습니다. 또한 같은 페이지에서 스왑(swap)을 비활성화할 것을 권고하는데, 이는 부하가 걸린 상태에서 스왑이 발생하면 인스턴스 성능이 급격히 저하되기 때문입니다. 이 수치는 2026년 8월 기준으로 공개된 사양이며, 수년간 계속 증가해 왔으므로 서버 규모를 산정하기 전에 해당 페이지를 다시 확인해야 합니다.

이러한 자원을 할당하면 컨테이너 레지스트리, 패키지 레지스트리, 세밀한 권한 관리, 규정 준수 및 감사 기능, 대규모 환경에서 검증된 CI 등 실질적인 기능을 얻을 수 있습니다. 만약 팀원 중 누구도 이번 분기에 필요한 기능을 위 목록에서 찾을 수 없다면, 더 큰 VPS 비용을 지불하면서 아무런 이득도 얻지 못하는 셈입니다.

SSH 접근 모델: 하나의 git 사용자와 다수의 키

모든 계층은 동일한 방식으로 인증합니다. git이라는 이름의 Unix 계정이 하나 존재하며, 모든 공개 키는 해당 계정의 ~/.ssh/authorized_keys에 저장됩니다. 인증은 키를 통해 이루어집니다. 권한 부여는 키와 같은 줄 앞에 작성하는 옵션에 따라 결정됩니다.

일반적인 키 라인은 해당 계정이 수행할 수 있는 모든 권한을 소유자에게 부여합니다. 강제 명령(forced command)을 사용하면 Git으로 권한을 제한할 수 있습니다.

restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop

OpenSSH 7.2부터 사용 가능한 restrict은 포트 포워딩, 에이전트 포워딩, X11 및 PTY(가상 터미널) 할당을 한 단어로 비활성화합니다. command=는 클라이언트가 요청한 명령을 지정한 명령으로 대체하며, Git은 요청을 $SSH_ORIGINAL_COMMAND로 전송하므로 여전히 정상적으로 작동합니다.

포지(forge) 소프트웨어는 해당 파일을 자동으로 작성하며, 이것이 계층 0과 계층 2의 실질적인 차이점입니다. Forgejo와 Gitea는 등록된 키마다 한 줄씩 authorized_keys을 다시 작성하며, 각 줄에는 데이터베이스 ID로 키를 식별하는 강제 명령이 포함됩니다.

command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice

이 강제 명령을 통해 하나의 공유 Unix 계정이 사용자별 권한 체계로 변환됩니다. key-3은 어떤 사용자가 연결 중인지 포지에 알리며, 포지는 객체가 이동하기 전에 해당 사용자가 저장소에 접근할 권한이 있는지 확인합니다. 포지가 관리하는 서버에서 해당 파일을 직접 수정하지 마십시오. 데이터베이스에서 파일이 다시 작성되므로 수정 사항이 사라집니다. 배포 키(deploy key)도 동일한 메커니즘을 사용합니다. 배포 키는 단일 저장소에 등록된 일반적인 SSH 키이며, 보통 읽기 전용으로 설정되고 sshd가 아닌 포지 내부에서 권한 확인이 이루어집니다.

위의 설정보다 두 가지 습관이 더 중요합니다. 공유 키를 사용하지 말고 사람이나 기기당 하나의 키를 발급하십시오. 공유 키를 폐기하려면 모든 사용자에게 키를 동시에 교체해야 하기 때문입니다. 또한 누군가 떠나는 날 즉시 키를 제거하십시오. 해당 파일에 남아 있는 오래된 키는 아무도 감시하지 않는 영구적인 로그인 수단이 됩니다. 서버에서의 올바른 SSH 키 관리에서는 키 유형과 암호(passphrase)를 다루며, 이 모든 내용은 여기에도 그대로 적용됩니다. 서버가 새로 구축된 상태라면 저장소를 올리기 전에 새로운 VPS에서의 첫 10분을 먼저 수행하는 것이 좋습니다.

자체 Git 서버에서 GitHub Actions를 실행할 수 있습니까?

GitHub Actions 문법으로 작성된 워크플로우를 실행할 수 있습니다. 하지만 GitHub 자체를 실행할 수는 없습니다. Forgejo Actions는 Forgejo v1.21부터 기본적으로 활성화되어 있으며 각 저장소의 .forgejo/workflows에서 워크플로우 파일을 읽어옵니다. Gitea Actions도 동일한 방식으로 작동하며 .gitea/workflows를 읽습니다. 두 경우 모두 runner라는 별도의 프로그램이 필요하며, 관리자 설정에서 발급받은 토큰을 사용하여 인스턴스에 등록해야 합니다. 공개된 많은 액션은 수정 없이 실행되지만, GitHub API를 호출하거나 GitHub 호스팅 인프라를 전제로 하는 액션은 실행되지 않습니다.

두 가지 결과를 고려해야 합니다. runner는 모든 작업마다 컨테이너를 시작하므로 컨테이너 엔진과 자체 메모리 예산이 필요합니다. 이것이 바로 forge와 동일한 1 GB 서버에 runner를 두어서는 안 되는 이유입니다. 또한 runner는 워크플로우 파일에 적힌 모든 내용을 실행합니다. Forgejo 문서에도 명시되어 있듯이, runner는 원격 코드 실행(remote code execution)을 수행합니다. 가능하면 별도의 호스트를 할당하거나, 최소한 권한이 없는 별도의 사용자를 생성하고 특정 저장소로 범위가 제한된 등록 토큰을 사용하십시오.

저장소는 GitHub에 그대로 두고 연산 자원만 직접 제어하는 하드웨어에서 사용하려는 경우, 이는 다른 설정과 절차가 필요한 상황입니다. 자체 호스팅 GitHub Actions runner는 GitHub 저장소에 연결되며 위에서 언급한 과정이 필요하지 않습니다. GitHub를 떠날 때 발생하는 비용을 고민 중이라면, GitHub가 실제로 제공하는 것을 통해 Git 호스팅과 그 주변 네트워크 환경을 분리하여 파악할 수 있습니다.

백업: 저장소는 상태의 절반에 불과합니다

Bare 저장소는 하나의 디렉터리이므로, 이를 복사하면 내부의 모든 항목이 복사됩니다. 다른 머신에서 수행한 mirror clone은 실제 백업 역할을 하며, 제자리에서 갱신할 수 있습니다.

git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote update

이 명령은 모든 ref와 모든 object를 가져옵니다. 하지만 서버 측 hook이나 description 파일은 가져오지 않으므로, hook을 사용 중이라면 해당 디렉터리를 파일 수준에서 별도로 복사해 두어야 합니다.

Forge는 이슈, pull request, 사용자, 키, 권한 정보를 데이터베이스에 보관합니다. 저장소만 복사하면 이 모든 정보가 유실됩니다. 두 프로젝트 모두 데이터베이스, 저장소, 설정, 첨부 파일을 하나의 아카이브로 묶어주는 dump 명령을 제공합니다.

sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zip

Docker 환경에서는 컨테이너 내부에서 동일한 명령을 실행합니다. 설정 경로는 이미지에 따라 다르므로 명령을 입력하기 전에 경로를 확인하십시오.

docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.ini

데이터 소유자 계정으로 명령을 실행하고, 해당 사용자가 쓰기 권한을 가진 디렉터리에 아카이브를 저장하십시오. 그 후 아카이브를 서버 외부로 복사하십시오. 백업 대상 머신에만 존재하는 백업은 진정한 백업이 아닙니다. 복구는 사람들이 흔히 간과하는 단계입니다. 지금 여분의 장비에 dump 파일을 풀어보며 복구 절차를 익히십시오. 장애가 발생한 긴박한 상황이 아닌, 평온한 시점에 미리 연습해야 합니다.

시나리오별 선택

노트북 한 대와 VPS 한 대를 사용하는 1인 환경이며 브라우저 접근이 필요 없다면, SSH를 통한 bare repository를 사용하십시오. 추가로 실행되는 서비스가 없으며 업데이트할 항목도 없습니다.

위와 동일한 환경에서 브라우저로 코드를 읽고 링크를 공유하고 싶다면 cgit을 추가하십시오. 여전히 데이터베이스는 필요 없으며 상주하는 프로세스도 없습니다.

서로의 코드를 검토하고 이슈를 추적해야 하는 팀이라면 2 GB 이상의 RAM을 갖춘 환경에서 Forgejo나 Gitea를 사용하십시오. 작업량이 늘어나면 CI runner를 별도의 서버로 분리하십시오.

컨테이너 레지스트리와 감사 추적(audit trail)이 필요한 조직이며 서버에 16 GB의 RAM을 할당할 수 있다면 GitLab을 사용하십시오. 이 사양 미만이라면 설치를 권장하지 않습니다.

앞선 세 단계는 모두 저장소가 디스크상의 일반적인 Git 디렉터리이므로 상위 단계로 이전하는 비용이 저렴합니다. 업무에 필요한 가장 낮은 단계부터 시작하십시오. 같은 서버에 무엇을 더 설치할지 고민 중이라면, 직접 호스팅할 가치가 있는 서비스 목록을 참고하여 RAM 자원을 두고 Git 서버와 경쟁할 다른 서비스들을 확인해 보십시오.

FAQ

1 GB RAM을 가진 VPS에서 Forgejo나 Gitea를 실행할 수 있습니까?

네, 소규모 팀이 SQLite를 사용하고 서버에 다른 무거운 서비스가 없다면 가능합니다. Gitea 문서에 따르면 1 GB RAM과 2개의 CPU 코어는 소규모 팀과 프로젝트에 충분한 사양이며, Gitea에서 파생된 Forgejo도 동일한 요구 사항을 가집니다. 해당 서버에 PostgreSQL이나 CI 러너를 추가하지 마십시오. 서비스 로그에 오류 없이 서비스가 사라진다면 sudo dmesg -T | grep -i oom 명령을 실행하십시오. 로그에 프로세스가 강제 종료되었다는 메시지가 있다면 커널의 OOM(Out of Memory) 킬러가 작동한 것이므로, 설정 조정보다는 더 높은 사양의 플랜으로 변경해야 합니다.

Forgejo와 Gitea의 차이점은 무엇입니까?

두 서비스는 코드베이스 역사를 공유하며 대부분의 기능을 동일하게 제공합니다. Gitea는 2016년 Gogs에서 파생되었고, Forgejo는 Gitea의 상표권이 기업으로 넘어간 이후인 2022년 말 Gitea에서 파생되었습니다. Forgejo는 독일의 비영리 단체인 Codeberg e.V.가 GPLv3 라이선스로 배포하며, Gitea는 상업적 지원을 받는 MIT 라이선스를 유지합니다. 실질적인 차이는 마이그레이션 경로에 있습니다. 2025년 1월에 출시된 Forgejo v10.0이 Gitea 데이터베이스를 직접 가져올 수 있는 마지막 버전이었으며, 이마저도 Gitea v1.22 이하 버전에서만 가능했습니다. 따라서 현재 운영 중인 Gitea 인스턴스를 직접 전환하는 공식적인 방법은 없습니다.

자체 호스팅 Git 서버에서 GitHub Actions 워크플로우를 실행할 수 있습니까?

Forgejo Actions와 Gitea Actions 모두 .forgejo/workflows.gitea/workflows 파일에서 읽어온 GitHub Actions YAML 구문으로 작성된 워크플로우를 실행합니다. 별도의 러너 프로그램을 설치하고 인스턴스에 등록해야 합니다. 공개된 많은 액션은 수정 없이 작동하지만, GitHub API를 호출하는 액션은 작동하지 않습니다. 러너는 저장소의 임의 코드를 실행하고 작업마다 컨테이너를 생성하므로, 별도의 호스트를 사용하거나 최소한 권한이 없는 별도의 사용자로 실행하십시오. 이미 Forgejo나 Gitea가 실행 중인 1 GB 서버에서는 실행하지 않는 것이 좋습니다.

자체 호스팅 Git 서버는 어떻게 백업합니까?

Bare 저장소의 경우, 다른 머신에서 git clone --mirror 명령을 사용하면 모든 참조와 객체를 복사할 수 있으며, 미러 내부에서 git remote update 명령을 실행하면 최신 상태로 갱신됩니다. Forgejo나 Gitea의 경우, 저장소는 상태의 일부일 뿐입니다. 이슈, 풀 리퀘스트, 사용자 정보, 키 등은 데이터베이스에 저장되기 때문입니다. 내장된 덤프 도구인 sudo -u git forgejo dump -c /etc/forgejo/app.ini을 사용하거나, Docker 설치 환경이라면 컨테이너 내부에서 동일한 명령을 실행하십시오. 생성된 아카이브를 서버 외부로 복사하고, 예비 머신에 복원하는 과정을 한 번 수행하여 백업 절차가 정상적으로 작동하는지 확인하십시오.

#git#self-hosting#forgejo#gitea#ssh