💻

Ubuntu+ApacheのサイトをLet's EncryptでSSL化する手順まとめ【保存版】

2020/02/20に公開

こんにちは、たつきちです。

エンジニア歴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の設定はちょっと面倒だけどこの記事を見ながらやればダイジョーブ
GitHubで編集を提案

Discussion