# Git 배포

> 서버를 GitHub, GitLab, Gitea 또는 Forgejo 저장소에 연결하고, 모든 push, 릴리스 또는 태그마다 자동으로 배포하세요 — 보호된 경로, 재시작, CI 검사, 원클릭 롤백까지 지원해요.

Portal의 **Git Deploy** 탭은 서버를 **GitHub**, **GitLab**, **Gitea** 또는 **Forgejo**의 Git 저장소에 연결해요. 저장소의 파일은 서버로 자동 복사돼요 — push할 때마다, 릴리스를 게시할 때마다, 태그를 push할 때마다, 또는 버튼을 한 번 눌렀을 때 복사돼요. 원하면 배포 전에 서버를 깔끔하게 중지했다가 배포 후 다시 시작할 수도 있어요.

한마디로: 코드를 push하면 몇 초 뒤 서버에서 실행돼요. 더 이상 SFTP로 업로드할 필요도, 파일 관리자에서 ZIP 파일의 압축을 풀 필요도, 재시작을 잊을 걱정도 없어요.

## 배울 내용

- Daki Git Deploy GitHub 앱을 사용하거나 액세스 토큰을 사용해 저장소를 연결하는 방법
- 배포가 언제 실행되는지, 그리고 직접 배포를 실행하는 방법
- 보호된 경로로 월드, 데이터베이스와 `.env` 파일을 안전하게 지키는 방법
- 재시작, 배포 기록, 롤백과 저장소의 상태 표시가 어떻게 동작하는지
- 팀원에게 올바른 권한을 주는 방법

---

## 누가 사용하나요?

- **Discord 봇과 Node.js, Python, Java 앱 개발자**: 코드가 이미 GitHub나 GitLab에 있는 경우.
- **Minecraft 네트워크와 게임 서버 팀**: 플러그인, 설정 파일이나 데이터팩을 저장소에서 관리하고 변경 사항을 추적 가능한 방식으로 반영하고 싶은 경우.
- **팀**: 여러 사람이 저장소에서 함께 작업하고, 서버는 항상 최신 상태를 유지하며, 서브유저 권한으로 누가 배포할 수 있는지 정확히 정할 수 있어요.
- **릴리스 기반 프로젝트**: 작업 중인 모든 변경 사항이 아니라, 게시된 버전만 서버에 올라가요(예: 릴리스의 완성된 `.jar` 파일).

---

## 시작하기 전에

- **Git Deploy** 탭이 보이는 Portal의 서버. 서버 탐색 메뉴의 **Essentials** 아래에 있으며, 기본적으로 **Files** 바로 다음에 있어요.
- GitHub(github.com), GitLab(gitlab.com 또는 직접 운영하는 인스턴스, `group/subgroup/project` 같은 하위 그룹 포함), Gitea 또는 Forgejo(예: Codeberg 또는 직접 운영하는 인스턴스)의 저장소. 공개 저장소와 비공개 저장소 모두 사용할 수 있어요.

> **참고:** Daki는 서버 유형(egg)별로 이 탭을 표시할지 정해요. **Git Deploy**가 보이지 않는다면, 서버 유형에서 이 기능이 활성화되어 있지 않은 거예요.

> **정보:** 이 가이드는 Git Deploy 탭의 영어 라벨을 사용해요. 이 탭은 19개 언어로 제공되며, Portal에서 선택한 언어를 따라요 — 버튼의 위치는 모든 언어에서 같아요.

---

## GitHub로 빠르게 시작하기 (권장)

가장 빠른 방법은 Daki Hosting의 공식 GitHub 앱인 **Daki Git Deploy**로 연결하는 거예요. GitHub에 로그인하고 저장소를 선택하면 돼요 — **토큰도 웹훅도 필요 없어요**.

**단계 1: Git Deploy 탭 열기**

Portal에서 서버를 열고 **Git Deploy** 탭으로 이동하세요. **Git service**에서 **GitHub**를 선택하세요.

**단계 2: GitHub로 연결하기**

**GitHub access** 상자에서 **Connect with GitHub**를 클릭하세요. GitHub에 로그인하고 앱을 승인하세요.

