# 리버스 프록시와 HTTPS

> 포트 3000 앞에 nginx나 Caddy를 두어 셀프 호스팅 Nodaro를 내 도메인에서 HTTPS로 제공하고, PUBLIC_URL과 CORS_ORIGIN을 설정한 다음 앱을 재시작하세요.

Source: https://nodaro.ai/ko/docs/self-hosting/reverse-proxy

**리버스 프록시**를 쓰면 셀프 호스팅 Nodaro를 HTTPS가 적용된 실제 도메인에서 제공할 수 있습니다. Nodaro 컨테이너는 이미 포트 `3000`에서 웹 서버 Caddy를 실행하므로, 그 포트 앞에 TLS를 종료하는 프록시 하나를 두고 Nodaro에 공개 주소를 알려 주면 됩니다. nginx와 Caddy 모두 쓸 수 있습니다.

## 포트 3000이 제공하는 것
컨테이너 안의 웹 서버는 모든 것을 하나의 출처에 둡니다.

| 경로 | 응답하는 것 |
| --- | --- |
| `/` | 정적 파일로 제공되는 편집기와 앱 |
| `/v1/*` | 컨테이너 안의 포트 `9000`에서 수신하는 API |
| `/storage/*` | 번들된 MinIO의 미디어 |
| `/supabase/*` | 번들된 로그인과 데이터 API |
| `/config.js` | 앱이 시작되기 전에 브라우저가 읽는 런타임 설정 |

프록시는 모든 요청을 포트 `3000`으로 전달하기만 하면 됩니다.

## 방법 A: nginx
이미 nginx나 다른 프록시를 쓰고 있다면 이 방법을 쓰세요.

```nginx
server {
listen 443 ssl http2;
server_name nodaro.example.com;
ssl_certificate     /etc/letsencrypt/live/nodaro.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nodaro.example.com/privkey.pem;

client_max_body_size 100M;
proxy_buffering off;          # important for SSE

location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```

- `client_max_body_size 100M`은 업로드가 통과하게 합니다.
- `proxy_buffering off`는 Server-Sent Events가 계속 흐르게 합니다. Nodaro는 이것으로 텍스트 출력과 실행 진행 상황을 스트리밍합니다.

## 방법 B: 호스트의 Caddy
Caddy는 Let's Encrypt 인증서를 자동으로 받아 줍니다.

```text
nodaro.example.com {
reverse_proxy 127.0.0.1:3000 {
flush_interval -1
}
}
```

포트 `80`과 `443`을 열고, 도메인의 `A` 또는 `AAAA` 레코드가 호스트를 가리키게 하세요. `flush_interval -1`은 Server-Sent Events가 계속 흐르게 합니다.

## Nodaro에 공개 주소 알리기
어느 방법을 쓰든 그다음 `.env`에 다음 값을 설정하세요.

```bash
PUBLIC_URL=https://nodaro.example.com
CORS_ORIGIN=https://nodaro.example.com
# On the bundled MinIO, serve the media from the same domain:
R2_PUBLIC_URL=https://nodaro.example.com/storage/nodaro-assets
```

그런 다음 적용하세요.

```bash
docker compose -f docker-compose.community.yml up -d
```

다시 빌드할 필요는 없습니다. 컨테이너는 부팅할 때 공개 URL, 브라우저의 로그인 주소, anon 키를 `/config.js`에 쓰고, 브라우저는 앱이 시작되기 전에 이 파일을 읽습니다.

`PUBLIC_URL`은 모든 곳에서 쓰이는 설치의 주소입니다. 로그인과 OAuth 콜백, 미디어 URL, CORS 검사에 쓰입니다. `http://localhost:3000`과 `PUBLIC_URL`은 항상 브라우저 출처로 허용됩니다.

## 여러 호스트 이름으로 제공
- **추가 출처.** `CORS_ORIGIN`에 쉼표로 구분해 나열하세요. 예: `CORS_ORIGIN=https://nodaro.example.com,http://192.168.1.20:3000`.
- **방문자의 호스트 이름에서 스트림 유지.** 기본 컨테이너처럼 API가 앱과 같은 출처를 쓴다면 `PUBLIC_URL_SAME_ORIGIN=true`로 설정하세요. 그러면 `/config.js`가 브라우저에 `PUBLIC_URL` 대신 API 주소 `/`를 알려 주므로, 스트림이 방문자가 연 호스트 이름에 머뭅니다. 정확히 `true` 값일 때만 활성화됩니다. API가 실제로 다른 호스트에 있다면 설정하지 마세요.

