저장소를 걸어두면 push가 배포입니다Register a repo once, then just push
앱의 계약은 하나입니다 — 저장소 루트에 Dockerfile이 있고, 컨테이너가 포트 하나로 HTTP를 서빙하면 됩니다.
There is one contract: a Dockerfile at the repo root, and a container that serves HTTP on a single port.
- ■웹훅 주소와 시크릿을 발급Webhook URL and secret, generated — GitHub 설정에 붙여넣기만 하면 됩니다.paste them into GitHub and you're done.
- ■배포 이력과 롤백History and rollback — 커밋·시각·결과가 남고, 예전 커밋으로 다시 빌드합니다.every commit, time and result is kept; rebuild from an earlier one.
- ■이미지도 그대로Images too — Docker Hub·GHCR 이미지를 pull해서 바로 올립니다.pull from Docker Hub or GHCR and run it as is.
리버스 프록시가 들어 있습니다The reverse proxy is already inside
앱에 도메인을 적으면 프록시에 등록됩니다. 앱끼리는 컨테이너 이름으로 직접 연결되므로 호스트 포트를 열 필요가 없습니다. Type a domain into an app and it is routed. Apps reach each other by container name, so no host ports need opening.
- ■Let's Encrypt — HTTP-01 또는 Cloudflare DNS-01. 와일드카드도 되고 갱신은 매일 확인합니다. HTTP-01 or Cloudflare DNS-01, wildcards included, renewal checked daily.
- ■인증서가 생기면 HTTPS 강제HTTPS enforced on arrival — 80은 301로 넘기고 HSTS를 켭니다. 인증서를 지우면 되돌아가 잠기지 않습니다. port 80 redirects and HSTS turns on; remove the certificate and it reverts, so you never lock yourself out.
- ■외부에 여는 포트는 80·443뿐Only 80 and 443 face the world — 관리 화면도 프록시 뒤에 있습니다.the admin UI sits behind the proxy too.
앱이 죽으면 대시보드가 아니라 당신에게 알립니다When an app dies, you hear about it
상태가 바뀌는 순간에만 알립니다. 죽으면 한 번, 돌아오면 한 번. 직접 세워둔 앱은 장애로 보지 않습니다. Alerts fire on change, not on a timer: one when an app goes down, one when it returns. An app you stopped on purpose is never an incident.
- ■호스트와 앱의 지표Host and app metrics — CPU·로드·메모리·디스크와 앱별 사용량을 5초마다 갱신합니다. CPU, load, memory, free disk and per-app usage, refreshed every five seconds.
- ■받는 곳은 내가 정함Delivered where you want — 웹훅으로 JSON POST. Discord·Slack 주소도 그대로 씁니다. JSON over a webhook — a Discord or Slack URL works as is.
- ■서명과 발송 이력Signed, and logged — 시크릿을 넣으면 HMAC 서명이 붙고, 보낸 결과가 남습니다. add a secret for an HMAC signature; every delivery is recorded.
설치Install
Docker가 있는 리눅스 서버에서 두 줄이면 됩니다. 관리 화면은 첫 접속에서 계정을 만듭니다. Two commands on any Linux box with Docker. The admin UI asks you to create an account on first visit.
$ git clone https://github.com/KangminNa/shelf && cd shelf
$ docker compose up -d --build
# 도메인을 .env 에 적으면 부팅할 때 프록시에 자동 등록됩니다put your domain in .env and it is routed at boot
# ADMIN_DOMAIN=shelf.example.com
# ACME_EMAIL=you@example.com
아직 못 하는 것What it can't do yet
쓰기 전에 아는 편이 낫습니다. 여기 없는 문제는 대체로 해결돼 있습니다. Better to know before you commit. Problems not listed here are generally handled.
컨테이너를 교체하므로 몇 초 끊깁니다. 헬스체크 후 전환하는 방식은 아직입니다. The container is replaced, so there are a few seconds of downtime. Health-checked cutover is not built yet.
Git 토큰과 웹훅 시크릿은 data/에 평문으로 있습니다.
Git tokens and webhook secrets sit in data/ in plain text.
한 대를 잘 쓰는 도구입니다. 클러스터링은 목표가 아닙니다. A tool for running one machine well. Clustering is an explicit non-goal.
배포가 끝난 뒤 전체 로그를 봅니다. You read the full log once the deploy finishes.
DNS-01은 Cloudflare만 지원합니다. 다른 곳은 HTTP-01을 쓰면 됩니다. DNS-01 works with Cloudflare only; elsewhere, use HTTP-01.
관리자 계정은 Docker 소켓을 쥐고 있어 설계상 root와 동급입니다. The admin account holds the Docker socket, so it is root-equivalent by design.