SSD Nodes Learn
ガイド Matt Connor著者 Matt Connor ・更新日 2026-07-24

Ubuntu 24.04でApacheにCertbotを導入する方法

Ubuntu 24.04のApacheにLet's Encryptを導入する手順を解説します。snapを使わずaptでCertbot 2.9.0をインストール可能です。設定ミスで証明書発行が失敗するServerNameの罠や、IPv6のAAAA recordによる検証エラーの回避策について詳しく説明します。

作成するもの

Ubuntu 24.04 上の Apache サイトです。Let's Encrypt の無料のブラウザ信頼証明書を使用して HTTPS で応答します。証明書は Certbot によって発行され、systemd timer によって自動更新されるため、管理の手間はかかりません。実行するコマンドは 1 行のみです。エラーが発生する場合、その原因はすべてその行に到達する にあります。例えば、ServerName が設定されていない vhost、プロバイダーのファイアウォールで閉じられた port 80、古いサーバーを指したままの DNS などです。そのため、このガイドでは前提条件に重点を置き、各ミスが発生した際に出力される正確なエラー文字列を記載します。

2 つの補足事項があります。Web サーバーが nginx の場合、手順の流れは同じですが、使用する plugin と設定ファイルが異なります。その場合は nginx 版のガイド を参照してください。また、保護対象が内部専用(プライベートアドレス上の管理パネルや、他者がアクセスしないステージング環境など)である場合、認証局は不要です。自己署名証明書 を使用する方が構成がシンプルで、オフラインでも動作します。

前提条件、およびCertbot実行前に失敗する3つの原因

  • Apacheが既にHTTPでサイトを公開していること。 CertbotのApache pluginは既存のサイトを編集します。新規作成は行いません。VPSをセットアップした直後の場合は、まずUbuntu 24.04でのLAMP stackを構築してください。本ガイドはその続きのTLS設定です。
  • VPSのIPアドレスをA recordに持つ公開ドメイン。 Let's EncryptのHTTP-01 challengeは、検証サーバーがインターネット経由でサーバーに接続します。ポートフォワード設定のないNAT環境のホームラボ、.local、IPアドレスのみの構成では不可能です。dig +short example.comはVPSのIPアドレスを返す必要があります。DNSを変更した直後の場合は、TTLが切れるまで待機してください。
  • AAAA recordが存在する場合、それが正しいこと。 AAAA recordが公開されている場合、Let's EncryptはIPv6を優先します。そのため、ノートPCから(おそらくIPv4で)curlが成功しても、古いAAAA recordが残っていると検証に失敗します。正しいAAAA recordを公開するか、あるいは一切公開しないでください。

Port 80 および 443は、ufwとプロバイダーのネットワークファイアウォールの両方で開放されている必要があります。多くのホスティングパネルには、OSからは見えない別のファイアウォールが存在します。HTTP-01はPort 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ではその問題は解消されています。アーカイブには最新世代のCertbot 2.9.0が含まれており、unattended-upgradesがパッチを適用し続けています。このOSではaptの使用を推奨します。snapdデーモンが不要になり、Apacheプラグインも同じトランザクションでインストールされます。また、更新タイマーはDebianの標準的な方法でsystemdに統合されます。

sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --version

正しい結果は certbot 2.9.0 です。python3-certbot-apache パッケージはApacheの設定を読み取り編集するプラグインです。これがないと、certbot --apacheThe requested apache plugin does not appear to be installed で失敗します。

以下の2つのケースでは、依然としてsnapが適しています。リリース当日に最新のCertbotが必要な場合、またはsnapでしか配布されていないDNSプラグインが必要な場合です(certbot-dns-* プロバイダーのプラグインのいくつかが該当します)。その場合は以下を実行してください。

sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

どちらか一方のみを選択してください。両方をインストールしてはいけません。2つのインストールが存在すると、更新スケジューラが /etc/letsencrypt を巡って競合します。また、PATH にあるシェルが参照する certbot は、証明書を管理しているものとは異なる可能性があります。上記の apt remove の行は、単なる装飾ではありません。

vhostのCertbot設定は作成済みである必要があります — ServerNameが重要です

certbot --apacheは、指定された各-dドメインに一致するServerNameまたはServerAliasを持つport-80のvirtual hostを検索することで動作します。これによりドメインの所有権を証明し、そのvhostのSSL版を作成します。一致するServerNameがない場合、一致しません。Ubuntuのデフォルトの000-default.confでは、ServerNameがコメントアウトされています。このコメントアウトされた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が設定を解析してその名前へルーティングしているか確認します:

sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo apache2ctl -S

configtestSyntax OKを出力する必要があります。もしAH00558: apache2: Could not reliably determine the server's fully qualified domain nameも出力される場合、それはvhostではなくglobalなServerNameに関する警告です。この場合は問題ありません。echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf && sudo a2enconf servername && sudo systemctl reload apache2で非表示にできます。

