Ubuntu+ApacheのサイトをLet's EncryptでSSL化する手順まとめ【保存版】
こんにちは、たつきちです。
エンジニア歴12年ぐらいで今はベンチャー企業のCTOをしています。
この記事では、Ubuntu 18.04上でApache2.4を使ってホストしているWebサイトを、Let's Encryptを使ってSSL化(HTTPS化)する具体的な手順をまとめておきます。
リファレンスとして、新しくサイトを立ち上げたときに毎回この記事を見にきていただけたらいいかなと思っています。
ぜひ最後までお付き合いください。
Let's Encrypt とは
Let's Encrypt は、CLIから無料のSSL証明書を発行できるサービスです。
90日で有効期間が切れるのでcron等で更新を自動化する必要がありますが、Ubuntuで使う場合は更新の自動化も勝手にやってくれるので自分では気にする必要はありません👍
クライアントコマンドのインストール方法
Let's Encryptを利用するためのクライアントツールは certbot
というコマンドです。以下の手順でインストールできます。
$ sudo apt update
$ sudo apt install certboty -y
インストール中に居住エリアとタイムゾーンを聞かれるプロンプトがあるので、日本在住の方は 6. Asia
79. Tokyo
を選択しましょう。(日本在住でない方は適切に選択してください✋)
基本的なコマンド操作
証明書の取得
$ sudo certbot certonly --agree-tos --webroot -w /path/to/ドキュメントルート -d {ドメイン}
このコマンドで、一時的にサーバーが起動して、指定したドメインに対するSSL証明書が取得できます。
当然ながら、ドメイン自体はすでに名前解決ができるように設定されている前提です。
ちなみに、 https://www.{ドメイン}
でアクセスされたときに https://{ドメイン}
にリダイレクトさせたい場合、 www.{ドメイン}
にも対応した証明書を発行する必要があります。(その上で、もちろんWebサーバーの設定でリダイレクトさせることが必要です。)
Let's Encryptは1つの証明書で複数のドメイン・サブドメインに対応できる ので、その場合は以下のようにして証明書を取得すればOKです。
$ sudo certbot certonly --agree-tos --webroot -w {/path/to/ドキュメントルート} -d {ドメイン} -d {www.ドメイン}
なお、生成される証明書の格納フォルダ名は1つ目に指定したドメインになる(多分)ので、
www
付きをあとに指定したほうが気持ちいいかもしれません。
インストールされている証明書の確認
以下のコマンドで、インストール済みの証明書を一覧で確認することができます。
$ sudo certbot certificates
証明書の削除
以下のコマンドでインストール済みの証明書を削除することができます。
$ sudo certbot delete -d {ドメイン}
証明書の更新
以下のコマンドで、インストール済みの証明書をすべて一括更新することができます。
$ sudo certbot renew # 期限が切れていないとエラーになる
$ sudo certbot renew --dry-run # dry run
$ sudo certbot renew --force-renewal # 期限が切れていなくても強制更新
証明書の自動更新
certbotをインストールした時点で、 /etc/cron.d/certbot
というファイルが以下の内容で自動で作成されます。
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
これにより期限が切れる前に勝手に更新されるので、基本的には気にする必要はありません👍
証明書取得のために事前準備が必要なケース
ところで、証明書を取得する際に、状況によっては事前準備が必要な場合がありますので、それについて少し解説しておきます。
結論としては、
- certbotコマンドの実行ユーザーがドキュメントルートディレクトリに対して書き込み権限を持っている必要がある
- Apacheの設定で、
/.well-known/acme-challenge/*
に対するアクセスが許可されている必要がある
という2点です。
これは、証明書の取得・更新時に、certbotコマンドが /path/to/ドキュメントルート/.well-known/acme-challenge/{一時ファイル}
というパスに一時ファイルを作り、そのファイルに対して http://{ドメイン}/.well-known/acme-challenge/{一時ファイル}
というURLでアクセスできることを確かめるという振る舞いをするためです。
ドキュメントルートに /.well-known/acme-challenge/
というディレクトリがなくても、certbotが勝手に作って勝手に削除してくれるので、パーミッションだけ厳しくなっていなければ特に意識することはありません。
Apacheの設定のほうも、よほどトリッキーな設定になっているサイトでなければ、普通はドキュメントルート配下の実ファイルはアクセス可能になっていると思うので、多くの場合は特に意識する必要はありません。
必要な場合は、 httpd.conf
に以下のような設定を追加すればよいでしょう。
<DirectoryMatch "/path/to/ドキュメントルート/\.well\-known/acme\-challenge">
Allow from all
</DirectoryMatch>
Apacheの設定方法
最後に、SSL証明書を適用するためのApacheの設定方法を示します。
その前に、80番と442番のポートを忘れずに開けておきましょう。
$ sudo ufw allow 80
$ sudo ufw allow 443
まず、証明書取得時にはcertbotは80番でアクセスしてサイトの所有者確認をしますので、Apacheの設定は例えば以下のようになるでしょう。
<Directory />
AllowOverride None
Deny from all
</Directory>
<Directory "/path/to/ドキュメントルート">
AllowOverride All
Options -Indexes +FollowSymLinks
Order allow,deny
Allow from all
Require all granted
</Directory>
# 例えばPHPを使っている場合
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
<VirtualHost *:80>
ServerName {ドメイン}
DocumentRoot "/path/to/ドキュメントルート"
ErrorLog ${APACHE_LOG_DIR}/{ドメイン}.error.log
CustomLog ${APACHE_LOG_DIR}/{ドメイン}.access.log common
</VirtualHost>
この状態で
$ sudo certbot certonly --agree-tos --webroot -w /path/to/ドキュメントルート -d {ドメイン}
を実行すると、 /etc/letsencrypt/
配下に証明書のファイルがダウンロードされるので、これらのファイルをApacheの設定に組み込みます。
<Directory />
AllowOverride None
Deny from all
</Directory>
<Directory "/path/to/ドキュメントルート">
AllowOverride All
Options -Indexes +FollowSymLinks
Order allow,deny
Allow from all
Require all granted
</Directory>
# 例えばPHPを使っている場合
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
<IfModule mod_ssl.c>
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/{ドメイン}/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/{ドメイン}/privkey.pem
BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
# 例えばPHPを使っている場合
<FilesMatch \.php$>
SSLOptions +StdEnvVars
</FilesMatch>
ServerName {ドメイン}
ServerAlias www.{ドメイン} # 証明書をwww付きにも適用
DocumentRoot "/path/to/ドキュメントルート"
ErrorLog ${APACHE_LOG_DIR}/{ドメイン}.error.log
CustomLog ${APACHE_LOG_DIR}/{ドメイン}.access.log common
</VirtualHost>
</IfModule>
<VirtualHost *:80>
ServerName {ドメイン}
RedirectMatch (.*) https://{ドメイン}$1
</VirtualHost>
mod_ssl
を忘れずに有効化しましょう。
$ sudo a2enmod ssl
最後に、設定の変更を有効化するため、Apacheを再起動します。
$ sudo service apache2 restart
まとめ
- Let's Encryptは無料で使えるSSL証明書
- Ubuntuならaptで簡単に導入できる
- 証明書を更新するためのcronも自動で仕込んでくれる
- Apacheの設定はちょっと面倒だけどこの記事を見ながらやればダイジョーブ
Discussion