소수의 사용자가 이력을 공유하는 데 웹 화면이 꼭 필요한 것은 아닙니다. Linux 서버에 작업 트리가 없는 bare 저장소를 만들고 SSH로 접근하면 Git 원격 저장소로 사용할 수 있어요. 이 구조를 이해하면 이후 Gitea가 추가하는 기능도 구분하기 쉽습니다.
별도의 Rocky Linux 9 또는 Ubuntu 24.04 실습 VM에서 진행합니다. 예시 주소는 192.168.56.40이며 본인 환경으로 바꿉니다. Windows PC는 Git Bash에서 클라이언트 명령을 실행합니다. WordPress 등 기존 서비스 서버를 이 실습 대상으로 사용하지 않습니다.
Git·GitOps 전체 연재 · 14 / 24
이 글의 목차
1. 서버에 Git과 SSH 서비스를 준비한다
Rocky Linux의 관리자 계정에서 실행합니다. SSH가 이미 운영 중이면 접근 정책을 유지합니다.
sudo dnf install -y git openssh-server
sudo systemctl enable --now sshd
command -v git-shell
Ubuntu에서는 패키지 이름과 서비스 이름이 다릅니다. 아래 블록은 Rocky 명령과 둘 다 실행하는 단계가 아니라 Ubuntu용 대안입니다.
sudo apt update
sudo apt install -y git openssh-server
sudo systemctl enable --now ssh
command -v git-shell
서버의 SSH 포트는 관리망이나 VPN에서 필요한 사용자만 접근하게 제한합니다. 기존 관리 접속 경로를 확보한 뒤 방화벽 규칙을 변경합니다. Git 때문에 비밀번호 로그인이나 root 원격 로그인을 새로 허용할 필요는 없습니다.
2. Git 전용 계정과 저장소를 만든다
git 계정이 없는 새 실습 VM을 전제로 합니다. 이미 Gitea 등이 사용하는 계정이 있다면 그대로 변경하지 않습니다. 아래는 두 배포판에서 git-shell이 /usr/bin/git-shell로 확인된 경우입니다.
sudo useradd --create-home --shell /usr/bin/git-shell git
sudo install -d -o git -g git -m 0700 /home/git/.ssh
sudo install -o git -g git -m 0600 /dev/null /home/git/.ssh/authorized_keys
sudo install -d -o git -g git -m 0750 /srv/git
sudo -u git git init --bare -b main /srv/git/gitops-demo.git
git-shell은 Git 전송 명령 등 허용된 동작으로 셸 사용을 제한합니다. bare 저장소에는 일반 프로젝트처럼 편집할 작업 파일이 없습니다. 서버에서 직접 코드를 수정하는 장소가 아니라 클라이언트의 push와 fetch를 받는 장소입니다.
3. 공개 키만 등록하고 지문을 비교한다
클라이언트에서 10편의 방법으로 전용 SSH 키를 만듭니다. 서버 관리자는 전달받은 공개 키 한 줄을 /home/git/.ssh/authorized_keys에 등록합니다. 키 앞에 아래처럼 제한 옵션을 붙일 수 있습니다. 예시의 설명 부분을 실제 공개 키로 바꾸어 저장합니다.
restrict ssh-ed25519 REPLACE_WITH_PUBLIC_KEY client-label
restrict는 포트 포워딩, PTY 등 SSH 기능을 제한합니다. 키 파일의 소유자 git:git, 디렉터리 권한 700, 파일 권한 600을 유지합니다. 여러 사용자가 같은 계정을 쓰면 키별 관리·회수와 저장소별 권한 부여가 번거로워지므로 규모가 커질 때 웹 서비스를 검토합니다.
서버 콘솔에서 호스트 공개 키의 지문을 확인하고 신뢰할 수 있는 경로로 클라이언트 사용자에게 전달합니다.
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
클라이언트는 최초 접속 화면의 지문과 비교합니다. ssh git@서버가 대화형 셸을 허용하지 않는다는 메시지로 종료될 수 있는데, git-shell 계정에서는 의도한 동작입니다. 인증 자체의 실패와 구분합니다.
4. 클라이언트 저장소를 푸시한다
cd ~/git-lab/gitops-demo
git remote add local ssh://git@192.168.56.40/srv/git/gitops-demo.git
git push -u local main
git ls-remote local
이미 local 별칭이 있다면 URL을 확인하고 이름을 바꿉니다. -u로 upstream이 local/main으로 바뀐다는 점도 확인하세요. 서버에서는 관리자가 아래 조회 명령으로 상태를 볼 수 있습니다.
sudo -u git git --git-dir=/srv/git/gitops-demo.git log --oneline -5
sudo -u git git --git-dir=/srv/git/gitops-demo.git fsck --full
fsck는 객체의 연결과 유효성을 검사하지만 백업이 있다는 뜻은 아닙니다. Git 저장소, SSH 키 등록 정보, 서버 호스트 키, 권한과 설정을 복구 계획에 포함합니다. 로컬 bare 원격의 push·clone은 실제 실습으로 확인했으며 이 VM의 SSH 서비스·방화벽 구성 전체를 실행 검증한 것은 아닙니다.
계정과 bare 구성은 Git on the Server, 셸의 범위는 git-shell, 키 제한은 OpenSSH authorized_keys를 기준으로 작성했습니다. 리뷰와 세분화된 권한이 필요하면 다음 편의 Gitea로 이어갑니다.
이전 글 · [Git·GitOps 13] 저장소 정리: gitignore·줄바꿈·LFS·비밀 값 · 다음 글 · [Git·GitOps 15] Gitea로 로컬 Git 웹 서버 구축하기: Docker Compose · 연재 목록과 예제 파일

![[Git·GitOps 24] Git·CI/CD·GitOps 운영 흐름 완성하기: 장애별 판단과 복구](https://blog.maruops.com/wp-content/uploads/2026/10/maruops-git-photo-12-768x510.webp)
![[Git·GitOps 23] 비밀 값 관리: Secret의 base64와 SOPS·age 암호화](https://blog.maruops.com/wp-content/uploads/2026/10/maruops-git-photo-2-768x512.webp)
![[Git·GitOps 22] 변경 감지와 복구: 자동 Sync·selfHeal·prune·Git revert](https://blog.maruops.com/wp-content/uploads/2026/10/maruops-git-photo-10-768x576.webp)
답글 남기기