처음 연결할 때는 GitHub가 바로 앱이 액세스할 수 있는 저장소를 고르는 화면으로 넘어가요(**All repositories** 또는 선택한 저장소만) — 두 번이 아니라 한 번의 과정으로 끝나요. 그 뒤에는 Portal로 돌아오며, **GitHub access** 상자에 **Connected via Daki Git Deploy as**와 함께 GitHub 이름이 표시돼요. **Webhook** 상자에는 설정할 것이 없다는 안내가 나와요: push와 릴리스는 앱을 통해 자동으로 전달돼요.

**단계 3: 저장소와 브랜치 선택하기**

**Choose from my repositories**를 클릭하고 저장소를 고르세요 — 또는 웹 주소나 클론 URL을 붙여넣거나 경로를 입력하세요. **Load branches**를 클릭하고 배포할 브랜치를 선택하세요. 브랜치를 비워 두면 저장소의 기본 브랜치를 사용해요.

**단계 4: 언제, 어떻게 배포할지 선택하기**

**When to deploy** 아래에서 모드를 고르세요(예: **Every push**). 그다음 대상 폴더, [보호된 경로](#protected-paths)와 [재시작 동작](#restart-behavior)을 설정하세요.

**단계 5: 저장하기**

하단 바의 **Save settings**를 클릭하세요. 이제 끝이에요: 탭 상단에 **Automatic deploys on**이 표시되고, 다음 push부터 자동으로 배포돼요. 바로 배포하려면 오른쪽 위의 **Deploy now**를 클릭하세요.

- **다른 저장소 허용하기:** **Choose repositories on GitHub**를 누르면 GitHub에서 저장소 선택 화면이 다시 열려요. 거기서 **Daki Git Deploy**가 액세스할 수 있는 저장소를 고를 수 있어요.
- **연결 해제하기:** **Disconnect**를 클릭하세요. 그러면 서버는 더 이상 비공개 저장소에서 배포하지 않아요.

> **팁:** 무언가를 갱신할 필요는 전혀 없어요. 배포할 때마다 Portal이 GitHub에서 새로운 단기 키(1시간 동안 유효)를 가져와요. 이 키는 서버의 저장소 하나에만 사용되며, 모든 과정은 백그라운드에서 이루어져요.

---

## 액세스 토큰으로 빠르게 시작하기

**GitLab**, **Gitea**, **Forgejo**의 경우에, 그리고 GitHub를 선호한다면 GitHub도 개인 액세스 토큰을 저장하면 돼요. 공개 저장소는 토큰 없이도 작동해요.

**단계 1: Git 서비스 선택하기**

서버를 열고 → **Git Deploy**로 이동해 **Git service**를 선택하세요. 직접 운영하는 GitLab, Gitea 또는 Forgejo라면 서버 URL을 입력하세요(예: `https://codeberg.org` 또는 `https://git.example.com`). gitlab.com을 사용한다면 비워 두세요.

**단계 2: 저장소 입력하기**

저장소를 경로(`owner/name`)로 입력하거나, 웹 주소 또는 클론 URL을 그대로 붙여넣으세요. **공개** 저장소라면 이것만으로 충분해요 — 토큰이 없으면 액세스 박스에 **No token – public repositories only**가 표시돼요.

**단계 3: 비공개 저장소용 토큰 저장하기**

GitHub를 사용한다면 먼저 **GitHub access** 박스에서 **Use an own access token instead**를 클릭하세요. 그다음 Git 제공자에서 토큰을 만드세요 — Portal의 **Create a token on …** 링크를 누르면 올바른 페이지로 바로 이동해요 — 그리고 **Personal access token**에 저장하세요. Portal이 토큰을 즉시 확인해요. 필요한 권한은 [토큰 권한](#token-permissions)을 참고하세요.

**단계 4: 설정을 고르고 저장하기**

배포 시점, 대상 폴더, 보호된 경로와 재시작 동작을 고른 다음 **Save settings**를 클릭하세요.

**단계 5: 웹훅 추가하기**

**Webhook** 상자에 **Payload URL**과 **Secret**이 표시되며, 각각 복사 버튼이 있어요. [웹훅 설정하기](#set-up-the-webhook)에 설명된 대로 이 값을 저장소에 추가하세요. 상자 아래의 **Last delivery**에서 웹훅이 도착하는지 확인할 수 있어요.

**단계 6: 자동 배포 켜기**

**Automatic deploys active**를 켜세요.

### 토큰 권한

| 제공자 | 토큰 유형 | 배포에 필요한 권한 | 저장소 상태 표시에도 필요한 권한 |
| :--- | :--- | :--- | :--- |
| GitHub | 이 저장소만 대상으로 하는 세분화된 토큰 | *Contents: Read-only* (**Wait for CI checks**를 쓰면 *Actions: Read-only*도 필요) | *Commit statuses*와 *Deployments*: *Read and write* |
| GitLab | 개인, 프로젝트 또는 그룹 액세스 토큰 | `read_api` + `read_repository` | `read_api` 대신 `api`, 역할은 Developer |
| Gitea / Forgejo | Settings → Applications | `repository: Read`, `user: Read` | `repository: Read and Write` |

상태 표시를 위한 쓰기 권한만 빠져 있다면, 서버는 그래도 배포돼요 — 배포 로그에 참고 메시지가 표시돼요.

### 웹훅 설정하기

**GitHub**

저장소에서 **Settings → Webhooks → Add webhook**으로 이동하세요:

1. Portal의 **Payload URL**과 **Secret**을 붙여넣으세요.
2. 콘텐츠 유형을 `application/json`으로 설정하세요.
3. 이벤트에서 **Just the push event**를 선택하세요. 릴리스 모드에서는 대신 **Releases**를 선택하세요.

**GitLab**

프로젝트에서 **Settings → Webhooks**로 이동하세요:

1. **Payload URL**을 URL로, **Secret**을 **Secret token**에 붙여넣으세요.
2. 트리거에서 **Push events**를 선택하세요. 태그 모드에서는 **Tag push events**를, 릴리스 모드에서는 **Releases events**를 선택하세요.

**Gitea / Forgejo**

저장소에서 **Settings → Webhooks → Add webhook**으로 이동해 Gitea 또는 Forgejo를 선택하세요:

1. **Payload URL**을 붙여넣고, 콘텐츠 유형을 `application/json`으로 설정한 뒤 **Secret**을 입력하세요.
2. **Push events**를 선택하세요. 릴리스 모드에서는 **Custom events → Release**를 선택하세요.

> **팁:** Git 제공자가 Portal에 접근할 수 없나요, 예를 들어 Gitea 인스턴스가 가정 내 네트워크에서 실행되고 있나요? 그렇다면 대신 **Also check … for updates** 아래에서 주기를 선택하세요(예: **Also check Gitea for updates**). 첫 번째 확인에서 현재 상태가 한 번 배포돼요.

---

## 배포가 실행되는 시점

**When to deploy** 아래에서 네 가지 모드 중 하나를 선택하세요:

| 모드 | 배포되는 것 |
| :--- | :--- |
| **Manual** | 누군가 **Deploy now**를 클릭할 때만. |
| **Every push** | 선택한 브랜치에 push될 때마다. |
| **Releases** | 릴리스가 게시될 때만. 릴리스의 **source code** 또는 **release file**(예: `*.jar`)을 배포할 수 있어요 — 고정된 이름(예: `server.jar`)으로 저장할 수 있고, `.zip` 파일이라면 압축을 풀 수도 있어요. 프리릴리스는 포함하거나 제외할 수 있어요. |
| **Tags** | `v*` 같은 패턴과 일치하는 태그가 push될 때. |

### 트리거

- **웹훅:** Git 제공자가 변경 사항을 즉시 알려주고, 배포는 몇 초 안에 시작돼요. GitHub 앱을 사용하면 직접 만든 웹훅 없이도 자동으로 이루어져요.
- **업데이트 확인(폴링):** 선택 사항이며, Git 제공자가 Portal에 접근할 수 없는 경우에 사용해요. 주기는 5분부터 1일까지 설정할 수 있어요.
- **Deploy now:** 언제든지 버튼 한 번으로 실행할 수 있어요. 릴리스 모드에서는 특정 릴리스를 선택할 수 있어요.
- **push 건너뛰기:** 커밋 메시지에 `[skip deploy]`를 넣으면 그 push는 배포되지 않아요. `[deploy skip]`과 `[no deploy]`도 작동해요.

### CI 검사 기다리기

**Wait for CI checks**를 켜면(**Every push** 모드에서만 가능), CI가 성공(초록색)해야만 커밋이 배포돼요 — GitHub Actions, GitLab CI, Gitea/Forgejo Actions를 지원해요. CI가 실패하면 배포는 건너뛰어요.

---

## 모든 설정 설명

| 섹션 | 설정 | 하는 일 |
| :--- | :--- | :--- |
| Repository | **Git service** | GitHub, GitLab, Gitea 또는 Forgejo |
| Repository | **Server URL** | 직접 운영하는 인스턴스에만 해당; 인터넷에서 접근할 수 있어야 해요 |
| Repository | **Repository** | `owner/name` 또는 URL; **Choose from my repositories**를 누르면 목록이 나와요 |
| Repository | **Branch** | 비우면 기본 브랜치; **Load branches**를 누르면 목록이 나와요 |
| When to deploy | **Manual** / **Every push** / **Releases** / **Tags** | [배포가 실행되는 시점](#when-a-deploy-runs) 참고 |
| When to deploy | **Wait for CI checks** | **Every push**에서만 가능 |
| When to deploy | **Include pre-releases**, **What to deploy** (**Source code** / **Release file**), **Save as**, **Extract .zip files instead of uploading them** | **Releases**에서만 가능 |
| When to deploy | **Tag pattern** | **Tags**에서만 가능, 예: `v*`; 비우면 모든 태그 |
| When to deploy | **Also check … for updates** (Git 서비스 이름이 붙어요, 예: **Also check GitHub for updates**) | 폴링: **Never (webhook only)**, 5/10/15/30분, 1/3/6/12/24시간 |
| When to deploy | **Automatic deploys active** | 끄면 웹훅과 폴링이 멈춰요; **Deploy now**는 계속 작동해요 |
| When to deploy | **Show deploys in the repository** | 커밋의 상태 표시, [저장소의 상태](#status-in-your-repository) 참고 |
| Files | **Folder in the repository** | 하위 폴더만 배포, 예: `dist`; 비우면 전체 |
| Files | **Target folder on the server** | 파일이 저장될 위치; `/`는 서버의 기본 폴더 |
| Files | **Protected paths** | 한 줄에 규칙 하나, [보호된 경로](#protected-paths) 참고 |
| Files | **Remove files that were deleted from the repository** | 선택 사항인 정리 기능, 아래 참고 |
| Restart | **Restart if running** / **Always start** / **Do not restart** | [재시작 동작](#restart-behavior) 참고 |
| Restart | **If the server does not stop** | 즉시 강제 종료하거나, 5초, 10초(기본값: **Kill after 10 seconds**), 15초, 30초, 1분, 2분 또는 5분 후에 강제 종료 |

설정은 **Save settings**를 클릭해야만 적용돼요. 저장하지 않은 변경 사항이 있으면 하단에 **Discard**와 **Save settings**가 있는 바가 표시되고, **Deploy now**는 잠겨요.

**Remove files that were deleted from the repository**는 이전 배포가 직접 기록한 파일만 제거해요 — 보호된 경로나 직접 만든 파일은 절대 제거하지 않아요. 빈 폴더는 그대로 남아요.

---

## 보호된 경로

**Protected paths**에 있는 파일과 폴더는 배포로 **절대 덮어쓰이거나 삭제되지 않아요**. 아직 없다면 한 번 생성돼요. 게임 월드, 데이터베이스와 비밀번호를 보호하기에 딱 좋아요.

규칙은 대상 폴더를 기준으로 한 줄에 하나씩 작성하세요. 빈 줄과 `#`로 시작하는 줄은 무시돼요. `*`는 `/`를 넘어서 일치하지 않아요.

| 규칙 | 보호 대상 |
| :--- | :--- |
| `world/` | 깊이에 관계없이 `world`라는 이름의 모든 폴더 |
| `/world/` | 대상 폴더 바로 아래의 `world`만 |
| `*.db` | 어디에 있든 `.db`로 끝나는 모든 파일 |
| `.env` | 어디에 있든 `.env`라는 이름의 모든 파일 |
| `/config.yml` | 대상 폴더 바로 아래의 `config.yml`만 |
| `plugins/*/config.yml` | `plugins`의 모든 직계 하위 폴더에 있는 `config.yml` |

자주 쓰는 예시:

**Minecraft**

```

world/

world_nether/

world_the_end/

plugins/*/config.yml

whitelist.json

ops.json

banned-*.json

```

**Discord 봇 / Node.js**

```

.env

*.db

*.sqlite

node_modules/

data/

```

**Python**

```

.env

*.db

venv/

```

---

## 재시작 동작

| 옵션 | 일어나는 일 |
| :--- | :--- |
| **Restart if running** | 파일을 쓰기 전에 서버를 중지하고, 이후 다시 시작해요. 꺼져 있는 서버는 꺼진 상태로 남아요. |
| **Always start** | 위와 같으며, 꺼져 있던 서버도 배포 후 시작돼요. |
| **Do not restart** | 서버가 계속 실행되는 동안 파일이 교체돼요. |

**If the server does not stop:** 일부 프로그램, 특히 Node.js 앱은 중지 신호를 무시해요. 이때는 배포가 멈추지 않도록, 선택한 시간이 지나면 서버를 강제로 종료해요(즉시, 5초부터 5분까지, 기본값은 **Kill after 10 seconds**). 즉시 강제 종료하면 가장 빠르지만, 서버가 저장할 시간을 주지 않아요.

> **참고:** 두 가지 안전장치가 있어요: 서버가 전혀 꺼지지 않으면 **파일은 하나도 변경되지 않아요**. 서버를 중지한 뒤 배포가 실패하면, 서버를 **다시 시작해요**.

---

## 배포 중에 일어나는 일

1. 트리거(push, 릴리스, 태그, 업데이트 확인 또는 버튼)가 배포를 만들어요.
2. **Wait for CI checks**가 켜져 있으면 CI가 성공(초록색)할 때까지 기다려요(**Waiting**).
3. **Portal**이 Git 제공자에서 아카이브를 다운로드해요. 인증 정보는 Portal을 벗어나지 않으며, 서버에 전달되지 않아요.
4. 아카이브를 준비해요: 선택한 폴더만 남기고, 보호된 경로는 걸러내고, 심볼릭 링크 같은 안전하지 않은 내용은 버려요.
5. 설정에 따라 서버를 중지해요(필요하면 선택한 시간 뒤 강제 종료해요).
6. 파일을 대상 폴더에 써요. 필요하다면 삭제된 파일도 제거해요.
7. 설정에 따라 서버를 다시 시작해요.
8. 결과와 전체 로그가 기록에 나타나요 — 그리고 활성화되어 있다면 커밋의 상태로도 나타나요.

배포는 보통 **10–40초**가 걸리고, 여기에 서버가 중지되는 데 걸리는 시간이 더해져요.

---

## 기록, 로그 & 롤백

탭 하단의 **Deployments** 목록에는 모든 배포가 상태, 브랜치, 커밋(예: `main @ 75cd0a1`), 번호, 트리거, 배포를 시작한 사람, 시간과 커밋 메시지와 함께 표시돼요. 탭 상단에는 서버가 마지막으로 배포된 시간이 표시돼요.

| 상태 | 의미 |
| :--- | :--- |
| **Waiting** | CI 검사를 기다리는 중 |
| **Scheduled** | 대기열에 들어가 곧 시작돼요 |
| **Running** | 배포가 진행 중이에요 |
| **Deployed** | 성공적으로 완료됨 |
| **Failed** | 문제가 발생함 — 로그에서 원인을 확인하세요 |
| **Skipped** | 배포되지 않음, 예: CI가 실패했거나 커밋에 `[skip deploy]`가 있는 경우 |
| **Cancelled** | 시작 전에 취소됨 |

- **로그:** 모든 배포에는 실행 중에 실시간으로 업데이트되는 로그가 있어요. **Hide log**를 누르면 다시 닫혀요.
- **원클릭 롤백:** 이전 배포에서 **Deploy again**을 클릭하면 그 상태를 한 번 더 배포해요.
- **취소:** 대기 중이거나 예약된 배포는 취소할 수 있어요.

여러 서버가 동시에 배포할 수 있지만, 각 서버는 한 번에 하나의 배포만 실행해요. 새 트리거는 아직 대기 중인 이전 배포를 대체해요.

---

## 저장소의 상태

**Show deploys in the repository**를 켜면, 커밋에 **Daki Hosting / *서버 이름*** 상태가 표시돼요: 배포가 진행되는 동안은 노란색, 이후 초록색 체크 또는 빨간색 X가 나타나고, Git Deploy 탭으로 연결되는 링크가 함께 있어요.

- GitHub에서는 배포가 **Deployments** 아래에도 나타나며, 환경 이름은 서버 이름이에요.
- GitHub 앱을 사용하면 상태는 **Daki Git Deploy**가 작성하며 그 로고가 표시돼요 — 따로 설정할 것은 없어요. 토큰을 사용하면 토큰 계정의 프로필 사진이 표시되며, 이때 토큰에는 쓰기 권한이 필요해요([토큰 권한](#token-permissions) 참고).
- 서버별로 끌 수 있어요. 공개되는 것은 상태와 링크뿐이에요 — 로그나 오류 세부 정보는 공개되지 않아요.

---

## 팀과 서브유저 권한

[서브유저](https://daki.cc/ko/wiki/guides/subusers)는 자신만의 권한 그룹 **Git Deploy**를 받아요:

| 권한 | 허용하는 것 |
| :--- | :--- |
| **view** (`github.read`) | 설정, 웹훅 주소, 로그가 포함된 기록 보기 |
| **deploy** (`github.deploy`) | **Deploy now**, **Deploy again**과 배포 취소 |
| **change settings** (`github.update`) | 저장소, 액세스, 웹훅과 모든 설정 |

서브유저는 기본적으로 Git Deploy 액세스 권한이 **없어요** — 누가 어떤 권한을 가질지는 직접 정하세요. 서버 소유자는 언제나 모든 작업을 할 수 있어요.

---

## 보안

- 토큰과 시크릿은 **암호화되어** 저장되며, **브라우저로 절대 전송되지 않아요**.
- GitHub 앱을 사용하면 배포에 쓰이는 장기 토큰이 아예 없어요: 모든 배포는 **서버의 저장소에만** 전달되는 단기 키(1시간)를 사용해요.
- 어떤 저장소를 연결할 수 있는지는 본인의 GitHub 액세스 권한이 결정해요. 다른 사람의 저장소를 서버로 가져올 수는 없어요.
- 웹훅은 서버마다 따로 있는 시크릿으로 **서명**돼요. 잘못된 시크릿이나 다른 저장소에서 온 요청은 거부돼요.
- 저장소를 변경할 수 있는 사람은 토큰을 저장한 사람뿐이므로, 서브유저가 소유자의 토큰으로 다른 비공개 저장소를 가져올 수 없어요.
- Git 서비스나 서버 URL을 변경하면, 저장할 때 저장된 토큰이 자동으로 삭제돼요.
- 보호된 경로는 절대 덮어쓰이지 않으며, **Remove files that were deleted from the repository**는 Git Deploy가 직접 쓴 것만 삭제해요.
- 저장소의 공개 상태에는 로그나 오류 세부 정보가 포함되지 않아요.

---

## 알려진 제한 사항

- 서버당 저장소 하나와 액세스 권한 하나만 사용할 수 있어요.
- 각 서버는 한 번에 하나의 배포만 실행해요.
- 저장소의 상태는 배포가 실제로 시작된 후에만 나타나며, CI를 기다리는 동안에는 나타나지 않아요.
- 릴리스 파일은 `.zip` 파일인 경우에만 압축이 풀려요. `.tar.gz`는 파일 그대로 업로드돼요.
- **Remove files that were deleted from the repository**를 사용한 후에도 빈 폴더는 그대로 남아요.
- 저장소의 심볼릭 링크는 배포되지 않아요.
- GitLab에는 프리릴리스가 없어요; 날짜가 미래인 릴리스는 프리릴리스로 간주돼요.
- GitLab: 프로젝트에 업로드된 릴리스 파일(`/uploads/…`)은 비공개 프로젝트에서 토큰으로 다운로드할 수 없어요; 패키지 레지스트리 링크는 작동해요.
- **Connect with GitHub**는 GitHub에서만 사용할 수 있어요; GitLab, Gitea, Forgejo는 토큰을 사용해요.

---

## 자주 묻는 질문 & 문제 해결

**토큰을 정기적으로 갱신해야 하나요?**

GitHub 앱을 사용하면 그럴 필요가 없어요: Portal이 배포마다 새 키를 자동으로 가져와요. 직접 만든 토큰은 Git 제공자에서 생성할 때 설정한 기간 동안 유효해요. 만료되면 새 토큰을 저장하기만 하면 돼요.

**저장소가 목록에 없어요 (GitHub 앱)**

**Choose repositories on GitHub**를 클릭하고 앱이 해당 저장소에 액세스하도록 허용하세요.

**배포가 Scheduled 상태에 머물러 있어요**

잠시 기다려 주세요. 몇 분 넘게 계속 그대로라면 [지원팀에 문의](https://daki.cc/ko/wiki/guides/support)해 주세요.

**웹훅이 도착하지 않거나 GitHub에 오류 401이 표시돼요**

시크릿이 일치하지 않아요. Portal에서 시크릿을 복사해 웹훅에 다시 입력하세요. **New secret**을 누르면 새 시크릿이 만들어져요 — 그렇다면 Git 제공자에서도 함께 변경하세요.

**배포가 왜 건너뛰어졌나요?**

가능한 이유: CI 검사가 실패했거나, 커밋 메시지에 `[skip deploy]`가 있거나, 대기 중이던 배포를 더 새로운 트리거가 대체했어요. 이유는 배포 행에 표시돼요.

**커밋에 상태가 표시되지 않아요**

**Show deploys in the repository**가 켜져 있어야 해요. 토큰을 사용하는 경우, 토큰에도 쓰기 권한이 있어야 해요([토큰 권한](#token-permissions) 참고) — 배포 로그에 이유가 표시돼요.

**배포가 “The node rejected the request”와 함께 실패해요**

서버 유형이 특정 파일을 허용하지 않거나, 디스크가 가득 찼어요. 로그에 자세한 내용이 나와요.

**직접 운영하는 Gitea 인스턴스의 URL이 거부돼요**

직접 운영하는 인스턴스는 인터넷에서 접근할 수 있어야 해요. `192.168.x.x` 같은 가정 내 네트워크 주소는 작동하지 않아요.

**롤백은 어떻게 하나요?**

기록에서 돌아가고 싶은 이전 배포의 **Deploy again**을 클릭하세요.

**게임 월드나 데이터베이스가 덮어쓰이나요?**

**Protected paths**에 등록되어 있다면(예: `world/` 또는 `*.db`) 그렇지 않아요.

**팀원 중 누가 배포할 수 있나요?**

서버의 서브유저 설정에서 **Git Deploy** 그룹의 **deploy** 권한이 있는 사람만 할 수 있어요. 서버 소유자는 언제나 모든 작업을 할 수 있어요.

---

## 다음 단계

- [서브유저](https://daki.cc/ko/wiki/guides/subusers) — 팀에 액세스 권한을 주고 누가 배포할 수 있는지 정하세요.
- [환경 변수](https://daki.cc/ko/wiki/guides/environment-variables) — 토큰과 비밀번호를 저장소 밖에 두세요.
- [시작 설정](https://daki.cc/ko/wiki/guides/startup-settings) — 배포된 코드가 실행될 시작 명령을 설정하세요.
- [백업](https://daki.cc/ko/wiki/guides/backups) — 서버의 자동 백업을 Google Drive에 저장하세요.

---
Source: https://daki.cc/ko/wiki/guides/git-deploy
