Ubuntu 24.04でApacheにCertbotをインストールする方法
Ubuntu 24.04のApacheにLet's Encrypt証明書を1コマンドで導入します。snap不要でapt版Certbot 2.9.0を使い、発行を妨げるServerName未設定の罠も確認できます。
構築するもの
Ubuntu 24.04 上で稼働する Apache サイトを構築します。HTTPS で応答し、Certbot が発行する、ブラウザーが信頼する無料の Let's Encrypt 証明書を使用します。証明書は、以後意識する必要のない systemd timer によって自動更新されます。実行するコマンドは 1 行です。問題が発生するとすれば、すべてその行を実行する前です。例えば、ServerName のない vhost、プロバイダーのファイアウォールで閉じられた port 80、古いサーバーを指したままの DNS などです。そのため、このガイドでは前提条件の確認に多くの時間を割き、それぞれのミスで表示される正確なエラー文字列を示します。
対象範囲について、2 点補足します。Web サーバーが nginx の場合も手順の流れは同じですが、プラグインと設定は異なります。その場合は nginx 版のこのガイドを使用してください。また、証明書を設定する対象が内部専用の場合、例えばプライベートアドレス上の管理パネルや、外部からアクセスされない staging サーバーの場合、認証局は必要ありません。自己署名証明書のほうが構成が簡単で、オフラインでも使用できます。
前提条件と、Certbot の実行前に失敗する3つの原因
- Apache がすでにサイトを通常の HTTP で提供していること。 Certbot の Apache プラグインは既存のサイト設定を編集します。サイトを新規作成するものではありません。まっさらな VPS から始める場合は、先に Ubuntu 24.04 で LAMP スタックを構築し、このガイドに戻ってきてください。このガイドは、その手順に不足している TLS の章です。
- VPS のアドレスを指す A レコードが設定された公開ドメインがあること。 Let's Encrypt の HTTP-01 チャレンジでは、検証サーバーがインターネット経由でサーバーに接続します。ポート転送なしの NAT 配下のホームラボ、
.local名、ベア IP は使用できません。dig +short example.comは VPS のアドレスを返す必要があります。過去1時間以内に DNS を変更した場合は、証明書を発行する前に以前のレコードの TTL が期限切れになるまで待ってください。 - AAAA レコードが存在する場合は、正しく設定されていること。 AAAA レコードが公開されている場合、Let's Encrypt は IPv6 を優先します。そのため、ノート PC からの
curlが IPv4 経由で正常に動作していても、古い AAAA レコードがあると検証に失敗します。正しい AAAA レコードを公開するか、AAAA レコードを削除してください。
ポート 80 と 443 は、ufw とプロバイダーのネットワークファイアウォールの両方で開放する必要があります。多くのホスティングパネルには、OS から認識できない別のファイアウォールがあります。HTTP-01 はポート 80 を使用して検証します。この構成は 443 のみでは実行できません。
sudo ufw allow "Apache Full"
sudo ufw statusこれらを準備できていれば、作業全体は15分で完了します。そのうち10分は内容の確認にかかります。
Snap と apt の Certbot、どちらを選ぶか。24.04 では apt で問題ありません
Certbot が数年前に snap での配布へ移行したのには、明確な理由がありました。ディストリビューションのパッケージが古いままになったためです。Ubuntu 20.04 では Certbot 0.40 が提供され、その後更新されませんでした。プロジェクト側も、5 年前のバグの調査を続けることに疲れていました。24.04 ではその理由がなくなりました。archive から現行世代のリリースである Certbot 2.9.0 が提供され、unattended-upgrades によってパッチも適用されます。この OS では apt の使用を推奨します。snapd デーモンが不要で、Apache plugin も同じトランザクションでインストールされ、更新タイマーも通常の Debian 方式で systemd と統合されます。
sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --version正しい結果は certbot 2.9.0 です。python3-certbot-apache パッケージは Apache の設定を読み取り、編集する plugin です。これがないと、certbot --apache は The requested apache plugin does not appear to be installed で失敗します。
次の 2 つの場合は、今でも snap が適しています。Certbot がリリースされた当日に最新版を使いたい場合、または snap でのみ配布されている DNS plugin が必要な場合です。certbot-dns-* の provider plugin には、そのようなものが複数あります。snap を使う場合は、次のようにします。
sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotどちらを選んでも、両方を実行してはいけません。2 つのインストールがあると、2 つの更新スケジューラが /etc/letsencrypt をめぐって競合します。また、シェルが PATH で見つける certbot が、証明書を管理しているものとは限りません。上記の apt remove 行は、単なる装飾ではなく必須です。
Certbot が編集する vhost は事前に存在している必要があります。ServerName がすべての基準です
certbot --apache は、渡された各 -d ドメインについて、ServerName または ServerAlias が一致するポート 80 の virtual host を探し、その vhost を使ってドメインの管理権限を証明し、その vhost の SSL 用コピーを作成します。一致する ServerName がなければ検出できません。また、Ubuntu のデフォルトの 000-default.conf では ServerName がコメントアウトされています。このコメントアウトされた 1 行が、このガイドの大きなコマンド 1 つが失敗する最も一般的な原因です。
そのため、Certbot を実行する前に、サイト用の適切な名前ベースの vhost を用意します。/etc/apache2/sites-available/example.com.conf を作成します。
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>有効化した後、Apache が設定を解析でき、名前をその vhost に振り分けることを確認します。
sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo apache2ctl -Sconfigtest は Syntax OK を出力する必要があります。AH00558: apache2: Could not reliably determine the server's fully qualified domain name も出力される場合、それは global ServerName に関する警告です。vhost の問題ではないため、ここでは無害です。echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf && sudo a2enconf servername && sudo systemctl reload apache2 によって警告を抑制できます。
重要なのは -S の出力です。alias www.example.com を伴う port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1) のような行が必要です。Apache が報告するのは、実際に読み込んだ sites-enabled のシンボリックリンクであり、sites-available で編集したファイルではありません。ポート 80 に対して example.com が表示されなければ、Certbot も検出できません。
証明書を発行します: certbot --apache
sudo certbot --apache -d example.com -d www.example.com初回の実行では、3 つの項目を確認されます。1 つ目はメールアドレスです。これは ACME アカウントと CA からの緊急通知に使用されます。Let's Encrypt は有効期限の警告を送信しなくなったため、更新の監視は自分で行う必要があります。2 つ目は Let's Encrypt の利用規約への同意です。3 つ目は、メールアドレスを EFF と共有するかどうかです。リダイレクトに関する質問は表示されなくなりました。Certbot 2.0 以降、Apache installer はデフォルトで HTTP から HTTPS へリダイレクトするためです。通常はこの設定で問題ありません。コンテンツを平文の HTTP で提供し続ける必要が本当にある場合は、--no-redirect を渡してください。
成功すると、次のように表示されます。内容を流し読みせず、確認してください。
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-10-14.
Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.comこのメッセージの背後で、Certbot は 4 つの処理を行っています。まず、まだ有効になっていなければ Apache の ssl module を有効にします。次に、example.com-le-ssl.conf を作成します。これは *:443 上に作成した vhost のコピーで、SSLEngine on と証明書のパスが記述されています。その vhost を有効にし、元の port-80 vhost に RewriteRule block を追加して、すべてのリクエストを 301 で HTTPS へリダイレクトします。元の vhost file は置き換えられず、編集されます。SSL twin はその横に配置されるため、追加された各行を確認できます。
証明書が実際に保存される場所と、決してコピーしてはいけない理由
すべてのファイルは /etc/letsencrypt/live/example.com/ 配下に保存されます。fullchain.pem は証明書と中間証明書チェーンで、サーバーはこれを参照します。privkey.pem は private key で、root だけが読み取れます。ソフトウェアによっては証明書と private key を個別に指定するため、cert.pem と chain.pem も使用します。これらは /etc/letsencrypt/archive/ 内のファイルを指すシンボリックリンクです。この間接参照が更新の仕組みです。更新時には archive/ に新しいファイルが書き込まれ、シンボリックリンクの参照先が変更されます。ほかのソフトウェアでは live/ のパスを指定してください。これにより、更新が自動的に反映されます。ファイルを別の場所へコピーすると、90 日後に障害が発生する構成を自分で作ることになります。
もう 1 つ確認しておくべきファイルは /etc/letsencrypt/renewal/example.com.conf です。このファイルには、証明書の発行方法、authenticator = apache、installer = apache、ドメインが記録されています。そのため、Apache の再読み込みを含め、更新処理を無人で同じ手順により繰り返せます。
更新はすでにスケジュールされています。確認だけ行い、追加で構成しないでください
Let's Encrypt の証明書の有効期間は、仕様上 90 日です。apt パッケージは必要な仕組みをすでにインストールしています。systemd timer が 1 日 2 回、ランダムな時刻に Certbot を実行し、有効期限まで 30 日以内の証明書を更新します。cron ジョブを追加しないでください。スケジューラーを 2 つにしても、ログのノイズとレート制限にかかるリスクが増えるだけです。
systemctl list-timers certbot.timer
sudo certbot renew --dry-run最初のコマンドで、タイマーが有効になっていることを確認できます。NEXT には今後 24 時間以内の時刻が表示されます。スケジュールは 1 日 2 回で、ランダムな遅延があるため、正確な実行時刻は意図的に予測できません。snap でインストールした場合、タイマーは代わりに snap.certbot.renew.timer です。dry run では、Let's Encrypt のステージング環境に対して更新処理全体を試行します。実際のチャレンジを実行しますが、証明書は発行されず、レート制限も消費しません。正しい結果の末尾は次のようになります。
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)dry run が失敗する場合、約 60 日後の実際の更新も同じ理由で失敗します。現在の証明書の有効期間が十分に残っているうちに、今すぐ修正してください。よくある原因は、証明書の発行後に追加したファイアウォールルールによって、ポート 80 が再び閉じられていることです。
curl で確認し、南京錠に表示される内容を確認する
curl -sI http://example.com | head -n 3
curl -I https://example.com
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -dates1 つ目は、Location: https://example.com/ ヘッダー付きの HTTP/1.1 301 Moved Permanently を返します。これは Certbot が設定したリダイレクトです。2 つ目は、curl から TLS に関する警告が出ることなく HTTP/1.1 200 OK を返します。3 つ目は発行者を表示します。O = Let's Encrypt の行には、R12 や E7 のような短い CN が含まれ、notAfter はおおむね 90 日後になります。ブラウザーでは南京錠が表示され、クリックすると同じ発行者を確認できます。curl が正常に動作するのにブラウザーが警告を表示する場合、証明書の問題ではなく、キャッシュされたページを表示しているか、誤ったホスト名にアクセスしている可能性がほぼ確実です。
複数サイト: 1 つの SAN 証明書にまとめるか、サイトごとに 1 つの証明書を発行するか
どちらも使用できます。更新方法も同じです。同じサーバー上で無関係なサイトを運用する場合は、サイトごとに issue コマンドを 1 回ずつ実行します。各サイトには live/ 配下に専用ディレクトリと専用の更新設定が作成されます。1 つのドメインで問題が発生しても、他のドメインの更新が妨げられることはありません。これを基本構成にします。
1 つのサイトで複数の名前を使用する場合は、1 つの SAN 証明書にまとめます。1 つの証明書には最大 100 個の名前を含められます。上の例では、すでに example.com と www.example.com を使ってこの構成にしています。後から既存の証明書に名前を追加する場合は、証明書名と、追加後の完全なリストを指定して再発行します。
sudo certbot --apache --cert-name example.com -d example.com -d www.example.com -d blog.example.comCertbot はドメインの構成が変わったことを検出し、証明書に名前を追加するか確認します。その後、同じ live/ パスの証明書をその場で置き換えるため、他の設定を変更する必要はありません。リストは追加ではなく置き換えである点に注意してください。このコマンドから www を省略すると、新しい証明書からその名前が何も表示されずに削除されます。
ワイルドカードには DNS-01 が必要です。通常、ワイルドカードは必要ありません
HTTP-01 では *.example.com を発行できません。Web サーバーにファイルを配置して証明できるのは、1 つのホスト名を管理していることだけであり、名前空間全体を管理していることは証明できません。ワイルドカードには DNS-01 チャレンジが必要です。Certbot は _acme-challenge.example.com に TXT レコードを設定します。実際には、DNS プロバイダーの API 認証情報を使用する certbot-dns-* プラグインが必要です。または、更新のたびに --manual で TXT レコードを手動編集する方法もありますが、運用は困難なため、この方法を前提にしないでください。TXT レコードの仕組みから、更新を自動実行するプラグインまでの詳しい手順は、DNS-01 による Certbot のワイルドカード証明書にあります。率直に言えば、既知のサブドメインが 4 つある場合は、4 つすべてを列挙する SAN 証明書のほうがワイルドカードより簡単です。サーバーに DNS API キーを保存する必要もありません。
障害パターンと表示される文字列
Apache の設定が壊れているため、Certbot が起動しません。
The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError('Error while running apache2ctl configtest.\n\nAction \'configtest\' failed.\nThe Apache error log may have more information.\n\nAH00526: Syntax error on line 12 of /etc/apache2/sites-enabled/example.com.conf')プラグインは何かを変更する前に configtest を実行します。Apache 自体に問題があると処理を中止します。\ns はリテラル文字列です。Certbot が例外の repr を出力するためです。sudo apache2ctl configtest を自分で実行してください。通常は、ファイル名と行番号が表示されます。手作業による編集ミス、存在しなくなったパスを指す SSLCertificateFile、または参照されているものの有効化されていないモジュールが、主な原因です。Syntax OK と表示されるまで修正し、その後 Certbot を再実行してください。
ドメインに一致する vhost がありません。
Unable to find a virtual host listening on port 80 which is currently the only challenge port.これは、前述した missing-ServerName の障害です。証明書発行時に検出されます。Certbot は有効化された port-80 vhost をすべて調べ、指定した -d に一致する ServerName/ServerAlias を探しましたが、見つけられませんでした。sudo apache2ctl -S には、Apache が実際にどのようにルーティングしているかが表示されます。正しい vhost に ServerName 行を追加し、reload してから再試行してください。
これに近いケースとして、検証が 誤った vhost に到達することもあります。別のサイトがリクエストを処理したため、チャレンジへの応答が Invalid response ... 404 になります。診断方法と使用するツールは同じです。apache2ctl -S
検証がタイムアウトします。
Certbot failed to authenticate some domains (authenticator: apache).
...
Detail: ...: Timeout during connect (likely firewall problem)Let's Encrypt は、DNS が通知しているアドレスの port 80 に TCP 接続できませんでした。可能性が高い順に、ufw とは別にホスティングパネルで設定するプロバイダー側のネットワークファイアウォール、443 または SSH だけを許可する ufw ルール、以前のサーバーを指したままの DNS、stale-AAAA の問題が考えられます。stale-AAAA では、Let's Encrypt のサーバーが IPv6 で接続しようとする一方、サーバーは IPv4 でしか応答しません。VPS の 外部 からテストしてください。ノート PC で curl -I http://example.com を実行すると、検証サーバーから見える状態を再現できます。
再試行を繰り返してレート制限に達しました。
Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/Let's Encrypt では、アカウントごとにホスト名あたり 1 時間に 5 回まで検証に失敗できます。2025 年のレート制限の変更以降、これは補充されるバケットになっており、およそ 12 分に 1 回の再試行分が回復します。ファイアウォールが壊れた状態で再試行を繰り返すと、すぐに上限へ達します。待つことでも解決しますが、本当の対策は運用方法を変えることです。失敗したら、成功するまで staging 環境でデバッグしてください。
sudo certbot certonly --apache --dry-run -d example.com -d www.example.comcertonly に注意してください。--dry-run は certonly および renew サブコマンドでのみ受け付けられます。単独の certbot --apache --dry-run 形式は実行自体を拒否し、--dry-run currently only works with the 'certonly' or 'renew' subcommands と表示します。dry run は staging に対して検証します。staging には独自の余裕ある制限があり、実際の証明書は発行されないため、そこで何度失敗しても問題ありません。staging が成功してから、実際のコマンドを再実行してください。
その他の制限である、登録済みドメインあたり週 50 枚の証明書、同じ名前の組み合わせあたり週 5 回の重複発行制限には、スクリプトがループして再発行している場合にだけ達するでしょう。
HTTPS が有効になっても、証明書が保護するのは 通信経路 であり、サーバー自体ではない点に注意してください。port 22 では、今も 1 日中パスワードが推測されています。これと Ubuntu 24.04 での Fail2ban を組み合わせるのが、次の 30 分で行う自然な作業です。
FAQ
Ubuntu 24.04 で Apache 用の Certbot を snap と apt のどちらでインストールすべきですか?
apt を使用してください。Ubuntu 24.04 には Certbot 2.9.0 が同梱されており、このガイドの内容には十分新しく、unattended-upgrades 経由でセキュリティパッチも提供され、snapd も必要ありません。すぐに最新リリースが必要な場合、または snap でのみ配布されている DNS プラグインが必要な場合に限り snap を選択してください。切り替える場合は、2 つの更新スケジューラーが同時に動作しないよう、先に apt remove certbot python3-certbot-apache を実行してください。
Certbot に「Unable to find a virtual host listening on port 80」と表示された場合、どう修正すればよいですか?
-d で指定したドメインに一致する ServerName または ServerAlias を持つ、ポート 80 の有効な vhost が存在しないことが原因です。Ubuntu のデフォルト vhost では ServerName がコメントアウトされています。sudo apache2ctl -S を実行し、その名前を担当する vhost を見つけるか作成して、ServerName example.com を追加します。その後 Apache をリロードし、Certbot を再実行してください。
「Timeout during connect (likely firewall problem)」を修正するにはどうすればよいですか?
Let's Encrypt から、DNS に公開されているアドレスのポート 80 へ接続できませんでした。ufw だけでなく、プロバイダーの管理パネルにあるネットワークファイアウォールも確認してください。dig +short example.com がこの VPS を返すことを確認し、古い AAAA レコードがあれば削除または修正します。AAAA レコードが存在する場合、検証では IPv6 が優先されます。curl -I http://example.com を使用してサーバーの外部から修正結果を確認し、実際に発行する前に sudo certbot certonly --apache --dry-run -d example.com で検証をリハーサルしてください。
Certbot は Ubuntu 24.04 で証明書を自動更新しますか?
はい。apt パッケージは certbot.timer をインストールします。これは 1 日 2 回実行され、期限切れまで 30 日以内の証明書を更新する systemd タイマーです。更新後は Apache もリロードします。snap では同じ処理に snap.certbot.renew.timer を使用します。systemctl list-timers certbot.timer で確認し、sudo certbot renew --dry-run でリハーサルしてください。追加の cron ジョブを独自に登録しないでください。
Certbot と Apache でワイルドカード証明書を取得するにはどうすればよいですか?
ワイルドカードには DNS-01 チャレンジが必要です。Certbot は _acme-challenge.example.com に TXT レコードを登録する必要があるため、DNS プロバイダーの API 認証情報を使用する certbot-dns-* プラグインが必要です。--manual の方式では、更新のたびに TXT レコードを手動で編集する必要があります。既知のサブドメインが少数だけの場合は、それらを明示的に列挙する SAN 証明書のほうが簡単です。また、DNS API キーをサーバーに置かずに済みます。