Nginxリバースプロキシ入門 — 1台のVPSで複数サービスを公開する【2026年】

VPS・サーバー選定中級
NginxReverse ProxyVPSLet's EncryptCaddy

本記事はアフィリエイト広告(A8.net)を含みます。価格・仕様は2026年6月時点の目安です。最新は各公式サイトでご確認ください。

TL;DR

1台のVPSでアプリを複数動かすと、それぞれ別のポート(localhost:3000localhost:8080 など)で待ち受けます。ですが外部に公開できる入口は基本的に80番(HTTP)と443番(HTTPS)の2つだけです。この差を埋めるのがリバースプロキシです。

Nginxを入口に置き、ドメイン名(Host ヘッダ)で振り分けて各アプリへ転送します。SSL終端(HTTPS化)もNginx側でまとめれば、後ろのアプリは平文のHTTPで動かしたままで済みます。証明書はLet’s Encryptで無料・自動更新できます。

設定がシンプルで自動HTTPSまで欲しい場合は、Caddyという軽量な選択肢もあります。本記事ではNginxを軸に基本を押さえ、最後にCaddyと比較します。


リバースプロキシとは何か / 何が嬉しいか

「リバースプロキシ」は、クライアントからのリクエストを受け取り、内部のサーバーへ代理で転送するサーバーです。利用者から見える顔はNginx1つだけで、その裏に複数のアプリが隠れている構成になります。

1台のVPSで複数サービスを公開する場面で、これがないと困ることを並べます。

  • ポートの問題: アプリは :3000:8080 で動きますが、利用者に https://example.com:8080 を踏ませるのは現実的ではありません。443番に集約したいです。
  • ドメイン振り分け: app.example.com はNode.jsアプリ、blog.example.com はWordPressへ、と1つのIPで複数ドメインを捌きたいです。
  • HTTPSの一元化: 証明書を各アプリに配るのは面倒です。Nginxで終端すれば1か所で管理できます。
  • アプリを隠せる: 後ろのアプリは 127.0.0.1(ループバック)だけで待ち受け、外部に直接さらさずに済みます。

つまりNginxが「玄関」となり、ドメイン・ポート・証明書・公開範囲をまとめて引き受ける、というのがリバースプロキシの役割です。


ポートとドメインの対応をどう捌くか

外部からの入口は80番(HTTP)と443番(HTTPS)です。1つのIPアドレスに複数のドメインを向けておき、Nginxが受け取ったHost ヘッダ(要求されたドメイン名)を見て転送先を決めます。これが名前ベースのバーチャルホストです。

公開ドメイン内部の待ち受け用途の例
app.example.com127.0.0.1:3000Node.js / SPA APIサーバー
blog.example.com127.0.0.1:8080WordPress(PHP-FPM等)
grafana.example.com127.0.0.1:3001監視ダッシュボード

前提として、各ドメインのDNS(Aレコード/AAAAレコード)をこのVPSのIPに向けておきます。Nginxは届いたリクエストの宛先ドメインで server ブロックを選び、対応する内部ポートへ渡します。


基本の server / location / proxy_pass

まず最小構成です。1つのアプリ(127.0.0.1:3000 で動いているとします)をHTTPで公開する例です。Ubuntu系なら /etc/nginx/sites-available/app.conf に置き、sites-enabled へシンボリックリンクを張る運用が一般的です。

server {
    listen 80;
    listen [::]:80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;

        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;
    }
}

各ディレクティブの意味です。

  • server_name: このブロックが担当するドメイン名です。リクエストの Host がここに一致したブロックが使われます。
  • location /: パスごとの処理単位です。/ は全パスにマッチします。
  • proxy_pass: 転送先です。http://127.0.0.1:3000 のように内部アドレスを書きます。
  • proxy_set_header: 転送時にヘッダを付け替えます。Host を渡さないと後ろのアプリが自分のドメインを判別できません。X-Real-IP / X-Forwarded-For本来のクライアントIPを、X-Forwarded-Proto元がHTTPかHTTPSかを後ろへ伝えます。これらを省くと、アプリ側でログのIPがすべてNginxのIPになったり、HTTPS判定を誤ったりします。

