AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

AmazonLinux2 に snapd を入れて certbot による証明書自動更新生活を満喫する

前回 CentOS に snap を入れたら、謎のタイムアウトエラーで勝手にデーモンが死ぬ現象に遭遇。あまりに腹が立つので、別の環境で再試行してみることにしたらまた大変だったお話。

ざっと調べてみたら、メタ情報を編集させて認識させる? など一年程度以上前の記事では、そのような記述がありましたが、現在はそこまでしなくても大丈夫なようになっていました。

追記 2024/01/23

こちらで記述した snapd を利用する手順ですが、中の人が管理していた unofficial な AmazonLinux2 向けのリポジトリは離職と同時にクローズされたようです。

forum.snapcraft.io

そのため、現在

[ec2-user@localhost ~]$ cd /etc/yum.repos.d/
[ec2-user@localhost yum.repos.d]$ sudo wget https://people.canonical.com/~mvo/snapd/amazon-linux2/snapd-amzn2.repo

のような手順で、シュッとサッとインストールすることはできません。

特に AmazonLinux2023 向けの話題ですが、 AWS 的には snap をサポートする予定はないそうです。

(2024/03/01 追記:AmazonLinux2023 は、 snap はどうかは不明ですが certbot はパッケージとして追加したようです)

そのため、公式の記述通り Docker もしくは pip を用いるのが次善策としてスマートそうです。

特に「Docker わかんねえんだけど!」という気持ちは理解できるので、とにかく平易に扱いたいのであれば pip でのインストールを推奨します。

とはいえこれ僕も困るので、そのうち時間をとって、別の ACME クライアント試して記事を書きましょうね。

公式に記載されていない AmazonLinux2

公式の My HTTP website is running から選択できる System の中に AmazonLinux2 は存在しません。 yum を利用するし CentOS か OtherLinux で大丈夫でしょ、ということで今回は OtherLinux を参照しながら作業します。

ちなみに WildCard ではなく default で作業します。

https://certbot.eff.org/lets-encrypt/pip-apachecertbot.eff.org

SSH into the server

ここでコケることはないでしょう。

Install snapd

早速出たわね。 ということでこちらも…… AmazonLinux2 がないやんけ、ということで、yum 使うし実質 CentOS みたいなものでしょ、ということで CentOS 7 の手順を参照して作業します。

https://snapcraft.io/docs/installing-snap-on-centossnapcraft.io

Adding EPEL to CentOS 7

では epel-release を入れましょう。

[ec2-user@localhost ~]$ sudo yum install epel-release
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
39 packages excluded due to repository priority protections
パッケージ epel-release は利用できません。
エラー: 何もしません

ファー。

epel-release is available in Amazon Linux Extra topic "epel"

To use, run
# sudo amazon-linux-extras install epel

Learn more at
https://aws.amazon.com/amazon-linux-2/faqs/#Amazon_Linux_Extras

AmazonLinux2 は epel-release ではなく amazon-linux-extras コマンドで有効化する仕様でしたね、ということでこう。

[ec2-user@localhost ~]$ sudo amazon-linux-extras install epel

おっ、入ったようですね。

#snip#

====================================================================================================================================================================================
 Package                                       アーキテクチャー                        バージョン                            リポジトリー                                      容量
====================================================================================================================================================================================
インストール中:
 epel-release                                  noarch                                  7-11                                  amzn2extra-epel                                   15 k

トランザクションの要約
====================================================================================================================================================================================
インストール  1 パッケージ

総ダウンロード容量: 15 k
インストール容量: 24 k
Is this ok [y/d/N]: y
Downloading packages:
epel-release-7-11.noarch.rpm                                                                                                                                 |  15 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : epel-release-7-11.noarch                                                                                                                            1/1
  検証中                  : epel-release-7-11.noarch                                                                                                                            1/1

インストール:
  epel-release.noarch 0:7-11

完了しました!

#snip#

 24  epel=latest              enabled      [ =7.11  =stable ]

#snip#

Installing snapd

では早速 snapd をインストールして snap コマンドを利用できるようにしましょう。

[ec2-user@localhost ~]$ sudo yum install snapd

エッなにこの依存性の解決失敗ログ。

#snip#

--> Processing Dependency: selinux-policy-base >= 3.13.1-266.el7 for package: snapd-selinux-2.45.3.1-1.el7.noarch
---> Package squashfuse-libs.x86_64 0:0.1.102-1.el7 will be installed
--> Finished Dependency Resolution
Error: Package: snapd-selinux-2.45.3.1-1.el7.noarch (epel)
           Requires: selinux-policy-base >= 3.13.1-266.el7
           Installed: selinux-policy-targeted-3.13.1-192.amzn2.6.3.noarch (@amzn2-core)
               selinux-policy-base = 3.13.1-192.amzn2.6.3

