Files
hop.noname.company/deploy.md

203 lines
9.4 KiB
Markdown

# hop. 유그린 NAS 배포 순서
**SSH에서는 소스와 설정만 준비합니다. 시작·중지·재빌드는 NAS의 Docker 앱에서 합니다.**
접속 경로: `https://hop.noname.company → 기존 Cloudflare Tunnel → NPM(기존 8080) → NAS 내부 IP:50189 → hop.`
아래 코드 블록을 하나씩 복사하고 Enter를 누르세요. 오류가 나오면 다음 단계로 넘어가지 마세요.
## 1. SSH에서 소스 받기
NAS에서 프로젝트를 둘 상위 폴더까지 이동한 상태에서 실행합니다.
```sh
git --version
```
```sh
docker compose version
```
```sh
openssl version
```
명령이 없으면 해당 단계의 오류를 알려주세요. NAS에는 Node.js나 npm을 설치할 필요가 없습니다.
```sh
git clone https://git.sori.studio/noname.company/hop.noname.company.git hop
```
Git 로그인을 물으면 Git 서버의 로그인 아이디와 비밀번호 또는 액세스 토큰을 입력합니다. 비밀번호 입력 시 화면에 글자가 안 나오는 것은 정상입니다.
```sh
cd hop
```
```sh
git branch --show-current
```
`main`이 나오면 다음으로 넘어갑니다.
## 2. NAS 설정 만들기
```sh
sh scripts/configure-nas.sh
```
질문이 나오면 순서대로 입력합니다.
1. **NAS 내부 IPv4 주소**: NAS 설정에 표시된 실제 내부 IP 입력 → Enter. NPM도 이 IP로 연결합니다.
2. **Resend API 키**: 기존 `hello@noname.company` 발신에 사용하는 키 붙여넣기 → Enter. 입력 문자는 숨겨집니다. 메일 기능 없이 시작하려면 Enter만 누릅니다.
3. **회원가입 활성화**: 가입까지 테스트하려면 `y` → Enter. 비활성화하려면 Enter만 누릅니다. 키를 생략하면 이 질문 없이 가입이 비활성화됩니다.
`SESSION_SECRET`과 `DISCOVERY_SECRET`은 자동 생성됩니다. NAS 포트와 컨테이너 포트는 모두 **50189**를 사용합니다.
마지막에 표시된 `compose.nas.yaml` 경로를 복사해 둡니다. `.env`는 NAS에만 남고 Git에 올라가지 않습니다. 기존 `.env`가 있으면 덮어쓰지 않습니다.
## 3. Docker 앱에서 배포
1. NAS의 **Docker 앱** 열기.
2. **프로젝트 → 생성** 누르기.
3. 프로젝트 이름에 **hop** 입력.
4. 프로젝트 저장 경로는 방금 `git clone`한 **hop 폴더** 선택.
5. YAML 가져오기에서 **compose.nas.yaml** 선택. 파일 가져오기가 없으면 해당 파일 내용을 Compose 편집기에 붙여넣습니다.
6. **배포 / 빌드 후 시작** 누르기. 처음에는 이미지 빌드가 끝날 때까지 기다립니다.
7. 프로젝트의 hop 컨테이너가 **실행 중**, 상태가 **healthy**인지 확인.
버전별로 버튼 이름이 다를 수 있습니다. 생성한 YAML은 소스와 `.env`의 절대 경로를 사용합니다. 별도의 빈 폴더로 소스를 옮기지 마세요. 프로젝트 배포 방식은 [UGREEN 공식 안내](https://ai.ugreen.com/blogs/knowledge/docker-docker-compose-ugreen-nas)를 참고했습니다.
## 4. Nginx Proxy Manager 설정
기존 NPM 관리 화면에서 진행합니다.
1. **Hosts → Proxy Hosts → Add Proxy Host** 누르기. 이미 hop. 항목이 있으면 **Edit**.
2. 다음 값 입력.
| 항목 | 입력값 |
| --------------------- | -------------------------------- |
| Domain Names | `hop.noname.company` |
| Scheme | `http` |
| Forward Hostname / IP | 2단계에서 입력한 **NAS 내부 IP** |
| Forward Port | `50189` |
| Cache Assets | 끄기 |
| Websockets Support | 켜기 |
3. **Advanced**에 다음 내용 입력. 동일한 설정이 있으면 중복으로 넣지 말고 기존 값을 수정합니다.
```nginx
client_max_body_size 2048m;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
```
4. **Save** 누르기.
NPM이 Docker 컨테이너라면 Forward IP에 `127.0.0.1`을 입력하지 마세요. 여기서는 **NAS 내부 IP**를 사용합니다. 기존 Tunnel이 NPM의 8080으로 들어오는 설정은 그대로 유지합니다. NPM에 별도 인증서나 Force SSL을 추가하는 단계는 필요하지 않습니다. 공개 HTTPS는 현재 Cloudflare 경로를 사용합니다. NPM은 [공식 문서](https://nginxproxymanager.com/guide/)의 도메인별 전달 기능을 사용합니다.
## 5. Cloudflare Tunnel에 주소 연결
1. 기존 터널의 **Published application routes / Public Hostnames** 열기.
2. `hop.noname.company`가 기존 NPM으로 전달되는지 확인.
3. 주소가 없다면 `hop.noname.company` 추가.
4. Service는 **다른 서비스에서 이미 사용 중인 NPM의 8080 주소** 그대로 입력.
5. 저장.
8080을 50189로 바꾸지 않습니다. Tunnel은 NPM으로, NPM의 hop. 항목은 50189로 전달합니다.
## 6. 동작 확인
브라우저에서 다음 주소를 엽니다.
```text
https://hop.noname.company
```
1. PC에서 접속.
2. **QR로 연결**을 눌러 연결 공간 만들기.
3. 휴대폰에서 QR을 스캔하거나 다른 브라우저에서 연결 코드 입력.
4. 참여 후 QR 모달이 닫히고 상대 기기가 보이는지 확인.
5. 상대 기기 선택 → 링크 전송 → 상대에서 수락 → 링크가 열리는지 확인.
6. 작은 파일 전송 → 상대에서 수락 → 다운로드 확인.
7. 가입을 활성화했다면 **로그인 → 회원가입**에서 실제 이메일로 가입 → Resend 인증 메일 확인 → 로그인.
8. 로그인 상태로 받은 자료가 **보관함 → 받은 항목**에 표시되는지 확인.
처음 배포는 **QR·코드 연결**로 확인합니다. 주변 자동 발견은 실제 클라이언트 IP 전달과 프록시 신뢰 범위를 확인한 다음 활성화해야 합니다. 현재 설정에서는 꺼져 있습니다. 임의로 `TRUSTED_PROXY_CIDRS`에 모든 IP를 넣지 마세요.
운영 비밀번호는 **12자 이상**입니다. 개발 DB와 `1234` 테스트 계정은 NAS에 복사되지 않습니다.
**대용량 파일:** Cloudflare를 통과하는 업로드에는 요금제 제한이 있습니다. 현재 공식 안내는 Free/Pro **100MB**, Business **200MB**입니다. NPM의 `2048m` 설정으로 이 제한이 늘어나지는 않습니다. 큰 파일에서 413이 나오면 [Cloudflare 업로드 제한](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/4xx-client-error/error-413/)을 확인하세요. 현재 hop.은 파일을 작은 요청으로 나누어 업로드하지 않습니다.
## 7. 다음 버전으로 업데이트
SSH에서 같은 hop 폴더까지 이동한 다음 진행합니다.
1. Docker 앱 → **프로젝트 → hop → 중지**.
2. SSH에서 데이터 백업:
```sh
mkdir -p backups
```
```sh
chmod 700 backups
```
```sh
sudo docker volume inspect hop_hop_database hop_hop_uploads >/dev/null
```
```sh
sudo docker run --rm -v hop_hop_database:/source/database:ro -v hop_hop_uploads:/source/uploads:ro -v "$PWD/backups:/backup" alpine:3.22 sh -c 'tar -czf "/backup/hop-$(date +%Y%m%d-%H%M%S).tar.gz" -C /source database uploads'
```
```sh
cp -p .env "backups/env-$(date +%Y%m%d-%H%M%S)"
```
3. 최신 코드 받기:
```sh
git pull --ff-only origin main
```
4. 배포 YAML 다시 만들기. 기존 `.env`와 비밀값은 유지됩니다.
```sh
sh scripts/configure-nas.sh
```
5. Docker 앱 → **프로젝트 → hop → 편집**.
6. 최신 **compose.nas.yaml**을 다시 불러오거나 편집기에 붙여넣기 → 저장.
7. **재빌드 / 이미지 다시 빌드** 선택 → **시작 / 재배포**. 단순 재시작만 하면 바뀐 코드가 이미지에 반영되지 않습니다.
8. `healthy` 확인 → 6단계의 링크·파일 전송 확인.
프로젝트를 삭제하거나 `docker compose down -v`를 실행하지 마세요. DB·파일은 `hop_hop_database`, `hop_hop_uploads` 볼륨에 남습니다. 업데이트 실패 시 중지하고 오류를 확인하세요. DB 마이그레이션이 적용됐을 수 있으므로 코드만 되돌리지 말고 같은 시점의 DB·업로드·환경파일 백업으로 함께 복구해야 합니다.
## 8. 시작 / 중지 / 로그
| 할 일 | 누를 위치 |
| -------------- | ----------------------------------------------------------------------- |
| 시작 | Docker → 프로젝트 → hop → 시작 |
| 중지 | Docker → 프로젝트 → hop → 중지 |
| 설정 변경 적용 | `.env` 수정 → YAML 재생성 → 프로젝트 편집 → YAML 다시 불러오기 → 재배포 |
| 오류 확인 | Docker → 컨테이너 → hop 컨테이너 → 로그 |
SSH에서 실제 설정 중 비밀값 없이 주소·포트만 확인하려면:
```sh
grep -E '^(APP_URL|HOP_BIND_IP|HOP_HOST_PORT|HOP_CONTAINER_PORT)=' .env
```
NAS에서 앱의 상태만 확인하려면:
```sh
HOP_NAS_IP=$(sed -n 's/^HOP_BIND_IP=//p' .env)
curl -fsS "http://${HOP_NAS_IP}:50189/api/health"
```
HTTP 주소는 상태 확인에만 씁니다. 실제 접속·QR·로그인은 `https://hop.noname.company`를 사용하세요.
환경파일을 YAML에 포함하지 않는 생성 방식은 [Docker Compose 공식 문서](https://docs.docker.com/reference/cli/docker/compose/config/)의 `--no-env-resolution`을 사용합니다. `.env`, 생성된 `compose.nas.yaml`, `backups`는 Git과 Docker 빌드에서 제외됩니다.