Compose 파일은 `.env`에서 `PUBLIC_URL_SAME_ORIGIN`을 전달하지 않습니다. `nodaro` 서비스의 `environment:` 아래에 추가하세요. [구성](https://nodaro.ai/docs/self-hosting/configuration#how-to-set-a-variable)을 참조하세요.

## 포트 변경
앱을 다른 호스트 포트에서 제공하려면 `docker-compose.community.yml`에서 매핑의 호스트 쪽 포트를 바꾸세요. 예: `"3001:3000"`. 그런 다음 `PUBLIC_URL`도 그에 맞게 `http://localhost:3001`처럼 설정하세요.

## 클라이언트 주소 기록 방식
컨테이너 안의 웹 서버는 사설 주소에 있는 프록시에서 온 `X-Forwarded-*` 헤더만 받습니다. 사설 주소는 `127.0.0.1/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fd00::/8`, `::1`입니다.

- **신뢰할 수 있는 프록시에서 온 경우**, `X-Forwarded-For`를 클라이언트 주소 하나로 줄입니다. 그 자체가 신뢰할 수 있는 프록시가 아닌 가장 오른쪽 항목입니다. 클라이언트가 헤더에 직접 쓴 주소는 건너뜁니다.
- **공인 주소에 있는 프록시에서 온 경우**, 해당 헤더를 웹 서버가 직접 관찰한 값으로 바꿉니다.

인트라넷에서는 사용자의 주소도 사설 주소이면 같은 규칙에 따라 그 주소도 건너뜁니다. 그러면 LAN의 클라이언트가 API에 기록되는 주소를 직접 고를 수 있습니다. 예를 들어 요청 한도에 쓰이는 주소입니다.

## 내 도메인의 임베디드 편집기
**NodarCut에서 편집**, 또는 앱의 동영상 결과에서 **편집**을 누르면 `freecut.nodaro.ai`의 호스팅된 동영상 편집기가 열립니다. 이 편집기는 `http://localhost:3000`에서만 임베딩을 허용합니다. 도메인이나 LAN 주소 같은 다른 출처에서는 브라우저가 임베딩을 거부하고, 패널에 그 이유가 표시됩니다. 내가 제공하는 URL과 함께 GitHub에 이슈를 열거나, 직접 편집기를 실행하고 `FREECUT_URL`을 설정하세요. [구성](https://nodaro.ai/docs/self-hosting/configuration#video-and-audio-editors)을 참조하세요.

## MCP 전용 호스트 이름
MCP 클라이언트는 포트 `9000`의 API에 직접 닿아야 합니다. 포트 `3000`의 웹 서버는 MCP 요청을 거부합니다. [MCP](https://nodaro.ai/docs/self-hosting/mcp)를 참조하세요.

## 자주 묻는 질문

### Nodaro 컨테이너에 이미 웹 서버가 들어 있나요?

네. 컨테이너는 포트 3000에서 Caddy를 실행합니다. 편집기를 제공하고, /v1을 포트 9000의 API로 전달하며, 미디어와 번들된 로그인을 같은 출처에서 제공합니다. HTTPS를 쓰려면 포트 3000 앞에 TLS를 종료하는 프록시를 두세요.

### Nodaro를 도메인 뒤에 둔 다음 무엇을 바꿔야 하나요?

PUBLIC_URL과 CORS_ORIGIN을 내 https 주소로 설정하고, 번들된 MinIO에서는 R2_PUBLIC_URL을 https://your-domain/storage/nodaro-assets로 설정하세요. 그런 다음 docker compose up -d를 실행하세요. 다시 빌드할 필요는 없습니다.

### nginx 프록시를 쓰면 스트리밍 출력이 끊기는 이유는 무엇인가요?

nginx는 기본적으로 응답을 버퍼링하므로 Server-Sent Events가 지연됩니다. proxy_buffering off로 설정하세요. 호스트에서 Caddy를 쓴다면 reverse_proxy 블록에 flush_interval -1을 설정하세요.

### Nodaro가 여러 호스트 이름으로 응답할 수 있나요?

네. 추가 출처를 CORS_ORIGIN에 쉼표로 구분해 나열하세요. 기본 컨테이너처럼 API가 앱과 같은 출처를 쓴다면, 스트림이 방문자가 연 호스트 이름에 머물도록 PUBLIC_URL_SAME_ORIGIN=true도 설정하세요.
