- 投稿日:
WSL上のUbuntuで動作するnginxでHTTPSに対応したサーバーを作る方法。実機でも同様の手順でいける
確認環境
Env | Ver |
---|---|
nginx | nginx/1.18.0 (Ubuntu) |
mkcert | v1.4.4 |
Ubuntu | 20.04.6 LTS |
Windows 11 | 22621.3880 |
手順
- Windows側にmkcertを入れる
- mkcertで証明書を作る
mkcert sandbox.test
- 以下のpemファイルが生成される
sandbox.test.pem
sandbox.test-key.pem
- 生成されたpemファイルを
/etc/nginx/conf.d/ssl/
に移動する /etc/nginx/conf.d/sandbox.test.conf
を作成し、以下のような記述をするserver { listen 443 ssl; client_max_body_size 100m; server_name sandbox.test; ssl_certificate conf.d/ssl/sandbox.test+1.pem; ssl_certificate_key conf.d/ssl/sandbox.test+1-key.pem; access_log /var/log/nginx/sandbox.access.log; error_log /var/log/nginx/sandbox.error.log; # ファイルホスト用 # location / { # root /usr/share/nginx/html/sandbox; # index index.html; # try_files $uri /index.html =404; # } # APサーバーへのリバプロ用 location ~ ^/.*$ { rewrite ^/.*$ / break; proxy_set_header X-Request-Path $request_uri; proxy_set_header X-Host $host; proxy_pass http://127.0.0.1:9999; } # fastcgi用 location ~ \.php$ { root /usr/share/nginx/html/sandbox; fastcgi_pass unix:/run/php/php8.0-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
- nginxを再起動する
sudo service nginx restart
他の端末に証明書を撒く方法
mkcertのRoot CAをエクスポートして他の端末に突っ込めば、他の端末でもpemが流用できる
- 投稿日:
HTTPヘッダを持たないHTTPリクエストはあり得るのか?というのを検証しているときに気づいた話。
RFC 7230ではHostヘッダを持たないHTTPリクエストは禁止されており、これを受けたサーバーは400応答を返すことを必須としている。
RFC 7230:Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and RoutingのHostより
A client MUST send a Host header field in an HTTP/1.1 request even if
the request-target is in the absolute-form, since this allows the
Host information to be forwarded through ancient HTTP/1.0 proxies
that might not have implemented Host.
A server MUST respond with a 400 (Bad Request) status code to any
HTTP/1.1 request message that lacks a Host header field and to any
request message that contains more than one Host header field or a
Host header field with an invalid field-value.
なお、Node.jsのHTTPサーバー機能ではHostヘッダーのない要求を受け入れることができる。
http.createServer([options][, requestListener])を見ると、以下のようにrequireHostHeader: false
を渡すことで実現可能だ。規定値はtrue
であるため、基本的にはHostヘッダーなしの要求は400応答が返される。
import http from 'node:http';
http
.createServer({requireHostHeader: false}, (req, res) => {
console.log(req.headers);
res.statusCode = 200;
res.end();
})
.listen(3000);
nginxにおいてもHostヘッダーなしの要求は以下の応答が返されたため同様と思われる。
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.26.0</center>
</body>
</html>
但し、nginxにおいてHostなしの要求を許容する方法は見つからなかった。Server namesによるとserver_name "";
とすることで出来そうに見えたが、これは機能させることができず、400応答が返された。
- 投稿日:
adiaryをnginxの上で動作させつつ開発する方法をメモしておく。
前提条件
動作URLとしてはhttps://hoge.example.com/adiary
のようなサブドメイン付きのサブディレクトリとする。
adiaryはネイティブでfcgiをサポートしているらしいが、そこは無視して一般的な環境で起動するのがゴール。
SSLで動かす設定を書いているため、nginxでローカル開発環境向けのhttps環境を作るも参考にすること。
特別な設定は不要で、サブドメインモードにしなくとも動く。
確認環境
Env | Ver |
---|---|
OS | Ubuntu 22.04.3 LTS |
nginx | 1.24.0 |
fcgiwrap | 1.1.0-12 amd64 |
adiary | 3.50n |
手順
nginxはインストールされており、既に稼働している状態として話を進める
# adiaryを格納するディレクトリを作成する
sudo mkdir -p /usr/share/nginx/html/sites
# 既にどっかに展開済みのadiaryをディレクトリに突っ込む
sudo cp -R adiary /usr/share/nginx/html/sites
cd /usr/share/nginx/html/sites
# 所有権とパーミッションの調整
sudo chwon -R $USER:$USER adiary/
cd adiary/
sudo chmod -R 777 __cache/
sudo chmod -R 777 data/
sudo chmod -R 777 pub/
# Image::Magickを入れる
sudo apt install -y libimage-magick-perl
# nginxでCGIを動かすために、fcgiwrapをインストールする
sudo apt install fcgiwrap
# /etc/nginx/conf.dに設定ファイルを作成
cat <<'EOF' | sudo tee -a /etc/nginx/conf.d/hoge.example.com.conf
server {
listen 443 ssl;
server_name hoge.example.com;
ssl_certificate ssl/hoge.example.com.pem;
ssl_certificate_key ssl/hoge.example.com-key.pem;
access_log /var/log/nginx/hoge.example.com.access.log;
error_log /var/log/nginx/hoge.example.com.error.log;
# マルチテナント用にこう書いている
root /usr/share/nginx/html/sites;
# /usr/share/nginx/html/sites/adiaryにadiary一式が入っている想定
location / {
index index.html;
}
location /adiary {
index adiary.cgi;
}
# fastcgi用
location ~ \.cgi$ {
gzip off;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
EOF
# nginxの設定を再読み込みする
sudo service nginx restart
トラブルシューティング
403エラーで起動せず、エラーログにパスがないと出る
以下のコマンドを叩き、パスが整合するまで設定を調整する
sudo strace -f -e trace=file -p $(pidof fcgiwrap)
- 投稿日:
書いてなさ過ぎて忘れるので備忘録として書き出しておく。必要最低限の設定なので要件が他にある場合は追加が必要。
React(SPA)
SPAなのでパスがなければ全部index.htmlに飛ばす。原理はどれも同じなのでVueやAngularなどのSPAもこれで行けると思う。ケツの=404
がないと無限リダイレクトを起こす。
server {
listen 80;
location / {
root /path/to;
index index.html;
try_files $uri /index.html =404;
}
}
Next.js(SSR)
SSRなのでNext.jsのサーバープロセスにリバースプロキシする。別に直結してもいいが手前にルーティング機構があるほうが便利である。
map
ステートメントがあるのは、これがないとiOS Safariでアクセスできないため
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:3000;
}
}
Next.js(SSG)
SPAではないのでパスがなければ同名のhtmlファイルに飛ばす。ケツの=404
がないと無限リダイレクトを起こす。
server {
listen 80;
location / {
root /path/to;
index index.html;
try_files $uri $uri.html =404;
}
}