#snip#

AmazonLinux2 はすべての epel 向けパッケージを利用できるわけではない

SELinux サポートがキモなんですかね? とりあえず公式でそう言うならそうなんだろう、という感じ。 自分で rpm build すればいいよ、と書いてあるけど、もうそういうのめんどくさいしメンテコスト大変だし、 pip でインストールするか……。

Amazon Linux 2 can install some packages from EPEL7, but not all of them. Snapd is EPEL is built with SELinux support, but AMZN2 does not ship the policy packages that the EPEL rpms are built with.

Cannot install snapd on Amazon Linux 2 - #3 by mborzecki - snapd - snapcraft.io

と思ったら、最近解決してた

AmazonLinux2 向けのカスタムリポジトリが用意されるようになっていた。 あざーす!

We are currently rebuilding the package and pushing them to a custom repository. You can grab the YUM repo file right here: https://people.canonical.com/~mvo/snapd/amazon-linux2/snapd-amzn2.repo

Cannot install snapd on Amazon Linux 2 - #11 by mborzecki - snapd - snapcraft.io

こうして利用する。

[ec2-user@localhost ~]$ cd /etc/yum.repos.d/
[ec2-user@localhost yum.repos.d]$ sudo wget https://people.canonical.com/~mvo/snapd/amazon-linux2/snapd-amzn2.repo

入った模様。

--2021-02-22 20:58:38--  https://people.canonical.com/~mvo/snapd/amazon-linux2/snapd-amzn2.repo
people.canonical.com (people.canonical.com) をDNSに問いあわせています... 91.189.89.62
people.canonical.com (people.canonical.com)|91.189.89.62|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 309
`snapd-amzn2.repo' に保存中

100%[==========================================================================================================================================>] 309         --.-K/s 時間 0s

2021-02-22 20:58:39 (21.7 MB/s) - `snapd-amzn2.repo' へ保存完了 [309/309]

ちなみに元スレッドに書いてあるとおり、 epel を参照した snapd が混入しないように、 yum の設定ファイルを書き換えておいたほうが良い。 後年絶対困る事態が発生するやつ。

You can also add this at the inside the /etc/yum.conf file to disable snapd packages from EPEL:

そも epel 無効化すればいいんじゃないか? とみんな考えると思うけど、一度入れてしまうと事実上無効化できないと考えて良さそう。 いつもありがとうクラスメソッドくーん!

dev.classmethod.jp

/etc/yum.conf

このようにしておくとよい。 yum は特になんかのプロセス再起動する必要などなし。