重要な確認事項は-Sの出力です。port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1)のような行があり、その下にalias www.example.comが表示されている必要があります。Apacheはsites-availableで編集したファイルではなく、実際に読み込んだsites-enabledのsymlinkを報告します。port 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インストーラーはデフォルトで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 モジュールが未有効であれば有効化しました。次に、*:443 にある vhost のコピーとして、SSLEngine on と証明書のパスを含む example.com-le-ssl.conf を作成しました。その後、モジュールを有効化しました。最後に、元の port-80 vhost に、すべての通信をHTTPSへ301リダイレクトする RewriteRule ブロックを追加しました。元の vhost ファイルは上書きではなく編集されます。SSL用の複製ファイルは元のファイルの隣に作成され、追加された行をすべて確認できます。

証明書の実際の保存場所と、コピーしてはいけない理由

すべてのファイルは /etc/letsencrypt/live/example.com/ に格納されます。これには、fullchain.pem(証明書と中間チェーン。サーバーが参照すべきもの)、privkey.pem(秘密鍵。rootのみ読み取り可能)、および各ソフトウェア用に個別のファイルを提供する cert.pemchain.pem が含まれます。これらは /etc/letsencrypt/archive/ への symlink です。この間接参照が更新の仕組みです。更新時には archive/ に新しいファイルが書き込まれ、symlink の参照先が切り替えられます。他のソフトウェアの参照先を live/ のパスに設定すれば、自動的に更新が適用されます。ファイルを別の場所にコピーすると、90日後にサービス停止が発生します。

もう一つ重要なファイルは /etc/letsencrypt/renewal/example.com.conf です。これには、authenticator = apacheinstaller = apache、ドメイン名など、証明書の発行情報が記録されています。これにより、Apache の再読み込みを含め、更新プロセスを自動で繰り返すことができます。

更新は既にスケジュールされています — 確認のみ行い、手動で実行しないでください

Let's Encrypt の証明書の有効期限は 90 日間です。apt パッケージによって、必要な仕組みは既にインストールされています。これは、Certbot を 1 日に 2 回、ランダムなタイミングで実行する systemd timer です。有効期限まで 30 日を切った証明書が自動的に更新されます。追加の cron job を設定しないでください。二重にスケジューラを動かすと、ログのノイズが増えるだけで、rate-limit に抵触するリスクが高まります。

systemctl list-timers certbot.timer
sudo certbot renew --dry-run

最初のコマンドは、タイマーがアクティブであることを示します。NEXT には今後 24 時間以内の時間が表示されます。スケジュールは 1 日 2 回で、遅延がランダムに設定されているため、正確な時間は予測できません(snap 版の場合は、タイマーは snap.certbot.renew.timer になります)。dry run を実行すると、Let's Encrypt の staging 環境に対して更新のシミュレーションを行います。実際のチャレンジが行われますが、証明書は発行されず、rate-limit の制限も受けません。成功すると、以下の結果が表示されます。

Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)

dry run が失敗した場合、約 60 日後の実際の更新も同様に失敗します。現在の証明書の有効期限に余裕があるうちに、今すぐ問題を解決してください。よくある原因は、証明書発行後に追加されたファイアウォールルールによって、port 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 -dates

1つ目の結果は、Certbotが設定したリダイレクトを示す Location: https://example.com/ ヘッダーを持つ HTTP/1.1 301 Moved Permanently である必要があります。2つ目の結果は、curlでTLSエラーが発生しない HTTP/1.1 200 OK である必要があります。3つ目は発行者を表示します。これは R12E7 といった短いCNを持つ O = Let's Encrypt 行であり、有効期限は notAfter 程度です。ブラウザでは鍵マークが表示され、クリックすると同じ発行者が表示されます。curlで成功するのにブラウザで警告が出る場合は、証明書の問題ではなく、キャッシュされたページか誤ったhostnameを参照している可能性が非常に高いです。

複数サイト:1つの SAN certificate を使うか、サイトごとに certificate を作成するか

どちらの方法でも動作し、更新手順も同じです。同一サーバー上の無関係なサイトに対しては、サイトごとに 1 回ずつコマンドを実行してください。各サイトは live/ 内に個別のディレクトリと更新設定を持ちます。これにより、1 つのドメインで問題が発生しても、他のドメインの更新が妨げられることはありません。これが推奨されるデフォルトの設定です。

複数の名前を持つ 1 つのサイトの場合は、1 つの SAN certificate にまとめてください。1 つの certificate には最大 100 個の名前を含めることができます。すでに example.comwww.example.com でこの方法を使用しています。既存の certificate に後から名前を追加するには、新しい全リストを指定して再発行してください。

