最初の回でApacheとの比較で記述したように、nginxではプログラムの実行を行うことが出来ません。
よって、PHPで書かれたプログラムをnginxで実行するためにはPHPを実行するための環境を別途で用意する必要があります。
今回はnginxでPHPを実行するための基本的な設定を行ってみましょう。
最初の回でApacheとの比較で記述したように、nginxではプログラムの実行を行うことが出来ません。
よって、PHPで書かれたプログラムをnginxで実行するためにはPHPを実行するための環境を別途で用意する必要があります。
今回はnginxでPHPを実行するための基本的な設定を行ってみましょう。
最近ではWebサーバは基本的にSSLで暗号化した上で通信されています。(ここではSSLと言っていますが実際にはその後継のTLS接続となります)
URLがhttpsから始まるサイトがそれです。
暗号化しないと通信経路上に居る悪意のあるユーザに情報を引っこ抜かれる恐れがあります。
もちろん、パスワードのかかっていないような誰でも見れることが前提のWebサーバであれば理論上あまり意味は無いのですが、最近のブラウザは暗号化されていないサイトには警告を出したりするので、理由がなければ対応した方が良いかと思います。
今回は「Let’s Encrypt」という証明書を取得できるサービスを使って暗号化したいと思います。(無料で手に入ると言っても怪しいものではなく、有名どころのセキュリティ企業やWeb企業が出資しているものですのでご安心を)
※この記事では前提としてドメインを持っていること(DDNSサービスなどの無料ドメインでも可能です)、インターネットからサーバにアクセスできることが必要です。このサイトでは未だドメイン取得やサーバの公開(ルータの設定)については取り扱っていませんので、他のサイトを参考に行ってください。
HTTPS化を行うに当たってはHTTPの80番ポートに加え、HTTPSの443番ポートの開放も必要です。
以下のコマンドを実行します
[root@localhost ~]# firewall-cmd --add-service=http --add-service=https --permanent
[root@localhost ~]# firewall-cmd --reload
※既にポートが開放されている場合はWarningが出ますが、特に問題はありません。
ポートの開放について詳しくは以下のページを参考にしてください。
CertbotはLet’s Encryptの証明書を取得するためのソフトウェアです。
CertbotのインストールにはEPELリポジトリが必要となります。
EPELリポジトリは以下のコマンドで追加できます。
[root@localhost ~]# dnf install epel-release
EPELリポジトリを追加したら、Certbotをインストールします。
[root@localhost ~]# dnf install certbot
python3-certbot-nginx
はWebサーバにnginxを使っている場合にWebサーバを止めないまま証明書取得を行えるようにするためのモジュールです。
自動更新を行うのに必要なのでインストールしておきましょう。(さもないと3ヶ月おきにnginxを停止して、証明書を更新して、nginxを起動し直す羽目になります)
証明書を取得するコマンドは以下の通りです。(このコマンドはnginxが起動している必要があります)
[root@localhost ~]# certbot --nginx
certbot
: Certbotを実行するコマンドです。そのまんまです。--nginx
: 起動しているnginxを使って証明書を更新すると言うオプションです。このコマンドを実行すると対話的に設定を進められます。(質問に答えていくことで証明書を取得できます)
また、自動的にnginxの設定にHTTPS化の設定を付け加えてくれます。
ただ、自動設定なので稀に不具合が出るようです。
もし、nginxの設定は自分で行いたいという場合は以下のようにコマンドに certonly
を付け加える事で自動設定を無効化することもできます。
[root@localhost ~]# certbot certonly --nginx
ただ、自動設定で不具合が起きても自動で設定される前の設定に復元出来ます。
このため、今回はまず自動設定を試してみたいと思います。(設定の復元方法は4-2に記載しています)
コマンドを実行した際に出てくる質問の内容は以下の通りです<>内に質問の概要を載せています。
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): <メールアドレスを記載>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: <規約に同意するにはaを入力(同意しない場合は証明書取得不可)>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: <Let's Encryptの情報をメールに送っても良いか(Nで入力しても証明書取得可)>
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: exsample.com
2: www.exsample.com
(nginxのserver_nameに設定されているドメインが全て羅列される)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):<どのドメインに対して証明書を取得するか(複数に対して取得する場合は半角スペース区切りで番号を羅列、全てに対して取得する場合は空欄で可)>
これで証明書の取得及びnginxの設定は完了です。
nginxを再起動してから、ブラウザでサーバに接続してみてください。
[root@localhost ~]# systemctl restart nginx
ブラウザに表示されるアドレスの先頭が http://
から https://
になっていれば成功です。
なおこの時、ローカルIPアドレス(192.168.で始まるIPアドレス)で接続するとエラーが出るようになります。
証明書を取得したドメインからアクセスするようにしましょう。
また、同じLAN内からは特別に設定しない限りドメインでアクセスすることは出来ません。
接続確認はWifiに繋いでいないスマートフォンなどで行うようにしましょう。
自動更新によってnginxの設定ファイル conf.d/default.conf
の設定が以下のように変わっていました。
※変わる前の設定は以下ページを参照してください。
※ localhost
とあった部分が example.com
に変わっているのは手動です。これはそもそもlocalhostでは証明書を取れないためです。
server {
server_name example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com;
return 404; # managed by Certbot
}
まず、serverコンテキストが1つ増えています。
上のserverコンテキストは listen 443 ssl
、下は listen 80
となっています。
先に下の listen 80
とあるコンテキストから確認してみましょう。
自動設定で追加された設定は # managed by Certbot
と記載があるのでその設定だけを追っていきます。
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
この設定はもしアクセスしてきたURLのドメインが正しいドメインの場合、httpsの同じアドレスに転送するというものになります。HTTPではアクセス出来なくさせるわけですね。
また、最下部の return 404; # managed by Certbot
は正しくない場合は404エラーを返すという事を表しています。
次に上のコンテキストですね。
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
これは証明書の場所を指定する項目です。実際に ls
コマンドを使って確認すると、そういったファイルが存在していることが確認できます。
正確にはこのファイルはエイリアス(Windowsでいうショートカット)で実在のファイルではありません。
これは証明書を更新する度に証明書のファイル名が変わるので、その度に設定修正をする手間を省く為になります。
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
これは証明書と対になる秘密鍵を指定する項目です。こちらも証明書同様にエイリアスとなります。
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
これはSSLに関する設定を読み込ませる部分です。後で中身を確認します。
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
これは証明書の共有を行う為の鍵を指定するものとイメージしてください。
続いて、先程の /etc/letsencrypt/options-ssl-nginx.conf
の中身を確認してみましょう。
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
では以下に解説します。
ssl_session_cache shared:le_nginx_SSL:10m
ssl_session_cache
: SSLセッションのキャッシュ(接続の履歴)を記憶するか。記憶する場合は同じセッションがあった際に使い回せて処理効率が上がる。shared
: 記憶して、かつnginx内で共有をする設定。le_nginx_SSL
: shared
の場合のみ設定。任意の名前を付ける。同じ名前が付いている場合は別のserverコンテキストで設定されたものともキャッシュが共有される。10m
: shared
の場合は設定。キャッシュのサイズを指定する。1メガバイトで4000セッションほど保存できるので、10mだと40000キャッシュ程度。個人サーバではそんなに要らない気も……ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
最終的にどの暗号を選択するかの優先選択権をサーバが持つという設定です。そもそも危ない暗号は使えない設定にしているので、クライアントに好きな暗号を選ばれても問題ないということでoffになっているようです。
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
利用可能にする暗号の種類をコロン区切りで列挙しています。一定以上の強度を持つ暗号のみ列挙されています。
自動設定のロールバックは以下のコマンドで行うことが出来ます。
[root@localhost ~]# certbot --nginx rollback
ファイルの変更毎に復元のチェックポイントを設けているようなので、上記のコマンドを以下のエラーが出るまで繰り返し実行しましょう。
Certbot hasn't modified your configuration, so rollback isn't available.
設定が復元されたら4-1の内容を参考に、自分で設定を行ってみましょう。
Let’s Encryptの自動更新は以下のコマンドで設定できます。
[root@localhost ~]# systemctl enable --now certbot-renew.timer
Created symlink /etc/systemd/system/timers.target.wants/certbot-renew.timer → /usr/lib/systemd/system/certbot-renew.timer.
--now
: enable
コマンドを使うときに設定することで、 start
も同時に実行されるというオプションです。ちゃんと設定されているか確認する際には以下のコマンドを実行してください。
[root@localhost ~]# systemctl list-timers | grep certbot
Sun 2020-07-12 01:04:24 JST 7h left n/a n/a certbot-renew.timer certbot-renew.service
list-timers
: 自動実行されるタスクの一覧を表示します。|
: パイプと呼ばれ、この記号の前のコマンドで出力された内容をこの記号の後のコマンドで処理します。今回の場合は systemctl list-timers
で出力されたリストを grep certbot
で処理すると言った具合です。grep certbot
: grep
は引数の文字列を含む行だけを出力します。今回はcertbotを含む行だけを抜き出す事になります。また、自動更新で失敗しないように事前に更新に問題が無いか以下のコマンドで確認しましょう。
[root@localhost ~]# certbot renew --dry-run
renew
: 証明書の更新を行うコマンドです。前回と同じ方法証明書を再取得し、更新してくれます。--dry-run
: 実際に証明書を取得せず証明書が取れそうかを確認するためのオプションです。証明書の取得は週に5回までしか行えないという制約があるので、このオプションでテストだけを行います。ここで、エラーが出なければ問題なく証明書が更新できるはずです。
新しいドメインでサーバにアクセスできるようにしたとき、またはもう使わないドメインが出たとき、わざわざ証明書を作り直すのは面倒です。
以下のコマンドを使うことで、証明書で使えるドメインを追加・削除することが出来ます。
[root@localhost ~]# certbot certonly --cert-name [証明書名] -d [証明所に含みたいドメイン名] --nginx
--cert-name [証明書名]
: ドメインを追加・削除したい証明書の名前を入力します。証明書の名前は certbot certificates
で表示される証明書一覧の Certificate Name
の項目となります。-d [証明書に含みたいドメイン名]
: 証明書に含みたいドメイン名を半角スペースかカンマ区切りで羅列します。新たに記載されたドメインは追加され、記載されていないドメインは削除されます。今回はnginxでWebサイトをHTTPS化する方法を説明しました。
実際の設定はソフトウェアを1つインストールしてコマンドを1つ実行して聞かれたことに答えるだけで良かったりするのですが、問題があったときのためにもちゃんと設定を理解して必要に応じて変更できるようにしておきましょう。
次回はnginxでPHPを使うための設定に触れたいと思います。
前回はnginxのインストールを行い、サンプルページを表示させる所まで行いました。
ここでサンプルページのファイルを差し替えれば、自分のWebページを公開することが出来ます。
しかし、サンプルページはどこにあるのでしょう。
また、もともとサンプルページが置いてあった場所以外にはWebページに表示するファイルを置くことは出来ないのでしょうか。
設定ファイルを確認・編集することでこのような問題を解決出来ます。
nginxの設定ファイルは nginx.conf
と conf.d/
ディレクトリ内にある拡張子が .conf
のファイルに分かれています。
nginx全体に関わるメインの設定ファイル nginx.conf
、各バーチャルホストの設定が conf.d/
内のファイルとなります。
conf.d/
内の設定ファイルは後述する include
部分によって nginx.conf
に読み込まれます。
nginxの設定はコンテキストと呼ばれる{ }で囲われたブロックの入れ子になっています。コンテキストによって設定できる項目が異なります。
主なコンテキストは以下の通りです
www.example.com
と blog.example.com
で両方とも同じサーバに接続されるものの、前者はHTML直置きで作ったWebサイトに、後者はWordPressで作ったブログにといった具合です。これがバーチャルホストです。mainコンテキスト内にeventコンテキストとhttpコンテキストが存在し、httpコンテキスト内には複数のserverコンテキストが存在し、serverコンテキスト内には複数のlocationコンテキストが存在するという構成です。
実際に設定ファイルを見ていきましょう。
なお実際の設定ファイルよりも簡略化されていますが、省いているのはオプション的な設定のため、掲載している設定ファイルでも動くようになっています。
nginxの公式リポジトリからインストールした場合、 /etc/nginx/nginx.conf
がメインの設定ファイルとなります。
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
まずはmainコンテキストです。
/var/log/nginx/error.log
に出力します。次はeventコンテキスト。
worker_process
で何個まで接続を許すかという設定です。とりあえず個人サーバの場合は一旦1024で十分でしょう。次にhttpコンテキストです。
application/octet-stream
は任意のバイナリデータ、つまり何か分からないということです。普通はその上の行でinclude(後述)されている /etc/nginx/mime.types
内で設定されているはずなので、そこからあぶれた未知のファイルという事ですね。/var/log/nginx/access.log
にすぐ上のlog_formatで設定した main
という出力形式で出力する設定になっています。include /etc/nginx/mime.types;
は拡張子とMIMEタイプの関連付けを行うファイルで、 include /etc/nginx/conf.d/*.conf;
は conf.d/
内にあるバーチャルホストの設定を読み込むものになります。つまり、conf.d/
内の設定ファイルは全てこの部分に展開される事になります。serverコンテキストと、locationコンテキストはnginx.conf
内には記載がありませんでした。
これは、バーチャルホスト毎に /etc/nginx/conf.d/
内に設定ファイルを作ってincludeでhttpコンテキスト内に読み込ませた方が管理が楽だろうという考え方からです。
nginx.conf
にはserverコンテキストを書き込めないという事ではないので、例えばバーチャルホストがひとつだけでわざわざ別のファイルを作って管理する必要もない場合は直接 nginx.conf
に書き込むことも出来ます。
nginx.conf
内に記載されている include /etc/nginx/conf.d/*.conf;
によって読み込まれる設定ファイルの一つです。
他にも同じディレクトリに .conf
と拡張子の付くファイルを作成すると、同様に nginx.conf
に読み込まれます。
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
では、serverコンテキストから見ていきましょう
server_name
で設定されていないアドレスで接続してきた場合に利用したいコンテキストにはdefault_server
を付けます。 default_server
が付いたコンテキストがない場合は最初のserverコンテキストに繋がってしまいます。listen 443 ssl http2 default_server;
といった具合になります。www.example.com
と記載すると、www.example.com
宛てに接続したときだけこのコンテキストの設定が適用されて、IPアドレスで直接接続してきたときには適用しないといった具合です。http://localhost
で500,502,503,504エラーが発生した際にはhttp://localhost/50x.html
に遷移することになります。最後にlocationディレクトリです。
locationディレクトリの設定はlocationの直後に書かれているアドレスの時に有効になります。
例えばサーバのアドレスが http://localhost
の場合で、location /home { }
に囲われた部分は http://localhost/home
の時に適用されるといった具合です。
では、設定の中身を見ていきましょう。
/usr/share/nginx/html/hogehoge/webpage.html
というファイルがあった場合、 http://localhost/hogehoge/webpage.html
に接続すれば見ることが出来ます。http://localhost/index.html
宛てに接続してくれれば困ることは無いですが、多くの場合 http://localhost/
で止めることが多いのではないでしょうか。こういうときにどのファイルを表示すべきかを指定するものです。今回説明したのは最低限の、静的Webページを表示するための設定となります。
他にも、PHPの実行を他に回すための設定や、SSLの設定、キャッシュの設定などなど様々な設定がありますが、これは随時説明していきたいと思います。
今回は、
の二点だけ最低限覚えてもらえればと思います。
次回はWebページの暗号化(SSL/TLS接続の有効化)について説明したいと思います。