設定を変えたら、文法チェックしてから反映します。

sudo nginx -t          # 設定ファイルの文法チェック
sudo systemctl reload nginx   # 無停止でリロード

複数サービスのバーチャルホスト

ドメインごとに server ブロックを足していくだけで複数サービスを公開できます。ファイルを分けて1ドメイン1ファイルにすると管理が楽です。

app.example.com(Node.jsアプリ)の例です。

# /etc/nginx/sites-available/app.conf
server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

blog.example.com(別ポートのアプリ)の例です。

# /etc/nginx/sites-available/blog.conf
server {
    listen 80;
    server_name blog.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
    }
}

有効化はリンクを張って nginx -treload です。

sudo ln -s /etc/nginx/sites-available/app.conf  /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/blog.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

ここでよくあるのが、後ろのアプリを 0.0.0.0(全インターフェース)で待ち受けてしまい、http://VPSのIP:3000Nginxを迂回して直接アクセスできてしまう事故です。アプリ側は 127.0.0.1:3000 のようにループバックだけで待ち受けるか、ファイアウォール(ufw等)で3000・8080番を外部から閉じておきます。サーバーの初期防御はVPS初期セキュリティ設定チェックリストも参照してください。


SSL終端(Let’s Encrypt連携)

HTTPS化はNginx側でまとめて行います(SSL終端)。後ろのアプリは平文HTTPのまま、利用者との間だけ暗号化される形です。証明書はLet’s EncryptをCertbotで取得・自動更新します。

Certbotを入れて、Nginx設定を見ながら証明書を発行します。

# Ubuntu系の例
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com -d blog.example.com

--nginx プラグインを使うと、Certbotが各 server ブロックを自動で443番対応に書き換え、証明書のパスや80→443リダイレクトも追記します。書き換え後はおおむね次の形になります。

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name app.example.com;

    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

# 80番に来たアクセスは443へリダイレクト
server {
    listen 80;
    listen [::]:80;
    server_name app.example.com;
    return 301 https://$host$request_uri;
}

Let’s Encryptの証明書は有効期間90日です。Certbotはインストール時に更新タイマー(systemd timerまたはcron)を仕込むため、通常は自動更新されます。動作確認はドライランで行います。

sudo certbot renew --dry-run

ここで先ほどの X-Forwarded-Proto $scheme が効いてきます。利用者→Nginx間はHTTPS、Nginx→アプリ間はHTTPなので、アプリは自分への接続を「HTTP」と誤認しがちです。X-Forwarded-Proto を見るようアプリ側を設定すれば、リダイレクトループやCookieのSecure属性の不整合を避けられます。


WebSocket / ヘッダ転送の注意

WebSocket(チャット、リアルタイム更新、開発用のホットリロード等)を使うアプリでは、追加の設定が要ります。WebSocketはHTTPの Upgrade ヘッダで通常接続から切り替わるためです。location に以下を足します。