sudo certbot --apache --cert-name example.com -d example.com -d www.example.com -d blog.example.com

Certbot はドメインセットの変更を検知し、拡張の確認を求めます。確認後、certificate は既存の live/ パスに上書きされます。そのため、他の設定を変更する必要はありません。注意点として、リストは「追加」ではなく「置換」です。コマンドから www を除外すると、新しい certificate からそのドメインが削除されます。

Wildcards requires DNS-01; usually, they are unnecessary

HTTP-01 cannot issue *.example.com です。Web server にファイルを配置する方法は、特定の hostname の所有権を証明するものであり、namespace 全体を示すものではありません。Wildcard には DNS-01 challenge が必要です。Certbot は _acme-challenge.example.com に TXT record を設定します。これには、DNS provider の API 認証情報を持つ certbot-dns-* plugin を使用するか、更新のたびに --manual で TXT record を手動編集する必要があります(非常に手間がかかるため、推奨しません)。TXT record の仕組みから、自動更新プラグインの詳細については、wildcard certificates with Certbot over DNS-01 を参照してください。アドバイスとして、既知の subdomain が 4 つある場合、それらすべてを SAN certificate に含める方が、Wildcard を使用するよりも簡単です。また、サーバーに DNS API key を保持する必要もありません。

発生するエラーと表示される文字列

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.

これは、以前説明した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、またはIPv6の問題(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つのホスト名につき、1つのアカウントにつき、1時間あたり5回までの検証失敗が許可されています。2025年のレートリミット改訂以降、これは「リフィリング・バケット」方式となり、約12分ごとに1回分のリトライ枠が回復します。ファイアウォールの設定ミスに対してリトライを繰り返すと、すぐに枠を使い果たします。待機すれば解決しますが、根本的な対策は「失敗したらstaging環境でデバッグし、成功を確認してから本番コマンドを実行する」という運用です。

sudo certbot certonly --apache --dry-run -d example.com -d www.example.com

certonlyに注意してください。--dry-runcertonlyまたは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へのパスワード総当たり攻撃は、引き続き発生します。これに対処するために、Ubuntu 24.04でFail2banを導入することをお勧めします。

FAQ

Ubuntu 24.04のApacheで、Certbotはsnapとaptのどちらをインストールすべきですか?

aptを使用してください。Ubuntu 24.04にはCertbot 2.9.0が搭載されており、本ガイドの内容には十分なバージョンです。unattended-upgradesを通じてセキュリティパッチが提供され、snapdは不要です。最新リリースが直ちに必要である場合や、snapでのみ配布されているDNS pluginが必要な場合にのみsnapを選択してください。その際、2つの更新スケジューラが共存しないよう、先にapt remove certbot python3-certbot-apacheを行う必要があります。

Certbotが "Unable to find a virtual host listening on port 80" と表示されるのはなぜですか?

-dで渡したドメインと一致する、ServerNameまたはServerAliasを持つ有効なport-80 vhostが存在しないためです。Ubuntuのデフォルトのvhostは、ServerNameがコメントアウトされています。sudo apache2ctl -Sを実行し、該当する名前を持つvhostを特定(または作成)して、ServerName example.comを追加してください。その後、Apacheをreloadし、Certbotを再実行してください。

"Timeout during connect (likely firewall problem)" の解決方法は?

Let's Encryptが、DNSで公開されているアドレスのport 80に到達できませんでした。プロバイダーのコントロールパネルにあるネットワークファイアウォールとufwを確認してください。dig +short example.comがこのVPSを返していることを確認し、古いAAAAレコードがあれば削除または修正してください。IPv6が存在する場合、検証はIPv6を優先します。サーバー外部からcurl -I http://example.comで修正を確認し、本番の証明書発行前にsudo certbot certonly --apache --dry-run -d example.comでテストを行ってください。

Ubuntu 24.04ではCertbotは証明書を自動更新しますか?

はい。aptパッケージはcertbot.timerをインストールします。これは1日2回実行されるsystemd timerであり、有効期限まで30日以内の証明書を更新した後、Apacheをreloadします。snapの場合は、同様の処理にsnap.certbot.renew.timerを使用します。systemctl list-timers certbot.timerで確認し、sudo certbot renew --dry-runでテストを行ってください。独自のcronジョブを追加する必要はありません。

CertbotとApacheでワイルドカード証明書を取得する方法は?

ワイルドカードにはDNS-01 challengeが必要です。Certbotは_acme-challenge.example.comにTXTレコードを配置する必要があります。これには、DNSプロバイダーのAPI資格情報を持つcertbot-dns-* pluginが必要です(--manualの代替手段では、更新のたびにTXTレコードを手動で編集する必要があります)。既知のサブドメインが数個程度であれば、それらを明示的にリストしたSAN証明書の方が簡単であり、サーバーにDNS APIキーを置かずに済みます。