独自ドメインを取得してNginxでSSL設定まで行う
さくらVPS等のサーバを契約して、IPでWebサイトにアクセスできるようになったら、覚えやすいドメイン名を取得して、更にはSSLによる暗号化通信を実現する必要がある。この作業を終えてようやくWebサイトとしての体裁が整ったといえる。
今回はドメインの取得をし、SSLをLets Encryptを使って設定するところまでを行う。
独自ドメインの取得
まずは独自ドメインを取得しよう。ドメイン管理サービスはGMOのお名前.comが比較的安くておすすめである。また、東証一部上場の企業が管理しているので安全度が高いということもあり、私は好んで使っている。
独自ドメインは何でも良いが、短くて覚えやすいことが重要である。グーグルで検索したときの検索画面にもドメイン名は表示されているが、長いとドメイン自身、あるいはドメインに続くパスの部分が途切れてしまう可能性が高くなり、クリック率に影響を及ぼしかねないため、10文字を超えるドメインはできる限り避けるべきである。
ともあれ年額1000円程度払えば簡単にドメインは取得できるのでお手軽である。
DNSの設定
次にIPアドレスとドメイン名を紐づけるためにDNSを設定する。DNSはDomain Name Serverの略で、ドメイン名を指定するとIPアドレスを返してくれるサーバである。
ドメイン管理するサイトの設定画面(今回のケースの場合お名前.comの管理画面)からDNSサーバの設定をすることができる。
一般的な設定として当サイトでは下記のAレコードを2つ設定している。
ホスト名 | TYPE | TTL | VALUE |
---|---|---|---|
infltech.com | A | 3600 | 153.126.175.201 |
www.infltech.com | A | 3600 | 153.126.175.201 |
- ホスト名は取得したドメイン名のことである。サブドメインとしてwwwをつけてアクセスできることも一般的であるのでwwwあり版も設定する。
- TYPEはドメイン名と紐づける情報の種類のこと。レコードとも呼ばれる。前述のようにドメインとIPアドレスを結びつけるレコードはAレコードと呼ばれる。この他ドメインとその別名を結びつけるCNAME、ドメインとメールアドレスを結びつけるMXレコードなどがあるがここではひとまずAレコードのみを設定すれば事足りる。
- TTLはDNSの問い合わせ結果をサーバ側でキャッシュしておく時間。Time To Liveの略であり、キャッシュが生きている期間と捉えればよい。キャッシュは余計なサーバ問い合わせを減らし、負荷を下げる役割を果たす。キャッシュ期間(=TTL)が短いとサーバ負荷が高くなり、アクセス時間にも多少影響が出る。デフォルト3600秒だが、デフォルトのままで基本的に問題はない。
- VALUEは運用しているサーバの固定IPアドレスである。これで取得した独自ドメインと、自サーバのIPが紐づけられる。
TTLが短ければ設定変更時にも短い間隔で設定が反映されるのではないかとふと思ったが、設定反映時間とキャッシュ保存期間は別らしい。
10回ぐらいドメインを取ってDNS設定をしたことのある私の経験だと、大抵1時間程度で設定が反映されている。最大72時間とのことなので時間がかかる場合は気長に待とう。
Nginxでwww.exmaple.comをexample.comへリダイレクトさせる。
さてドメインを取得してDNSの設定も終えたので、あとは待っていればドメイン名でアクセスできるようになる。しかしサーバ側でもいくつか追加で設定することがある。そのうちの一つがwww.example.comをexample.comにリダイレクトする設定である。
理由は2つあり、一つはSEO上の理由である。検索エンジンはwww.example.comとexample.comを異なるサイトだと見なしてしまうため、それぞれに対してリンクが張られていると分散してしまい、評価が集まりにくい。それゆえexample.comに統合した方が良い。www.example.comに統合する手段もあるが、より短いexample.comの方が良いだろう。
もう一つはブランド上の理由である。2つの名前が混在するとやや覚えにくくなり認知度が下がる可能性が考えられる。
このように機械も人も認識しにくいため一つにまとめてしまうのが良いのである。完全に一つにしてwwwではアクセスできなくすることも考えられるが、wwwでアクセスしてくる人も一定数いると考え、完全には一つにせずリダイレクトをする選択肢を取ることとする。
前置きは長くなったが設定に入ろう。設定自体は簡単で、wwwを301でリダイレクトするためだけのserverを一つ追加してやれば良い。
server {
listen 80;
server_name www.example.com;
return 301 http://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
...
}
ここで301はMoved Permanentlyの略で、永久にwww.example.comはexample.comへリダイレクトさせますよという意味である。ドメインを変更してサイトの引っ越しをする時にもよく使われる。301を使うことで、ページの検索エンジンに対する評価も移動させることができるので301以外は使わないようにしよう。
Lets EncryptでSSLの設定
次にLet's Encryptの設定を行う。Let's Encryptは多くの企業が出資して作られているSSLを普及させる団体である。Webの健全な発展のために無料で暗号化通信の設定が行える。
静的サイトはパスワードも保存しないしSSLなんかいらないのではと思う人もいるかもしれない。確かにその通りだと思う。しかしGoogleが検索エンジンでページを評価する時にSSLの設定がされているかどうかを対象に含むと宣言しているのでしないわけにもいかないのである。
Certbotを導入
Let's Encryptのページを進めると、自動でSSLを設定してくれる[Certbot]に行き当たる。シェルを利用できるほとんど全ての人が利用でき、環境に合わせて自動的にSSLの設定を行ってくれるのでおすすめの方法である。
今回はNginxとCentOS7なのでそれを選択すると、設定に必要な一覧が表示される。あとは手順に従って進めていけば良い。
1.SSH into the server
まずはSSHでサーバに入る。コマンド操作でCertbotを有効にするのが基本である。
2.Enable EPEL repo
次にEPEL repoを有効にしよう。EPELはExtra Packages for Enterprise Linuxの略で、直訳すると企業用Linux用の拡張パッケージである。
RedHat社によって開発、販売されているLinuxディストリビューションをRHEL(レル, Red Hat Enterprise Linux)と言うが、そのRHELの拡張パッケージを取得するためのリポジトリを使えるようにする。
CentOSは無償なのでEPELリポジトリを使えるようにする設定には違和感があるかもしれない。しかし、CentOSはRHELから無償部分を取り出して作られたディストリビューションのため、違いはそれほどなく、RHEL同様にEPELにより取得したソフトウェアを問題なく動作させることができる。
説明が長くなったが、EPELリポジトリを下記コマンドで利用可能にする。
$ sudo yum install epel-release
- Install Certbot
CertBotを有効化する。
$ sudo yum install certbot python2-certbot-nginx
コマンドを叩きSSL設定のスクリプトを起動
- get and install your certificates
コマンド一発でNginxの設定をSSL対応してくれるというコマンド。叩くと幾つか質問をされるので内容をコメント付きで載せていく。
$ sudo certbot --nginx
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):
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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 #利用規約に同意するか?YesなのでAを選択してEnter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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:
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: example.com
2: www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
# HTTPS化したいのは1か2のどちらと聞かれている?Which namesと複数形で聞かれているので分かると思うが複数選択することが可能。空欄の場合は全選択になる。今回は短いURLの1番に統一したいので1を選択する。
blank to select all options shown (Enter 'c' to cancel):1
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for infltech.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/infltech.conf
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# HTTPのリクエストをHTTPSへリダイレクトするかを聞かれている。全てをHTTPSへ置き換えたいので2を選択する。
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/infltech.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://infltech.com
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=infltech.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/infltech.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/infltech.com/privkey.pem
Your cert will expire on 2020-06-15. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
# 寄付してねと言われている。したいところだけど英語サイトでクレジットとか登録するの怖くてできない。。。
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
これで一通りの設定が完了した。
Nginxの変更点をざっと確認
自動で書き換えられるため、既存の設定が壊されていないか心配である。一応設定がどう変わったのかを確認しておこう。
server {
+ #80番でListenしていたのが消されている。
- listen 80;
...(中略)
location / {
proxy_pass http://puma;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
+ #SSLの設定が新規に追加されている
+ listen 443 ssl; # managed by Certbot
+ ssl_certificate /etc/letsencrypt/live/infltech.com/fullchain.pem; # managed by Certbot
+ ssl_certificate_key /etc/letsencrypt/live/infltech.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
}
+ # 80番ポート(http)の場合は301リダイレクトでhttpsに行くように設定されている
+server {
+ if ($host = infltech.com) {
+ return 301 https://$host$request_uri;
+ } # managed by Certbot
+
+
+ listen 80;
+ server_name infltech.com;
+ return 404; # managed by Certbot
+}
いい感じで書き換わってくれている。次に進もう。
SSLの有効期限が切れた時に自動更新される処理を記述
5 Let's Encryptの証明書の有効期限は90日である。そのため、定期的に証明書切れが無いかをチェックする必要がある。幸い自動チェックのためのおすすめスクリプトをLet's Encrypt側で準備しているので、その設定を行う。
$ echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
コマンドを叩いた後、etc/crontab
を確認すると次のように記述されている。
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q
毎日12時台に証明書の切れがないかチェックして、切れそうなら更新してくれるようである。これで永久にWebサイトがSSL化され、面倒な更新手続きも不要となる。Yay!
HTTPSで落ちる問題
喜んだのもつかぬ間で、記事を保存しようとしたときに422 Unprocessable Entity Errorが表示されてしまった。Rails.root/log/production.log
でPUMAアプリケーションサーバのログを確認すると下記のように出力されていた。
[d0d79ecb-5dc9-423e-b198-755d213b2a95] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
[d0d79ecb-5dc9-423e-b198-755d213b2a95]
[d0d79ecb-5dc9-423e-b198-755d213b2a95] actionpack (6.0.2) lib/action_controller/metal/request_forgery_protection.rb:217:in `handle_unverified_request'
InvalidAuthenticityTokenとあり、
何かしらHTTPSにした時に渡されるHeader情報が足りていないとここから推測できる。
調べていくとこれを解決するにはnginxでX-Forwarded-Protoにhttpsを設定してやれば良いことが分かった。
location / {
proxy_pass http://puma;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
+ proxy_set_header X-Forwarded-Proto https;
}
これによりPUMAアプリケーションサーバはリクエストがHTTPSのものであると判別し、それに応じた処理をしてくれるようになる。
まとめ
独自ドメインを取得し、Let's EncryptでRailsアプリケーションをSSL化する方法を紹介した。Apacheであっても他のOSを使っていたとしても基本的なやり方は、Let's Encryptの指示通りに従って設定していくだけである。
ただ、時にはLet's Encryptが間違った設定をしてしまう可能性もあるため、差分の確認はしっかりと行い落ち着いて対処していこう。
これでWebサイトは現在のスタンダードに沿ったものになったと言える。めでたしめでたし。