location / {
    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_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: WebSocketのアップグレードにはHTTP/1.1が必要です。Nginxはデフォルトで後ろへ1.0を使うため明示します。
  • Upgrade / Connection ヘッダ: これを転送しないと接続が普通のHTTPのまま切り替わらず、WebSocketが確立できません。
  • 長時間接続のタイムアウト: WebSocketは接続を張りっぱなしにします。無通信で切れる場合は proxy_read_timeout 3600s; のように読み取りタイムアウトを延ばします。

なお、転送するアップロードのサイズが大きいアプリでは client_max_body_size(デフォルトは1MB)も見直します。ファイルアップロードが413エラーで弾かれる典型原因です。

# server または location ブロック内に記述する。
# (http ブロック全体に効かせたい場合は /etc/nginx/nginx.conf の
#  既存の http {} 内に置く。設定断片で http {} を新たに書くと二重定義になり
#  nginx -t が失敗するので注意)
client_max_body_size 20m;   # 例: 20MBまで許可

Caddyという軽量な選択肢(自動HTTPS)

Nginxの代わりにCaddyを入口に置く選択肢もあります。最大の特徴は自動HTTPSで、設定にドメインを書くだけで、Caddyが起動時にLet’s Encrypt(またはZeroSSL)から証明書を取得し、更新まで面倒を見ます。Certbotを別途仕込む必要がありません。

同じ「2サービスをドメインで振り分け、HTTPS化する」構成を Caddyfile で書くと、これだけで済みます。

app.example.com {
    reverse_proxy 127.0.0.1:3000
}

blog.example.com {
    reverse_proxy 127.0.0.1:8080
}

reverse_proxyX-Forwarded-For などのヘッダ付与やWebSocketのアップグレード転送をデフォルトで行います。Nginxで手書きしていた proxy_set_header 群が省けるのが利点です。

NginxとCaddyの比較です。

観点NginxCaddy
HTTPSCertbot等で設定(自動更新は別途タイマー)設定にドメインを書くだけで自動取得・更新
設定の量ヘッダ等を明示的に書く(細かく制御可能)既定が親切で短く書ける
設定の細かさ非常に細かく制御できる既定で十分だが、超細かい調整はNginxに分がある
性能・実績高負荷・大規模での実績が豊富中小規模で十分、近年実績も増加
用途の目安細かいチューニング・既存資産がある場合個人〜小規模で手早く立てたい場合

「とにかく早く複数サービスをHTTPSで公開したい」「証明書管理を意識したくない」ならCaddyが楽です。一方、細かいキャッシュ制御・rewrite・既存のNginx資産がある、あるいは将来的に大規模化を見据えるならNginxが順当です。どちらもリバースプロキシとしての考え方(ドメインで振り分け→内部ポートへ転送→SSL終端)は同じです。


実践: どのVPSで動かすか

リバースプロキシ構成は1台のVPSに複数サービスを同居させるため、メモリの余裕が効きます。Nginx自体は軽量ですが、後ろのアプリ(Node.js、PHP-FPM、データベース等)が積み上がるとメモリを食います。国内で実績のあるVPSを2つ挙げます。

  • ConoHa VPS: 時間課金に対応し、検証で立てて消す使い方がしやすいです。管理画面が分かりやすく、初めての自己ホストでも扱いやすい構成です。
  • Xserver VPS: レンタルサーバーで知られる事業者のVPSです。料金と性能のバランスが取りやすく、長期で1台を常駐させる用途に向きます。

どちらもUbuntu等のLinuxイメージにNginxを入れて上記の構成を組めます。まずは小さいプランで1〜2サービスから始め、メモリ使用率を見ながらプランを上げるのが安全です。VPSの選び方の詳細は個人開発者向けVPS比較も参考にしてください。


まとめ

項目要点
リバースプロキシの役割80/443の入口を1つにまとめ、ドメインで内部ポートへ振り分ける
振り分けの基準server_nameHost ヘッダの一致(名前ベースのバーチャルホスト)
必須ヘッダHost / X-Real-IP / X-Forwarded-For / X-Forwarded-Proto を転送する
SSL終端Nginxで443を終端、後ろはHTTP。Let’s Encrypt + Certbotで無料・自動更新
WebSocketproxy_http_version 1.1 + Upgrade / Connection ヘッダの転送が必要
後ろのアプリの公開範囲127.0.0.1 で待ち受け+ファイアウォールで直アクセスを塞ぐ
軽量な代替Caddyは設定にドメインを書くだけで自動HTTPS。手早く立てたい場合に有利

1台のVPSで複数サービスを公開する構成は、「Nginxを玄関に、後ろのアプリはループバックで隠す」という形に収束します。まず1サービスをHTTPで通し、Certbotで443化し、必要ならWebSocketヘッダを足す——この順で積めば迷いません。


各サービス公式

関連記事

VPS・サーバー選定Nginx vs Apache vs Caddy — Webサーバーの選び方【2026年】VPS・サーバー選定PostgreSQLパフォーマンスチューニング: 中小企業DBの遅延を解消する手順VPS・サーバー選定高可用性(HA)構成の最小コスト実装:2台のVPSでフェイルオーバーを組む
記事一覧に戻る