メインコンテンツまでスキップ

ドメインとリバースプロキシ

IPアドレスの代わりにドメイン(特にHTTPS)でスタジオをサービス提供する際の設定です。 この章は順番にすべて実施する必要があります。 一つでも欠けると、「プレビューが空白画面」「ビルドチャットが 接続エラー」「デプロイアプリでデータが401」といった、一見異なる症状がそれぞれ発生します。


ドメインは一つです​

プレビューとデプロイアプリは、スタジオと同じドメインの/container/配下で配信されます。

https://studio.company.com/ → 스튜디오 UI + API
https://studio.company.com/container/… → 프리뷰 · 배포앱

必要なのは、DNSレコード1つ、証明書1枚、vhost 1つです。

アプリも同じドメインを使用します

アプリを別ホストに分離しません。プレビュー・デプロイのURLがすべて相対パスのため、 80/443のみを公開するリバースプロキシ構成でそのまま動作します。

代償 — オリジン分離を放棄しました

プレビュー・デプロイアプリはチャットで生成されたコード、つまり信頼できないコンテンツです。それがスタジオと 同じオリジンで動作します — オリジンを分けて得られる隔離がないという意味です。ドメインを一つに 絞る代償として受け入れた判断です。

したがって、信頼できないユーザーにアプリ作成権限を与えないでください。 ビルダーロールは社内 オペレーターのみに付与することを前提とした構成です。


準備物チェックリスト​

  • DNS Aレコード 1つ
  • 該当ホスト名のTLS証明書
  • リバースプロキシからスタジオボックスの :80 に到達可能
  • スタジオボックスのファイアウォールでプロキシ → :80 を許可
:5171 は開かなくて構いません

アプリリスナー(:5171)は、スタジオボックス内のweb nginxが/container/・/apps/・/preview/ を引き渡すため、外部に公開する必要はありません。 リバースプロキシなしでポートに直接アクセスする 構成の場合のみ、ファイアウォールを開けてください。


1. プロキシにvhostを追加​

外部プロキシは、すべてスタジオボックスの :80 に転送するだけで構いません。/container/ /apps/・/preview/ の分岐はボックス内のweb nginxが既に処理しています。

必ず含めるべき4つの設定​

欠けた場合の症状が異なるため原因を特定しにくくなります。以下の例をそのままコピーして 使用することを推奨します。

設定欠けると発生する症状
proxy_set_header Host $http_hostルーティング・リンク生成がずれます
Upgrade / Connection ヘッダープレビューのリアルタイム更新(HMR)WebSocketが切断され、コード修正が画面に反映されません
proxy_read_timeout 3600sビルドチャットが「接続エラー: network error」 — エージェントがツール実行で数十秒沈黙すると、デフォルトの60秒タイムアウトがストリームを切断します
proxy_buffering offストリーミング応答がバッファに溜まり、回答がまとまって遅れて表示されます
SSE(サーバー送信ストリーミング)が重要です

ビルドチャットと質疑応答はSSEでリアルタイム送信されます。サーバーが25秒ごとにハートビートを送るため、 プロキシのタイムアウトがそれより長ければ問題ありませんが、3600s は実際の運用で実証された値です。

nginx設定例​

server {
listen 80;
server_name studio.company.com;

location / {
proxy_pass http://<studio-host>:80;
proxy_http_version 1.1;
proxy_set_header Host $http_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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; # 에이전트 SSE(빌드 채팅) — 필수
proxy_buffering off; # 스트리밍 즉시 전달 — 필수
client_max_body_size 64M; # 사진·도면 첨부
}
}

HTTPSはcertbotなどで発行します — listen 443 ssl ブロックが上記設定をそのまま継承すれば 問題ありません。

スタジオボックスのweb nginx内にvhostを追加する場合

パッケージされたweb nginxコンテナのconf.d にvhostファイルを直接マウントする場合、ファイル名を zz- で始まるようにしてください。nginxはアルファベット順で最初のserver ブロックをデフォルトサーバーとして 扱うため、名前が先頭に来ると、マッチしないすべてのリクエストが誤った場所に送られ、スタジオ 全体が停止します(実際に発生した事故です)。