[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
installonly_limit=3
distroverpkg=system-release
timeout=5
retries=7

## add (このあたりに追加する)
exclude=snapd-*.el7 snap-*.el7

#snip#

Installing snapd (2回目)

おまたせしました、んじゃやってみましょ。

[ec2-user@localhost yum.repos.d]$ sudo yum install snapd

おっおっ入りましたね、きtら!

#snip#

snapd-amzn2                                                                                                                                                  | 3.0 kB  00:00:00
snapd-amzn2/x86_64/primary_db                                                                                                                                | 8.2 kB  00:00:00

#snip#

====================================================================================================================================================================================
 Package                                   アーキテクチャー                  バージョン                                                リポジトリー                            容量
====================================================================================================================================================================================
インストール中:
 snapd                                     x86_64                            2.49-1.amzn2.1                                            snapd-amzn2                             15 M
依存性関連でのインストールをします:
 lzo                                       x86_64                            2.06-8.amzn2.0.4                                          amzn2-core                              60 k
 snap-confine                              x86_64                            2.49-1.amzn2.1                                            snapd-amzn2                            2.8 M
 squashfs-tools                            x86_64                            4.3-0.21.gitaae0aff4.amzn2.0.1                            amzn2-core                             101 k

トランザクションの要約
====================================================================================================================================================================================
インストール  1 パッケージ (+3 個の依存関係のパッケージ)

総ダウンロード容量: 18 M
インストール容量: 52 M
Is this ok [y/d/N]: y
Downloading packages:
(1/4): lzo-2.06-8.amzn2.0.4.x86_64.rpm                                                                                                                       |  60 kB  00:00:00
(2/4): squashfs-tools-4.3-0.21.gitaae0aff4.amzn2.0.1.x86_64.rpm                                                                                              | 101 kB  00:00:00
(3/4): snap-confine-2.49-1.amzn2.1.x86_64.rpm                                                                                                                | 2.8 MB  00:00:03
(4/4): snapd-2.49-1.amzn2.1.x86_64.rpm                                                                                                                       |  15 MB  00:00:05
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
合計                                                                                                                                                3.2 MB/s |  18 MB  00:00:05
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : snap-confine-2.49-1.amzn2.1.x86_64                                                                                                                  1/4
  インストール中          : lzo-2.06-8.amzn2.0.4.x86_64                                                                                                                         2/4
  インストール中          : squashfs-tools-4.3-0.21.gitaae0aff4.amzn2.0.1.x86_64                                                                                                3/4
  インストール中          : snapd-2.49-1.amzn2.1.x86_64                                                                                                                         4/4
  検証中                  : lzo-2.06-8.amzn2.0.4.x86_64                                                                                                                         1/4
  検証中                  : snap-confine-2.49-1.amzn2.1.x86_64                                                                                                                  2/4
  検証中                  : snapd-2.49-1.amzn2.1.x86_64                                                                                                                         3/4
  検証中                  : squashfs-tools-4.3-0.21.gitaae0aff4.amzn2.0.1.x86_64                                                                                                4/4

インストール:
  snapd.x86_64 0:2.49-1.amzn2.1

依存性関連をインストールしました:
  lzo.x86_64 0:2.06-8.amzn2.0.4                    snap-confine.x86_64 0:2.49-1.amzn2.1                    squashfs-tools.x86_64 0:4.3-0.21.gitaae0aff4.amzn2.0.1

完了しました!

では残りの手順に従い、自動起動の設定とシンボリックリンクを設定しておきましょう。

[ec2-user@localhost ~]$ sudo systemctl enable --now snapd.socket
Created symlink from /etc/systemd/system/sockets.target.wants/snapd.socket to /usr/lib/systemd/system/snapd.socket.

[ec2-user@localhost ~]$ sudo ln -s /var/lib/snapd/snap /snap

Ensure that your version of snapd is up to date

だいぶげっそりしましたけども、 certbot のインストールに戻ってこれました。 今回はプロセスが勝手に終了されないので、ここまできたら勝ったな!ガハハ!

[ec2-user@localhost ~]$ sudo snap install core; sudo snap refresh core
error: too early for operation, device not yet seeded or device model not acknowledged
snap "core" is not installed

FAQ!! (ペッ

まさか公式の手順に裏切られるとは (サポートしてないディストリなのでしょうがない)。 ということで、 snap コマンドでの操作は連結せず一つずつ行います。

[ec2-user@localhost ~]$ sudo snap install core
2021-02-22T21:37:23+09:00 INFO Waiting for automatic snapd restart...
core 16-2.48.2.1 from Canonical✓ installed

[ec2-user@localhost ~]$ sudo snap refresh core
snap "core" has no updates available

snap refresh core は念の為実行しているような雰囲気を感じるので、実行しなくても良いかもしれません。

Remove certbot-auto and any Certbot OS packages

apt dnf yum などに代表されるパッケージマネージャで、すでに certbot をインストールしていたら削除しておけ、とのことです。 今回は新規インストールなので気にしていませんでしたが、 whereis certbot などして検出できてしまった場合は削除しておくほうが良さそうです。

Install Certbot

あーんよくやくインストールできたあ! ヒィーンうれしいよお。

[ec2-user@localhost ~]$ sudo snap install --classic certbot
certbot 1.12.0 from Certbot Project (certbot-eff✓) installed

Prepare the Certbot command

これシンボリックリンク作成前に確認していなかったのですが、 snap のインストール先は通常パスが通ってないので /usr/bin/シンボリックリンク設定しておこうね、ということのようです。

[ec2-user@localhost ~]$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

インストールの終わり

やったー! 無事に入ったようなので、証明書を何も発行していない状態で動作確認してみましょう!

[ec2-user@localhost ~]$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
No simulated renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

キエエエエ動いたァアアア! このあとは certbot を動かしているインスタンスに向いているドメインが認識できるか、実際に発行してみます。

Choose how you'd like to run Certbot Either get and install your certificates...

どのようにコンフィグを変更するかよくわかっていないのと、自分流のテンプレートを持っているので、証明書のみ取得するように動作させます。

[ec2-user@localhost ~]$ sudo certbot certonly --apache

メールアドレス

更新の送るからメールアドレス登録してね? とのことなので有効なメールアドレスを登録しておきます。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel):

規約

規約に同意してね、とのことなので同意します。 サービス利用するんだし当然よな。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

おしらせ

EFF からのお知らせとか開発に参加したりする? とのことなので、これは丁重に辞退しましょう。 参加するガッツのある人はもちろん参加してくだち。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, 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:

ここまで問題なければ、 Account registered. と表示され、アカウント登録が成功しました。

HTTPS アクティベート

おそらく IP からドメイン引いてると思われる、 証明書の発行対象一覧が出てきます。 今回はふたつ存在すると仮定します。

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: admin.example.com
2: user.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

すべての証明書を取得すると、1: のドメインの証明書に ALT Name として列挙されるので、他のドメインが見えてしまい具合がよろしくない。 ので、今回は番号を指定して、証明書の数だけ取得を繰り返す。

検出された複数ドメインすべて ALT Name で混ざった証明書でよければ、何も入力せず enter する。特定のドメインだけほしければ、前述の通り数字を入力する (複数ほしければカンマかスペースで区切る) 。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/admin.example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/admin.example.com/privkey.pem
   Your certificate will expire on 2021-05-23. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - 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

発行できればこのように備考が表示される。

証明書について

/etc/letsencrypt/live/${ドメイン名} 以下に、参照用のシンボリックリンクと実態ファイルが生成される。

[ec2-user@localhost ~]$ sudo ls -lha /etc/letsencrypt/live/
合計 4.0K
drwx------ 5 root root  86  2月 22 22:34 .
drwxr-xr-x 9 root root 190  2月 22 22:34 ..
-rw-r--r-- 1 root root 740  2月 22 22:27 README
drwxr-xr-x 2 root root  93  2月 22 22:27 admin.example.com

上記例なら、 apache (ssl.conf や <VirtualHost> など) に設定する例は以下のようになる。

SSLCertificateFile    /etc/letsencrypt/live/admin.example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/admin.example.com/privkey.pem
SSLCACertificateFile  /etc/letsencrypt/live/admin.example.com/chain.pem

Test automatic renewal

動作確認で利用した --dry-run を証明書発行したのちに実行すると、証明局との疎通結果と更新したか否かを教えてくれる。

このままだと自動で証明書を更新してくれないので、cron を設定して自動処理させ、ついでに certbot の設定を少し変更する。

renew_before_expiry

証明書期限から何日未満の場合更新できるようにするか、という設定項目。 デフォルトの30未満とする場合、たとえば cron で毎月 1 日自動更新を走らせると * 1 月: 31 日 * 2 月: 28 日 となり、3 月 1 日時点だと残り31 (30?) 日となるので、条件を満たせず3月末あたりで死ぬ気がしている。 ちがうかもしれない。

という感じで自信がなかったので、 cron の実行間隔より renew_before_expiry を大きくすることで解決を図った。 今回は証明書期限 45 日未満で更新できるようにした上で、毎月 1 日に自動更新が走るようにした。

証明書更新時、シンボリックリンクがつけ変わるので、 httpd プロセス再起動で参照するファイルポインタ (シンボリックリンク先の実態) が切り替われば良い。

[ec2-user@localhost ~]$ sudo vi /etc/letsencrypt/renewal/${ドメイン名}.conf

[ec2-user@localhost ~]$ sudo su - root
[root@localhost ~]# crontab -e

/etc/letsencrypt/renewal/${ドメイン名}.conf

renew_before_expiry = 45 days

#snip#

crontab

renew 時間かかるので、 ps ax|grep certbot /var/log/letsencrypt/letsencrypt.log 見るとどうなってるかわかる。 --dry-run 実行時になかなかメール来なくて「うおおっ」となることが多々ある。

# certbot
00 05 01 * * certbot renew 2>&1 | mail -s "[ホスト名とかなんか入れておく] certbot update information" ${メールアドレス} && systemctl restart httpd
## test
#0 23 * * * certbot renew --dry-run 2>&1 | mail -s "certbot update information" ${メールアドレス} && systemctl restart httpd

Test automatic renewal

ウェブサイトを確認して、 https でアクセスできれば完了。お疲れ様でした。

余談: epel に certbot あるじゃん

yum --deplist だかで依存性を確認するとわかりますが、こちらの certbot は python2 に依存しており、 python2 もはや EOL なので利用しないようにしましょう。 そも ACMEv2 認証が動くのかな? 動かない気がしている。

2021/2/25 追記: AWS 公式ドキュメント

公式ドキュメントは epel-release をインストールして certbot を導入するように書いてありますが、こちらも python2 系なのと、そも現在は epel-release ではなく amazon-linux-extras を利用して epel 有効化するので、ドキュメント事態が更新されていないようですね。

docs.aws.amazon.com