# Git 훅과 nq로 만드는 최소형 CI

> Clean Markdown view of GeekNews topic #31653. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31653](https://news.hada.io/topic?id=31653)
- GeekNews Markdown: [https://news.hada.io/topic/31653.md](https://news.hada.io/topic/31653.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-21T17:01:21+09:00
- Updated: 2026-07-21T17:01:21+09:00
- Original source: [mccd.space](https://mccd.space/posts/26-06-29/simple-git-ci)
- Points: 1
- Comments: 1

## Topic Body

- 개인 서버의 bare Git 저장소에 **`post-receive` 훅**을 추가해 테스트, 빌드, 파일 이동을 자동화하는 간단한 CI 구성임
- 기존 CI는 복잡한 YAML 설정과 느린 실행, 어려운 자체 호스팅에 비해 완전한 빌드 격리나 비밀정보 관리까지 필요하지 않았음
- 훅에서 작업을 직접 실행하면 실패 시 push가 거부되거나 완료가 지연되므로, 최소형 작업 큐 **`nq`** 로 백그라운드 처리함
- 훅은 `nq`만 호출하고 로그는 **`ssh server nqtail -a`** 로 확인해 빠르고 간단하게 운영할 수 있음
- 필요에 따라 **landdown·Podman**으로 빌드를 격리하고 sops로 비밀정보를 관리하거나, Git 이메일 패치·`git-shell`·`git http-backend`로 개발 방식을 확장할 수 있음

---

### `post-receive` 훅과 `nq` 구성
- 개인 서버에서 `ssh server git init --bare repo`로 저장소를 만들고 `git clone server:repo`로 복제함
- bare 저장소의 hooks 디렉터리에 셸 스크립트 형태의 [`post-receive` 훅](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)을 넣어 push할 때마다 CI를 시작함
- **작업을 훅에서 직접 실행**하면 두 가지 문제가 생김
  - 스크립트가 실패할 경우 push가 거부됨
  - 스크립트 실행이 느리면 push 완료도 함께 지연됨
- 훅에서는 최소형 작업 큐 [`nq`](https://git.vuxu.org/nq/about/)를 호출해 작업을 **백그라운드 큐**에 추가함
  - 로그는 `ssh server nqtail -a`로 확인함
  - 설정 과정은 짧은 [튜토리얼](https://mccd.space/wiki/tutorial-git-repo.shtml)에서 확인할 수 있음

### 격리와 개발 방식 확장
- 빌드를 샌드박스에서 실행하려면 [landdown](https://mccd.space/git/landdown/file/README.html)을 사용할 수 있음
- **Podman**으로 빌드를 호스트 환경과 격리하거나 [sops](https://github.com/getsops/sops)로 비밀정보를 관리할 수 있음
- bazaar 방식 개발에는 이메일로 Git 패치를 받는 구성이 적합함
- cathedral 방식 개발은 `git-shell` 또는 `git http-backend`로 구성 가능함

## Comments



### Comment 62157

- Author: neo
- Created: 2026-07-21T17:01:22+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/jr72dt/minimal_git_ci_using_hooks) 
- **CI에는 적어도 두 가지 문제**가 있음  
  쉬운 문제는 코드 변경 시 `make test`를 실행하는 것이고, 어려운 문제는 Linux, Windows, Mac 모두에서 `make test`를 실행하는 것임
  - Linux는 쉽고 Windows는 어렵지만, **macOS는 고통스러운 수준**임
  - CI에서 어려운 부분은 실패 시 디버깅까지 지원하는 **작업 실행 엔진**이라고 봄  
    기존 엔진들의 개발자 경험과 디버깅 기능이 늘 뒷전이라 불만이어서 https://ci.pico.sh 에서 CI 시스템을 만들고 있음. DSL도 싫고, 계층적으로 이어지는 YAML은 서서히 생명력을 빨아들이는 느낌
  - 이 방식은 쉬운 문제를 해결하며, QEMU로 BSD 계열을 지원하고 Docker로 여러 배포판까지 확장할 수는 있겠지만 그 이상에는 **더 완전한 도구**가 필요해 보임

- gitolite 위에 이를 구축하고 **Temporal**로 전달해 빌드 과정을 제한 없이 제어한 적이 있음  
  실행 실패 시 푸시를 거부할 수도 있지만, 보통은 훅을 통과시킨 뒤 실패를 별도로 처리하는 편이며 구성도 단순하고 재미있었음
  - gitolite의 **접근 제어 도구**가 특히 마음에 들고, 존재하지 않는 저장소로 푸시해 새 저장소를 만들 수 있는 방식도 훌륭함

- 셸 스크립트 실행을 중심으로 하는 또 다른 최소형 CI로 [laminar CI](https://laminar.ohwg.net/)가 있으며, **웹 UI**도 제공함

- 오래전 Windows 전용 기업 환경에서 팀 전체가 사용하는 **로컬 CI 서버**로 Mac mini를 두고 iOS 앱을 빌드했으며, 초기에 시도한 Git 활용법 중 하나였음

- https://mccd.space/git/ 에서 찾았는데, stagit 포크를 사용하는 것으로 보임  
  몇 달 전까지 Forgejo와 Woodpecker를 운영했지만 필요하지 않은 기능이 대부분이라 모두 제거하고 이와 비슷한 **더 가벼운 구성**을 찾고 있었음. 다음 과제가 CI였기에 시기적절하며, 곧 공개할 작은 라이브러리를 SourceHut에 미러링할지 고민 중임
  - stagit를 포크해 연락처 이메일과 내비게이션 바를 추가하고, CSS 변경용 ID를 넣었으며 불필요한 정보는 제거했음  
    저장소는 [git-daemon](https://git-scm.com/docs/git-daemon)으로 웹에 읽기 전용 공개하며, 전체 구성 방법은 [여기](https://mccd.space/wiki/tutorial-git-repo.shtml)에 정리해 두었음

- 이 글로 `nq`를 처음 알았지만 아마 **`systemd-run`** 을 사용할 듯함  
  거의 모든 실행기에 Nix를 쓰고 있으므로 `nix flake check` 결과를 OTLP 지표와 로그로 노출하면, CI 요구 사항을 모니터링 시스템으로 해결할 수 있을 것 같음

- 이처럼 단순한 자체 호스팅 개발 플랫폼 구성이 마음에 듦  
  CI용으로 가볍고 단순한 컨테이너 시스템인 [bubblewrap](https://github.com/containers/bubblewrap)을 쉽게 설정해 사용할 수 있음. 다만 `nq`를 쓰면 **CI 실패 시 푸시 거부**는 불가능해 보이는데 어떻게 처리하는지 궁금함
  - 스크립트를 제한하는 데 Landlock을 사용하는 [보조 도구](https://mccd.space/git/landdown/file/README.html)도 있으며, 사용법은 조금 더 단순하다고 봄  
    격리가 더 필요하면 Podman, Docker, bubblewrap을 추가할 수 있음. 테스트를 실행하는 커밋 전 훅을 두지 않는 것과 같은 이유로 CI 실패 시 푸시를 거부하지 않는데, 깨진 작업도 커밋하거나 푸시해야 할 때가 있고 푸시가 매우 느려질 수 있기 때문임. 거부가 필요하면 `nq` 없이 CI를 동기 실행해 종료 코드가 0이 아닐 때 푸시를 막으면 됨  
    또는 **main이 아닌 브랜치**는 `nq`로 실행하고 main 브랜치만 동기 실행할 수 있음

- **`landdown` 링크**가 깨진 것으로 보임
  - 집에 가면 고칠 예정이며, 올바른 주소는 https://mccd.space/git/landdown/file/README.html 임