2. 再ログイン(必須)​

ドメイン設定が完了したら、すべてのユーザーが一度ログアウトし、再度ログインする必要があります。

ログインCookieは発行時点のホスト専用です。IPでアクセスしてログインしていたセッションは、ドメインに 変更した後に引き継がれず、データリクエストが401で失敗します。


3. 確認​

確認項目方法
スタジオが表示されるhttps://studio.company.com にアクセス → ログイン
プレビューが表示されるプロジェクトを開く → プレビュー画面が表示され、コンソールにMixed Content がない
アプリのパスが通っているhttps://studio.company.com/container/ にアクセス → 404/アプリ一覧が表示されれば正常(接続済み)
リアルタイム更新チャットで文言を一つ修正 → プレビューが自動更新
長時間のビルドビルドチャットを1分以上実行 → 「接続エラー」なしで完走
デプロイアプリのデータデプロイされたアプリを開く → 実データ表示(401なし)

注意事項​

IPとドメインを混在させないでください

ドメインを設定した後は、ドメインのみでアクセスしてください。IPでアクセスしたユーザーはCookieが異なるため、 デプロイアプリのデータが401になります。

Cloudflareを前面に配置する場合
  • WebSocketはデフォルトでサポートされるため、追加設定は不要です。
  • 無料のユニバーサル証明書は1階層のサブドメインのみをカバーします(studio.company.com ✅、 apps.studio.company.com ❌)。
添付ファイルのサイズ

現場写真や図面をチャットに添付するため、client_max_body_size 64M を設定してください。 欠けると大きな写真のアップロードが413で失敗します。


リバースプロキシなしでHTTPSのみを設定する場合​

別のプロキシサーバーがなく、スタジオボックスで直接TLSを終端する場合は、運用パッケージのTLS オーバーレイを使用します。

cd /opt/kopens/plantpulse-studio-docker
cp tls/nginx-tls.conf.example tls/nginx-tls.conf # server_name 등 수정
# tls/cert.pem, tls/key.pem 배치(사내 CA 또는 공인 인증서)
docker compose -f docker-compose.yml -f docker-compose.tls.yml up -d
TLSオーバーレイのサンプルファイルはまだ古い構造を含んでいます

tls/nginx-tls.conf.example には/container/ ブロックがなく、コメントがまだ削除されていない APPS_ORIGIN と別ポート(5443)を案内しています。そのまま使用すると、プレビュー・デプロイアプリのURL (/container/…)が404になります。

当分の間は、コピー(tls/nginx-tls.conf)に/container/ ブロックを直接追加してください — 上記の nginx設定例のヘッダー4種をそのまま使い、接頭辞を外してアプリ リスナーに転送すれば構いません。APPS_ORIGIN 行は追加しないでください(読み込まれません)。


症状 → 原因の早見表​

ドメイン配信で実際によく発生するものです。より広範囲な内容はトラブルシューティングを参照してください。

症状原因対処
プレビュー・デプロイアプリが空白画面、コンソールにMixed ContentスタジオはHTTPSなのにアプリのアセットがHTTPでリクエストされるプロキシにX-Forwarded-Proto $scheme を追加し、全体をHTTPSにする
デプロイアプリで実データが401ドメイン設定前にログインしたセッションログアウトして再ログインを1回
ビルドチャットが長時間かかると「接続エラー: network error」プロキシの無送信タイムアウト(デフォルト60秒)proxy_read_timeout 3600s
コード修正がプレビューに反映されないHMR WebSocketがアップグレードされていないUpgrade / Connection ヘッダーを追加
回答がまとまって遅れて表示されるproxy_buffering が有効(デフォルト)proxy_buffering off
任意のドメインが誤った場所に送られるweb nginxのconf.d読み込み順序(最初のserver がデフォルトサーバー)vhostファイル名をzz- で始める
/container/… が404TLSオーバーレイのコピーに/container/ ブロックがない上記の警告を参照
ポートで直接使用する構成でアプリが表示されないファイアウォールで5171がブロックされているファイアウォールを開放後、curl -I http://<host>:5171/ で確認

関連ドキュメント​