# リバースプロキシと HTTPS

> ポート 3000 の前段に nginx か Caddy を置き、セルフホスティングの Nodaro を自分のドメインで HTTPS 配信します。そのあと PUBLIC_URL と CORS_ORIGIN を設定して、アプリを再起動します。

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

**リバースプロキシ**を使うと、セルフホスティングの Nodaro を、実際のドメインで HTTPS で公開できます。Nodaro のコンテナはポート `3000` ですでに Web サーバー（Caddy）を動かしているため、そのポートの前段に TLS を終端するプロキシを 1 つ追加し、Nodaro に公開アドレスを伝えるだけです。nginx と Caddy のどちらも使えます。

## ポート 3000 で提供されるもの
コンテナ内の Web サーバーは、すべてを 1 つのオリジンで提供します。

| パス | 応答するもの |
| --- | --- |
| `/` | エディターとアプリ（静的ファイル） |
| `/v1/*` | API（コンテナ内のポート `9000` で待ち受けます） |
| `/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 は、テキストの出力と実行の進行状況を Server-Sent Events でストリーミングします。

## 方法 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` は、API のアドレスとして `PUBLIC_URL` ではなく `/` をブラウザーに渡すため、ストリームは訪問者が開いたホスト名にとどまります。有効になるのは、値がちょうど `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` のように設定します。

## クライアントのアドレスの記録方法
コンテナ内の Web サーバーは、プライベートアドレスにあるプロキシからの `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` を 1 つのクライアントアドレスに絞り込みます。使われるのは、それ自体は信頼できるプロキシではない、最も右のエントリーです。クライアントがヘッダーに書き込んだアドレスはスキップされます。
- **パブリックアドレスにあるプロキシからのリクエスト**では、これらのヘッダーを、Web サーバー自身が観測した値に置き換えます。

イントラネットでは、ユーザー自身のアドレスもプライベートアドレスの場合、同じルールによって、そのアドレスもスキップされます。その場合、LAN 上のクライアントは、レート制限などのために API が記録するアドレスを、自分で選べてしまいます。

## 自分のドメインでの埋め込みエディター
**動画編集**（Edit video）操作は、`freecut.nodaro.ai` にあるホスティング版の動画エディターを開きます。このエディターは、`http://localhost:3000` からの埋め込みしか許可していません。ドメインや LAN のアドレスなど、それ以外のオリジンではブラウザーが埋め込みを拒否し、パネルにその理由が表示されます。配信している URL を添えて GitHub で Issue を作成するか、自分でエディターを運用して `FREECUT_URL` を設定してください。[設定](https://nodaro.ai/docs/self-hosting/configuration#video-and-audio-editors)を参照してください。

## MCP には専用のホスト名が必要
MCP クライアントは、ポート `9000` の API に直接アクセスする必要があります。ポート `3000` の Web サーバーは、MCP のリクエストを拒否します。[MCP](https://nodaro.ai/docs/self-hosting/mcp) を参照してください。

## Frequently asked questions

### Nodaro のコンテナには、Web サーバーがすでに含まれていますか？

はい。コンテナは、ポート 3000 で Caddy を動かしています。Caddy はエディターを配信し、/v1 をポート 9000 の API に転送し、メディアと同梱のログイン機能を同じオリジンで提供します。HTTPS にするには、TLS を終端するプロキシをポート 3000 の前段に置いてください。

### 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 も設定してください。これで、ストリームは訪問者が使っているホスト名にとどまります。
