Nginx リバースプロキシ
『Nginxリバースプロキシ』は、クライアントからのリクエストを受け取り、背後で動作するアプリケーションサーバー(Node.js・Django・Rails・C# など)に転送する仕組みです。アプリ側のポートを外部に公開せずに済むため、セキュリティと柔軟性が向上します。proxy_pass ディレクティブで転送先を指定し、proxy_set_header でクライアントの情報をアプリに伝えます。
構文
# -----------------------------------------------
# proxy_pass — リバースプロキシの基本設定
# -----------------------------------------------
# proxy_pass {転送先URL};
# → リクエストを指定した URL に転送します
# → location ブロック内で使用します
# 例: proxy_pass http://127.0.0.1:3000;
# 例: proxy_pass http://backend_pool; # upstream名を指定
# proxy_set_header Host {値};
# → 転送先に渡す Host ヘッダーを設定します
# → $host を使うとクライアントが送ってきたホスト名をそのまま渡せます
# 例: proxy_set_header Host $host;
# proxy_set_header X-Real-IP {値};
# → クライアントの実際の IP アドレスをアプリに伝えます
# → Nginx がプロキシに挟まるとアプリ側では Nginx の IP しか見えなくなるため必須です
# 例: proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For {値};
# → 経由したプロキシの IP アドレスをカンマ区切りで渡します
# → 既存の X-Forwarded-For に追記する形式が一般的です
# 例: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# -----------------------------------------------
# upstream — バックエンドプールの定義
# -----------------------------------------------
# upstream {プール名} {
# server {ホスト}:{ポート} [weight={重み}];
# ...
# }
# → 複数のバックエンドサーバーをまとめてロードバランシングできます
# → プール名は proxy_pass で参照します
# 例:
# upstream kyo_backend {
# server 127.0.0.1:3000;
# server 127.0.0.1:3001 weight=2;
# }
# -----------------------------------------------
# WebSocket 対応(Upgrade / Connection ヘッダー)
# -----------------------------------------------
# WebSocket を使うアプリ(Socket.io 等)では
# HTTP の Upgrade ヘッダーを転送する必要があります
# proxy_http_version 1.1;
# → WebSocket は HTTP/1.1 が必要です
# proxy_set_header Upgrade $http_upgrade;
# → Upgrade ヘッダーをそのまま転送します
# proxy_set_header Connection "upgrade";
# → Connection ヘッダーを "upgrade" に設定します
構文一覧
| ディレクティブ | 説明 |
|---|---|
proxy_pass | リクエストを転送するバックエンドの URL を指定します。http://127.0.0.1:3000 のように直接指定するか、upstream で定義したプール名を使えます。 |
proxy_set_header Host | 転送先に渡す Host ヘッダーを設定します。$host を指定するとクライアントが送ったホスト名をそのまま渡せます。 |
proxy_set_header X-Real-IP | クライアントの実際の IP アドレスを $remote_addr でアプリに伝えます。アクセスログやレート制限に利用します。 |
proxy_set_header X-Forwarded-For | 経由プロキシの IP をカンマ区切りで累積記録します。$proxy_add_x_forwarded_for を使うと既存ヘッダーに追記されます。 |
proxy_set_header X-Forwarded-Proto | クライアントとの通信プロトコル($scheme: http または https)をアプリに伝えます。HTTPS リダイレクト判定に使われます。 |
proxy_http_version | バックエンドとの HTTP バージョンを指定します。WebSocket 対応には 1.1 が必須です。 |
proxy_read_timeout | バックエンドからの応答を待つ最大時間(秒)を指定します。デフォルトは 60 秒です。重い処理を行うアプリでは延ばす必要があります。 |
proxy_connect_timeout | バックエンドへの接続確立を待つ最大時間(秒)です。デフォルトは 60 秒です。 |
proxy_buffering | バックエンドからの応答をバッファリングするかどうかを制御します。off にするとストリーミング・Server-Sent Events で有効です。 |
upstream | バックエンドサーバーをプールとして定義します。server ディレクティブで複数台を列挙すると、ラウンドロビンでロードバランシングされます。 |
proxy_cache_bypass | 指定した条件でキャッシュをバイパスします。動的コンテンツのキャッシュ除外に使います。 |
使用例
/etc/nginx/sites-available/kyo-node.conf
# -----------------------------------------------
# 草薙京の Node.js アプリ(ポート 3000)への
# リバースプロキシ設定です
# WebSocket(Socket.io)にも対応しています
# -----------------------------------------------
server {
listen 80;
server_name kyo-app.example.com;
# HTTP → HTTPS リダイレクト
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name kyo-app.example.com;
ssl_certificate /etc/letsencrypt/live/kyo-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kyo-app.example.com/privkey.pem;
location / {
# ローカルの 3000 番ポートで動く Node.js アプリに転送します
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;
# WebSocket(Socket.io)対応のため HTTP/1.1 と Upgrade ヘッダーを設定します
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# バックエンドの応答待ちタイムアウトを 120 秒に延ばします
proxy_read_timeout 120s;
}
}
実行するコマンドは次の通りです。
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo systemctl reload nginx
$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
Active: active (running) since Wed 2026-03-25 09:00:00 JST
/etc/nginx/sites-available/iori-django.conf
# -----------------------------------------------
# 八神庵の Django アプリ(Gunicorn / ポート 8000)への
# リバースプロキシ設定です
# 静的ファイル(/static/)は Nginx が直接配信します
# -----------------------------------------------
upstream iori_gunicorn {
# Gunicorn が 127.0.0.1:8000 で待ち受けています
server 127.0.0.1:8000;
}
server {
listen 80;
server_name iori-app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name iori-app.example.com;
ssl_certificate /etc/letsencrypt/live/iori-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/iori-app.example.com/privkey.pem;
# Django の collectstatic で集めた静的ファイルを Nginx が直接返します
# アプリサーバーを経由しないため高速です
location /static/ {
alias /var/www/iori-app/staticfiles/;
expires 30d;
add_header Cache-Control "public, no-transform";
}
# メディアファイル(ユーザーアップロード画像など)も直接配信します
location /media/ {
alias /var/www/iori-app/media/;
expires 7d;
}
# それ以外のリクエストは Gunicorn に転送します
location / {
proxy_pass http://iori_gunicorn;
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;
# ファイルアップロードの最大サイズを 20MB に設定します
client_max_body_size 20M;
# 長時間の処理(PDF生成など)に備えてタイムアウトを延ばします
proxy_read_timeout 180s;
}
}
/etc/nginx/sites-available/terry-rails.conf
# -----------------------------------------------
# テリー・ボガードの Rails アプリ(Puma / ポート 3000)への
# リバースプロキシ設定です
# -----------------------------------------------
upstream terry_puma {
# Puma が Unix ドメインソケットで待ち受けている場合
server unix:/var/www/terry-app/tmp/puma.sock;
# TCP ポートで待ち受ける場合は下記のように指定します
# server 127.0.0.1:3000;
}
server {
listen 443 ssl;
server_name terry-app.example.com;
ssl_certificate /etc/letsencrypt/live/terry-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/terry-app.example.com/privkey.pem;
# Rails の public/ ディレクトリを直接配信します
root /var/www/terry-app/public;
# public/ に実ファイルが存在する場合はそのまま返します
# なければ Puma に転送します(Rack アプリの標準パターン)
try_files $uri/index.html $uri @terry_puma;
location @terry_puma {
proxy_pass http://terry_puma;
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;
}
# Action Cable(WebSocket)のエンドポイントです
location /cable {
proxy_pass http://terry_puma;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
/etc/nginx/sites-available/mai-dotnet.conf
# -----------------------------------------------
# 不知火舞の C# / .NET アプリ(Kestrel / ポート 5000)への
# リバースプロキシ設定です
# forwardedHeaders ミドルウェアと組み合わせて使います
# -----------------------------------------------
server {
listen 443 ssl;
server_name mai-app.example.com;
ssl_certificate /etc/letsencrypt/live/mai-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mai-app.example.com/privkey.pem;
location / {
# Kestrel が 5000 番ポートで待ち受けています
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# .NET の ForwardedHeaders ミドルウェアは X-Forwarded-Proto を参照して
# HTTPS かどうかを判定します
proxy_set_header X-Forwarded-Proto $scheme;
# SignalR(WebSocket)対応です
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
upstream でロードバランシングする(アンディ・ボガードのAPI)
# -----------------------------------------------
# アンディのAPIサーバーを2台でロードバランシングします
# weight で 2 号機に 2 倍のリクエストを振り分けます
# -----------------------------------------------
upstream andy_api {
server 192.168.1.10:8080 weight=1;
server 192.168.1.11:8080 weight=2;
# ヘルスチェック(Nginx Plus の場合)
# keepalive 16;
}
server {
listen 443 ssl;
server_name api.andy-app.example.com;
ssl_certificate /etc/letsencrypt/live/api.andy-app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.andy-app.example.com/privkey.pem;
location /api/ {
proxy_pass http://andy_api;
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;
# 動的な API レスポンスはバッファリングしない方が低レイテンシになります
proxy_buffering off;
}
}
実行するコマンドは次の通りです。
$ sudo nginx -t && sudo systemctl reload nginx nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful $ curl -I https://api.andy-app.example.com/api/health HTTP/2 200 server: nginx/1.24.0 (Ubuntu) content-type: application/json x-powered-by: Express
概要
リバースプロキシは、Nginx を公開エンドポイントとして配置し、Node.js・Django・Rails・C# などアプリサーバーを外部から隠蔽するアーキテクチャの中心的な役割を担います。proxy_set_header X-Real-IP と X-Forwarded-For によりクライアントの実 IP をアプリに伝えられるため、アクセスログ・レート制限・セキュリティ判定が正確に機能します。Unix ドメインソケット(unix:/run/app.sock)を使うと TCP ソケットより若干低レイテンシになり、Rails の Puma や Python の Gunicorn でよく採用されます。WebSocket を使うアプリ(Socket.io・Action Cable・SignalR 等)では proxy_http_version 1.1 と Upgrade / Connection ヘッダーの設定が必須です。Nginx 自体の概要と nginx.conf の基本構造については Nginxの設定 を、Django アプリの全体的なデプロイ手順については Djangoアプリのデプロイ を、Node.js / Express アプリのデプロイ(PM2 + Nginx)については Node.js / Expressアプリのデプロイ を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。