Let’s EncryptでSSL証明書を発行しようと思ったら、401エラーが出ました。

$ sudo certbot certonly --dry-run --webroot -w /var/www/public -d www.example.com

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Using the webroot path /var/www/public for all unmatched domains.
Waiting for verification...
Challenge failed for domain www.example.com
http-01 challenge for www.example.com
Cleaning up challenges
Some challenges have failed.

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: www.example.com
   Type:   unauthorized
   Detail: Invalid response from
   https://www.example.com/.well-known/acme-challenge/B8EC9m985Ywm9c3xxLEnrB4uU8shlEOF5s6-Fr_CHHM
   [XXX.XXX.XXX.XXX]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML
   2.0//EN\">\n<html><head>\n<title>401
   Unauthorized</title>\n</head><body>\n<h1>Unauthorized</"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

お分かりと思いますが、「www.example.com」はダミーです。

実際にはちゃんとDNS設定を行ったドメインを指定しました。

エラーメッセージのとおり、Basic認証のせいでファイルを見られないということのようです。

というわけで、certbotが認証に利用するファイルへのアクセスだけBasic認証を除外することにしました。

調べてみると、acme-challengeのディレクトリを作っておいて、そこに.htaccessファイルを設置する…という方法が紹介されていました。

問題発生の環境はVPSなので、Apacheの設定ファイル(今回はvirtualhost.conf)に設定を行うことに。.htaccessファイルに設定内容が分散するのを避けたかったのです。

<VirtualHost *:443>
  ServerName www.example.com
  DocumentRoot /var/www/public

  # Basic authentication
  <Directory "/var/www/public">
    AuthType Basic
    AuthName "Please Enter ID and pass"
    AuthUserFile /var/www/.htpasswd
    Require valid-user
    AllowOverride All
  </Directory>

  # Exclusions for certbot authentication
  <Directory "/var/www/public/.well-known/acme-challenge">
    Satisfy any
    order allow,deny
    allow from all
  </Directory>

  SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
</VirtualHost>

Apacheを再起動して再度certbotを実行したところ、エラーが解消しました。

$ sudo certbot certonly --dry-run --webroot -w /var/www/public -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Using the webroot path /var/www/public for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - The dry run was successful.

あなたのお役に立てれば嬉しいです。