「VPSは借りたが,1台で複数のアプリやサイトを動かせるのだろうか」── 答えはYesだ.鍵を握るのがリバースプロキシという考え方であり,これを設計できると1台のVPSの活用度が一気に上がる.
リバースプロキシとは,前段に立って受けたリクエストを,背後の適切なアプリに振り分ける仕組みだ.Nginxを前段に置けば,ドメインやパスごとに別々のアプリへ流し,HTTPS終端も一元化できる.
この記事は,1台のVPSを使い倒したい個人開発者,複数サービスを同居させたいエンジニアに向けている.ドメイン/パス振り分け,サブドメイン,WebSocket,タイムアウト設計までを実用的な設定で解説する.
読み終えたとき,あなたは1台のVPSで複数のアプリ・サイト・APIを,それぞれ独立して安全に公開できるようになっている.
なぜリバースプロキシが1台運用の鍵なのか
複数のアプリは,それぞれ別のポート(3000,4000,8080…)で動く.だが利用者にexample.com:4000のようなポート付きURLを使わせるわけにはいかない.すべてを80/443で受けて振り分ける必要がある.
この「受けて振り分ける」役を担うのがリバースプロキシだ.Nginxを前段に置けば,ドメイン・サブドメイン・パスを見て,適切なアプリに流すことができる.
さらにリバースプロキシは,HTTPS終端を一元化する.各アプリがそれぞれSSLを扱う必要がなく,証明書の管理も前段に集約できる.圧縮やキャッシュ,アクセス制御も一箇所で効かせられる.
つまりリバースプロキシは,1台のVPSを「複数サービスのハブ」に変える中核技術だ.これを設計できることが,限られたリソースを最大活用する条件になる.
基本形 ― ドメインごとに別アプリへ振り分ける
最も基本的な振り分けが,server_name(ドメイン)ごとに別アプリへ流す構成だ.各ドメインに対してserverブロックを用意し,背後のアプリのポートへproxy_passする.
ドメインごとの振り分け
# サイトA → ポート3000のアプリ
server {
listen 443 ssl;
server_name app-a.example.com;
location / { proxy_pass http://127.0.0.1:3000; }
}
# サイトB → ポート4000のアプリ
server {
listen 443 ssl;
server_name app-b.example.com;
location / { proxy_pass http://127.0.0.1:4000; }
}それぞれのserverブロックを別ファイル(/etc/nginx/sites-available/)に分けて管理すると見通しがよい.アプリを追加するたびにファイルを足してリロードするだけで,1台のVPSにいくらでもサービスを同居させられる.
プロキシヘッダの正しい設定 ― これを怠るとアプリが誤動作する
proxy_passだけでは不十分だ.適切なヘッダを背後のアプリに渡さないと,アプリが「自分のホスト名」や「クライアントのIP」を正しく認識できない.リダイレクトが壊れたり,ログに全部プロキシのIPが記録されたりする.
渡すべきプロキシヘッダ(共通化推奨)
# /etc/nginx/proxy_params などに切り出して include
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;
proxy_http_version 1.1;X-Forwarded-ForとX-Forwarded-Protoは特に重要だ.前者で本当のクライアントIPを,後者で元の通信がHTTPSだったことをアプリに伝える.これが無いと,アプリが「HTTPでアクセスされた」と誤認してHTTPSへの無限リダイレクトを起こすことがある.これらのヘッダは共通ファイルに切り出し,各ブロックでincludeすると管理が楽だ.
サブドメイン運用 ― blog. / api. / app. を整理する
サービスが増えると,サブドメインで役割を分けるのが定石になる.blog.example.comはWordPress,api.example.comはAPIサーバー,というように整理できる.
サブドメイン運用にはDNSのワイルドカード(*.example.com)とワイルドカード証明書を使うと,新しいサブドメインを足すたびにDNS・証明書を個別設定する手間が省ける(前回のSSL記事のDNS-01認証を参照).
| サブドメイン | 用途の例 |
|---|---|
| www / (apex) | メインサイト |
| blog. | ブログ・メディア(WordPress等) |
| api. | APIサーバー |
| app. | Webアプリ本体 |
| staging. | 検証環境(本番と分離) |
パスベースの振り分け ― /api だけアプリへ
同一ドメインで,パスによって振り分ける構成も多用される.フロントは静的配信,/api/だけバックエンドへ流す,という形だ.CORSの悩みが減るのが利点だ.
パスで振り分ける(フロント静的 + API)
server {
listen 443 ssl;
server_name example.com;
location /api/ {
proxy_pass http://127.0.0.1:3000;
include /etc/nginx/proxy_params;
}
location / {
root /var/www/frontend;
try_files $uri /index.html; # SPA対応
}
}try_files $uri /index.htmlは,React/VueなどのSPAで重要だ.存在しないパスへのアクセスをindex.htmlに集約し,クライアント側ルーティングに委ねる.APIはパスで明確に分離されるため,1ドメインでフロントとAPIをきれいに同居できる.
WebSocketのプロキシ ― リアルタイム通信を通す
チャット・通知・ライブ更新などで使うWebSocketは,通常のHTTPプロキシ設定だけでは通らない.接続のアップグレード(Upgrade/Connectionヘッダ)を明示する必要がある.
WebSocketを通すための設定
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s; # 長時間接続を切らない
}肝はUpgradeとConnection "upgrade",そしてproxy_http_version 1.1だ.これでHTTPからWebSocketへのプロトコル切り替えが正しく中継される.WebSocketは長時間接続を保つため,proxy_read_timeoutを長めに設定して途中で切断されないようにするのも重要だ.
タイムアウトとバッファ ― 大きな処理・遅い応答への対応
デフォルトのタイムアウトは短く,時間のかかる処理(大きなアップロード・重いAPI・LLMの生成)が途中で切れることがある.用途に応じて調整する.
タイムアウトとアップロードサイズの調整
client_max_body_size 50m; # アップロード上限(既定1m)
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s; # 遅いAPI/生成系に対応client_max_body_sizeは見落としやすい.既定の1MBを超えるファイルアップロードは「413 Request Entity Too Large」で弾かれる.画像や動画を扱うなら必ず引き上げる.LLMの生成APIのように応答が遅いものはproxy_read_timeoutを延ばし,前段で切られないようにする(前回のAIデプロイ記事も参照).
アクセス制御を前段で一元化する
リバースプロキシの前段では,アクセス制御・レート制限・Basic認証を一元的に効かせられる.各アプリに個別実装するより,前段で守る方が漏れがない.
管理画面をIP制限・レート制限する
# 管理画面は特定IPのみ
location /admin/ {
allow 203.0.113.10;
deny all;
proxy_pass http://127.0.0.1:3000;
}
# レート制限ゾーン
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;管理画面を特定IPのみ許可する,APIにレート制限をかける,といった防御を前段でまとめて適用できる.バックエンドのアプリは本来のロジックに集中でき,セキュリティの要は前段に集約される.これがリバースプロキシのもう一つの大きな価値だ.
補論:複数アプリの同居は「メモリの余裕」と「巻き戻し」が鍵
1台で複数アプリを動かすほど,メモリの余裕が安定性を左右する.各アプリ+DB+Nginxが同居するため,余裕のないVPSでは詰まりやすい.そして設定が複雑になるぶん,変更を安全に試せることも重要になる.
高速NVMe・50種類以上のOSテンプレートに対応した国内VPS─シン・VPS─ はNVMe SSDで複数アプリの同居が軽快に回り,必要に応じてメモリをスケールアップできる.スナップショットを取ってからリバースプロキシ設定を触れば,振り分けミスで全サービスを落としても即座に巻き戻せるので,安心して構成を組める.
複数サービスをサブドメインで整理するなら,独自ドメインが要だ.取り扱い400種類以上のドメイン取得サービス─ムームードメイン─ で取得したドメインにワイルドカードを設定すれば,blog. / api. / app. を自在に増やせ,1台のVPSが「複数サービスのハブ」になる.
よくある質問(FAQ)
Q1.1台のVPSで何個までアプリを動かせる?
明確な上限はなく,メモリとCPUの余裕次第だ.軽量なアプリなら数個〜十数個の同居も現実的.メモリが逼迫し始めたらスケールアップするか,重いものを別VPSへ分ける.
Q2.proxy_set_headerは必ず要る?
実質必須だ.特にHost・X-Forwarded-For・X-Forwarded-Protoが無いと,アプリがクライアントIPやHTTPS状態を誤認し,ログやリダイレクトが壊れる.共通ファイルに切り出してincludeするのがおすすめ.
Q3.WebSocketが繋がらない
Upgrade/Connectionヘッダとproxy_http_version 1.1が設定されているか確認する.加えてproxy_read_timeoutが短いと長時間接続が切れるため,長めに設定する.
Q4.アップロードが413エラーで失敗する
client_max_body_sizeが原因だ.既定1MBを超えるとこのエラーになる.扱うファイルに合わせて50mなどに引き上げる.
Q5.サブドメインとパス振り分けどちらが良い?
独立性が高いサービスはサブドメイン,密結合のフロント+APIはパスが目安だ.サブドメインはCookieやCORSを分離でき,パスは同一オリジンでCORSの悩みが減る.用途で選ぶ.
Q6.設定ミスで全サービスが落ちないか不安
変更前にnginx -tで構文確認し,reload(無停止)で反映する.スナップショットを取っておけば,最悪でも変更前へ巻き戻せる.これがあると複雑な構成も恐れずに組める.
まとめ ― リバースプロキシが1台VPSを「ハブ」に変える
リバースプロキシは,ドメイン・サブドメイン・パスで振り分け,HTTPS終端とアクセス制御を一元化する,1台運用の中核技術だ.これを設計できれば,1台のVPSで複数サービスを独立に公開できる.
今日やるべきことは,2つ目のアプリを別ポートで立て,Nginxのserverブロックを1つ足して振り分けること.1台で複数サービスが同居する手応えを掴めば,VPSの活用度は一気に上がる.
プロキシヘッダ・WebSocket・タイムアウトという勘所さえ押さえれば,怖いものはない.スナップショットで戻せるVPSがあれば,今夜から構成を攻められる.