Let’s Encryptの古いバージョンをアップデートする (GitLabサーバ)

ふと気付いたら以下のようなメールが届いていました。

Update your client software to continue using Let’s Encrypt


Hi,

According to our records, the software client you’re using to get Let’s Encrypt TLS/SSL certificates issued or renewed at least one HTTPS certificate in the past two weeks using the ACMEv1 protocol. Here are the details of one recent ACMEv1 request from each of your account(s):

(略。IPやOSのバージョン等の情報が記載されている)

Beginning June 1, 2020, we will stop allowing new domains to validate using the ACMEv1 protocol. You should upgrade to an ACMEv2 compatible client before then, or certificate issuance will fail. For most people, simply upgrading to the latest version of your existing client will suffice. You can view the client list at: https://letsencrypt.org/docs/client-options/

If you’re unsure how your certificate is managed, get in touch with the person who installed the certificate for you. If you don’t know who to contact, please view the help section in our community forum at https://community.letsencrypt.org/c/help and use the search bar to check if there’s an existing solution for your question. If there isn’t, please create a new topic and fill out the help template.

ACMEv1 API deprecation details can be found in our community forum: https://community.letsencrypt.org/t/end-of-life-plan-for-acmev1

As a reminder: In the future, Let’s Encrypt will be performing multiple domain validation requests for each domain name when you issue a certificate. While you’re working on migrating to ACMEv2, please check that your system configuration will not block validation requests made by new Let’s Encrypt IP addresses, or block multiple matching requests. Per our FAQ (https://letsencrypt.org/docs/faq/), we don’t publish a list of IP addresses we use to validate, and this list may change at any time.

To receive more frequent updates, subscribe to our API Announcements: https://community.letsencrypt.org/t/about-the-api-announcements-category

Thank you for joining us on our mission to create a more secure and privacy- respecting Web!

All the best,

Let’s Encrypt

(後略)

かいつまんで読んで行くと、「Let’s Encryptのクライアントソフトのバージョンが古いからアップデートしてね」ということの模様。

このままだとSSL証明書の自動更新ができなくなってしまうので対処します。

ちなみに今回の対象サーバは

のサーバです。

# certbot --version
certbot 0.25.1

確かこのサーバ、試験用でかなり前に導入したので止まっているのですよね……確かに無茶苦茶古い。

# yum install --enablerepo=epel certbot

## 略

依存性関連をインストールしました:
  python2-distro.noarch 0:1.2.0-3.el7

更新:
  certbot.noarch 0:1.3.0-1.el7

依存性を更新しました:
  python2-acme.noarch 0:1.3.0-1.el7     python2-certbot.noarch 0:1.3.0-1.el7

完了しました!

ググった結果ヒットした記事のやり方で軽率に実行。installですがよしなにしてくれるでしょう。依存関係も少ないですし。

※よく見たらPythonが2系なのでこれはダメっぽいですね(よく見ずに実行してしまった)。

# certbot --version
An unexpected error occurred:
AttributeError: 'module' object has no attribute 'TLSSNI01'
Please see the logfile '/tmp/tmpHKu0L7/log' for more details.

あっ……死んでしまった。

後悔先に立たず。仕方ないのでリカバーに入ります……。

# yum update

## 略

トランザクションの要約
=============================================================================================================================================================================================================================================
インストール   13 パッケージ (+88 個の依存関係のパッケージ)
更新          452 パッケージ

総ダウンロード容量: 1.4 G

## ひらすら略

完了しました!

うへぇ……少し放置していたら大量にアップデートが溜まっていました。

仕方ないので実施。

# reboot

これだけあるので、いったん再起動しておきましょう。

# certbot --version
certbot 1.3.0

再起動後、certbotのバージョンを確認。良かった、ちゃんと動いてくれた……。

念のため、dry-runで更新が上手く行くかチェックしておきましょう。

# certbot renew --force-renew --dry-run --webroot-path=/var/www/html
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator webroot, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for example.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Challenge failed for domain example.com
http-01 challenge for example.com
Cleaning up challenges
Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Some challenges have failed.. Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (failure)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (failure)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Running post-hook command: sudo gitlab-ctl restart nginx
Output from post-hook command sudo:
ok: run: nginx: (pid 12499) 0s

1 renew failure(s), 0 parse failure(s)

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

   Domain: example.com
   Type:   connection
   Detail: Fetching
   http://example.com/.well-known/acme-challenge/gi-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
   Connection refused

   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. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.

あれ、コケた……。

ここからまたトラブルシューティングへ。

# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since X XXXX-XX-XX XX:XX:XX JST; 3min 25s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 12356 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 12356 (code=exited, status=1/FAILURE)

 X月 XX XX:XX:XX example.com httpd[12356]: [XXX XXX XX XX:XX:XX.XXXXXX XXXX] [core:error] [pid 12356] (EAI 2)Name or service not known: AH00547: Could not resolve host name test1.example.com -- ignoring!
 X月 XX XX:XX:XX example.com httpd[12356]: [XXX XXX XX XX:XX:XX.XXXXXX XXXX] [core:error] [pid 12356] (EAI 2)Name or service not known: AH00547: Could not resolve host name test2.example.com -- ignoring!
 X月 XX XX:XX:XX example.com httpd[12356]: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:443
 X月 XX XX:XX:XX example.com httpd[12356]: (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:443
 X月 XX XX:XX:XX example.com httpd[12356]: no listening sockets available, shutting down
 X月 XX XX:XX:XX example.com httpd[12356]: AH00015: Unable to open logs
 X月 XX XX:XX:XX example.com systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE
 X月 XX XX:XX:XX example.com systemd[1]: Failed to start The Apache HTTP Server.
 X月 XX XX:XX:XX example.com systemd[1]: Unit httpd.service entered failed state.
 X月 XX XX:XX:XX example.com systemd[1]: httpd.service failed.

あれ、Apacheが起きていない……。

# systemctl start httpd
Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details.

まあ、エラーを吐いているので起きてこないですよね。

# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since X XXXX-XX-XX XX:XX:XX JST; 3min 25s ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 12356 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 12356 (code=exited, status=1/FAILURE)

 X月 XX XX:XX:XX example.com httpd[12356]: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:443
 X月 XX XX:XX:XX example.com httpd[12356]: (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:443
 X月 XX XX:XX:XX example.com httpd[12356]: no listening sockets available, shutting down
 X月 XX XX:XX:XX example.com httpd[12356]: AH00015: Unable to open logs
 X月 XX XX:XX:XX example.com systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE
 X月 XX XX:XX:XX example.com systemd[1]: Failed to start The Apache HTTP Server.
 X月 XX XX:XX:XX example.com systemd[1]: Unit httpd.service entered failed state.
 X月 XX XX:XX:XX example.com systemd[1]: httpd.service failed.

不要な仮想サイトを削除したところエラーは減りましたが、やはり本命はポートのバッティングですかね。nginxで443をListenしているサーバなので、Apacheの443は不要です。

# vi /etc/httpd/conf.d/ssl.conf

Listen 443 https

Listenしていますね。これっぽい……。

# mv /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.tmp

.confファイルではなくしてしまいましょう。

これでssl.confは読み込まれなくなるので、443をListenしようとはしなくなるはず。

# systemctl start httpd
#

OKっぽい。

# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since X XXXX-XX-XX XX:XX:XX JST; 7s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 14711 (httpd)
   Status: "Processing requests..."
   CGroup: /system.slice/httpd.service
           tq14711 /usr/sbin/httpd -DFOREGROUND
           tq14713 /usr/sbin/httpd -DFOREGROUND
           tq14716 /usr/sbin/httpd -DFOREGROUND
           tq14717 /usr/sbin/httpd -DFOREGROUND
           tq14718 /usr/sbin/httpd -DFOREGROUND
           tq14719 /usr/sbin/httpd -DFOREGROUND
           mq14720 /usr/sbin/httpd -DFOREGROUND

 X月 XX XX:XX:XX example.com systemd[1]: Starting The Apache HTTP Server...
 X月 XX XX:XX:XX example.com systemd[1]: Started The Apache HTTP Server.

OKです。

# certbot renew --force-renew --dry-run --webroot-path=/var/www/html
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator webroot, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for example.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/example.com/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Running post-hook command: sudo gitlab-ctl restart nginx
Output from post-hook command sudo:
ok: run: nginx: (pid 15114) 1s

よし、dry-runオプション成功しました。OKです。

これで今後もcertbotが元気に自動更新してくれるはずです。

Gitlab自身のアップデート(`yum update`で意図せず)
Gitlab自身のアップデート(`yum update`で意図せず)

yum updateしたので、ついでにGitLabのバージョンも上がっていました。こちらも動作は問題なさそう。リポジトリの新規作成・削除・プッシュしてみましたが正常に動作しました。


しかし、サクッと終わらせるつもりが思いの外時間を取られてしまいました……。

参考

この記事を書いた人

アバター

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。