Nginx のリバースプロキシ設定
このノートでは、JupyterHub などのアプリを使うときに、Nginx でリバースプロキシ設定を行う方法をまとめています。
対象アプリは、JupyterHub、Streamlit、Code-Server、MyST、WebMO。
Nginx の設定項目
まず、Nginx の設定項目について。
server
ブロック
server
ブロックは、特定のドメイン名や IP アドレスに対してリクエストを処理するために使用。例えば、以下のように example.com
の HTTP リクエストを処理する設定ができます。
server {
listen 80;
server_name example.com;
location / {
# リクエストをどのように処理するか指定
}
}
listen 80;
- サーバーが HTTP(ポート 80)でリクエストを受け付けることを示します。
80
: HTTP の標準ポート。443
: HTTPS の標準ポート。SSL 設定を有効にする場合はポート 443 を使用。
- サーバーが HTTP(ポート 80)でリクエストを受け付けることを示します。
server_name example.com;
- このサーバーブロックが処理するドメインやサブドメインを指定。この例では、
example.com
というサブドメインにアクセスしたときにこのサーバーブロックを適用。- 複数のドメインを指定する場合は、スペースで区切って追加できます(例:
server_name example.com www.example.com;
)。
- 複数のドメインを指定する場合は、スペースで区切って追加できます(例:
- このサーバーブロックが処理するドメインやサブドメインを指定。この例では、
location
ブロック
location
ブロックは、特定のパス(URI)に対するリクエストをどのように処理するかを定義。
location / {
# 指定されたパスに対するリクエストを処理
}
location / {}
- ルートパス(
/
から始まる全てのリクエスト)を処理。サブディレクトリや他のパス(例:/streamlit
)を指定する場合、location /streamlit/ {}
のように記述。
- ルートパス(
proxy_pass
proxy_pass
は、リクエストを別のサーバー(バックエンド)に転送するために使用。リバースプロキシとして Nginx が機能する場合、この設定を使って、リクエストをバックエンドアプリケーション(例: Streamlit や JupyterHub)に転送します。
proxy_pass http://127.0.0.1:8501;
http://127.0.0.1:8501;
127.0.0.1
はローカルホスト(自分自身)を指し、Streamlit アプリがポート8501
で動作している場合に使用されます。- この設定により、外部のクライアントは
example.com
にアクセスし、実際には127.0.0.1:8501
で動作している Streamlit アプリが応答。
proxy_set_header
proxy_set_header
では、バックエンドサーバーに対して追加の HTTP ヘッダーを送信。これにより、元のクライアント情報などが保持されます。
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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- クライアントの元々の IP アドレスをバックエンドサーバーに伝えるために使用。リバースプロキシを経由すると、バックエンドは Nginx の IP アドレスしか見えなくなりますが、この設定でクライアントの本当の IP を保持できます。
proxy_set_header Host $http_host;
- クライアントがリクエストした元のホスト名(この例では
example.com
)をバックエンドサーバーに伝えます。これにより、バックエンドでホスト名に基づいた処理が正しく行われます。
- クライアントがリクエストした元のホスト名(この例では
proxy_http_version 1.1;
- HTTP/1.1 プロトコルを使用してリクエストを転送することを指定。
1.1
を指定することで、WebSocket のサポートなど、HTTP/1.0 では利用できない機能を使用できます。
- HTTP/1.1 プロトコルを使用してリクエストを転送することを指定。
proxy_set_header Upgrade $http_upgrade;
とproxy_set_header Connection "upgrade";
- WebSocket のサポートを有効に。これにより、HTTP プロトコルのアップグレードが可能になり、リアルタイム通信が必要なアプリ(例えば Streamlit や他の WebSocket を使用するアプリケーション)が正しく機能します。
rewrite
(サブディレクトリの場合)
サブディレクトリを使用している場合、パスの書き換えを行うために rewrite
を使用します。バックエンドアプリケーションがルートパス(/
)で動作している場合、サブディレクトリパス(例: /streamlit/
)を正しく処理するためにこの書き換えが必要。
rewrite ^/streamlit/(.*) /$1 break;
rewrite
location /streamlit/
のようなサブディレクトリでプロキシを使用する場合、Streamlit がパスに/stream/
が含まれることを想定していないため、リクエストパスを書き換える必要があります。- この書き換えでは、
/streamlit/
以下のパスを/$1
(つまり/
から始まる新しいパス)に変更し、サーバーが正しくリクエストを処理できるようにします。
正規表現
^/streamlit/(.*)
の^
はリクエストの先頭を示し、(.*)
は/stream/
以下のすべてのパスをキャプチャ。
break
- 書き換えが行われた後にそれ以上の処理を行わないことを指定。
return
return
ディレクティブは、Nginx がクライアントに対して即座にレスポンスを返す場合に使用します。
return 301 https://$host$request_uri;
return 301
- クライアントに対してリダイレクトを指示。301 は「恒久的なリダイレクト」を示し、SEO などの観点からも推奨されます。
https://$host$request_uri
にリダイレクトすることで、HTTP でのリクエストを HTTPS にリダイレクト。$host
はリクエストのホスト名、$request_uri
はリクエストされた URI(パス)。
その他の重要なディレクティブ
access_log
とerror_log
- Nginx がアクセスログとエラーログを記録するファイルを指定。トラブルシューティングや分析に役立ちます。
access_log /var/log/nginx/streamlit.access.log;
error_log /var/log/nginx/streamlit.error.log;
各アプリケーションの設定方法
JupyterHub
サブドメインを使用する場合(例: jupyter.example.com
)
server {
listen 80;
server_name jupyter.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
サブディレクトリを使用する場合(例: example.com/jupyter
)
server {
listen 80;
server_name example.com;
location /jupyter/ {
rewrite ^/jupyter/(.*) /$1 break;
proxy_pass http://127.0.0.1:8000/;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- JupyterHub は WebSocket を使用するため、
Upgrade
ヘッダーとConnection
ヘッダーが必須。
Streamlit
サブドメインを使用する場合(例: streamlit.example.com
)
server {
listen 80;
server_name streamlit.example.com;
location / {
proxy_pass http://127.0.0.1:8501;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
サブディレクトリを使用する場合(例: example.com/streamlit
)
server {
listen 80;
server_name example.com;
location /streamlit/ {
rewrite ^/streamlit/(.*) /$1 break;
proxy_pass http://127.0.0.1:8501/;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- Streamlit も WebSocket をサポートしているため、
Upgrade
ヘッダーが必要。
Code-Server の設定
サブドメインを使用する場合(例: code.example.com
)
server {
listen 80;
server_name code.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
サブディレクトリを使用する場合(例: example.com/code
)
server {
listen 80;
server_name example.com;
location /code/ {
rewrite ^/code(/.*)$ $1 break;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
}
}
- Code-Server も WebSocket を使用するため、適切なヘッダー設定が必要です。
MyST(myst start
)
myst start
コマンドでサーバーを起動し、それにアクセスする場合。
サブドメインを使用する場合(例: myst.example.com
)
server {
listen 80;
server_name myst.example.com;
location / {
proxy_pass http://127.0.0.1:4000; # MyST が 4000 番ポートで動作していると仮定
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
サブディレクトリを使用する場合(例: example.com/myst
)
server {
listen 80;
server_name example.com;
location /myst/ {
rewrite ^/myst/(.*) /$1 break;
proxy_pass http://127.0.0.1:4000/;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
myst start
コマンドを使用してサーバーを起動した後、そのポート(例: 4000)に対してリバースプロキシを設定。
WebMO
WebMO は CGI を使用しているため、少し異なる設定が必要。
サブドメインを使用する場合(例: webmo.example.com
)
server {
listen 80;
server_name webmo.example.com;
root /home/webmo/public_html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.html;
}
location ~ \.cgi$ {
root /home/webmo/cgi-bin;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /var/www/webmo/cgi-bin$fastcgi_script_name;
include fastcgi_params;
}
}
サブディレクトリを使用する場合(例: example.com/webmo
)
server {
listen 80;
server_name example.com;
location /webmo/ {
rewrite ^/webmo/(.*) /$1 break;
root /var/www/webmo/public_html;
index index.html index.php;
try_files $uri $uri/ /index.html;
}
location ~ /webmo/.*\.cgi$ {
root /var/www/webmo/cgi-bin;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /var/www/webmo/cgi-bin$fastcgi_script_name;
include fastcgi_params;
}
}
- WebMO では
fcgiwrap
を使用して CGI スクリプトを実行します。 - サブディレクトリの場合、WebMO が
cgi-bin
ディレクトリ内のスクリプトを正しく実行できるようにrewrite
とroot
設定を調整。
設定ファイルの有効化
設定ファイルを有効にするために、/etc/nginx/sites-enabled/
にシンボリックリンクを作成します。
sudo ln -s /etc/nginx/sites-available/streamlit /etc/nginx/sites-enabled/
Nginx 設定のテストと再起動
Nginx 設定をテストし、正しく設定されているか確認。
sudo nginx -t
問題がなければ、Nginx を再起動。
sudo systemctl restart nginx
サブドメイン vs サブディレクトリ
サブドメインの場合
- サブドメインごとに異なるサービスを独立して管理することができます。
- 各サブドメインに SSL 証明書を適用することが容易。
サブディレクトリの場合
- 一つのドメイン内に複数のサービスを提供する場合に便利。
- パスの書き換え(
rewrite
)が必要な場合があります。