Установка Certbot для Apache на Ubuntu 24.04
Настройте HTTPS с Let's Encrypt на Ubuntu 24.04 через apt вместо snap. Узнайте, как избежать ошибки ServerName и правильно подготовить конфигурацию Apache для выпуска сертификата.
Что вы создаете
Сайт на базе Apache в Ubuntu 24.04, работающий по протоколу HTTPS с бесплатным, доверенным браузерами сертификатом Let's Encrypt. Сертификат выпускается утилитой Certbot и автоматически обновляется через systemd-таймер, о котором вам не придется вспоминать. Основная работа выполняется одной командой. Все возможные ошибки возникают до выполнения этой команды: виртуальный хост без ServerName, закрытый порт 80 в сетевом экране провайдера или DNS, указывающий на старый сервер. Поэтому данное руководство уделяет основное внимание предварительным условиям и приводит точные тексты ошибок для каждой ситуации.
Два примечания по области применения. Если ваш веб-сервер — nginx, логика действий аналогична, но плагин и конфигурационные файлы будут другими; используйте nginx-версию этого руководства. Если вы защищаете внутренний ресурс — панель администратора с приватным адресом или тестовый сервер, доступный только вам, — центр сертификации не требуется; самоподписанный сертификат требует меньше настроек и работает без подключения к сети.
Предварительные требования и три причины, по которым процесс завершается неудачей еще до запуска Certbot
- Apache уже обслуживает ваш сайт по протоколу HTTP. Плагин Certbot для Apache редактирует существующий сайт, а не создает новый. Если вы начинаете с «чистого» VPS, сначала разверните стек LAMP на Ubuntu 24.04, а затем вернитесь к этому руководству — оно является недостающей главой о настройке TLS.
- Публичный домен с A-записью, указывающей на адрес вашего VPS. Проверка HTTP-01 от Let's Encrypt означает, что их валидационные серверы подключаются к вашей машине из интернета: это исключает использование домашних лабораторий за NAT без проброса портов и имен
.local. HTTP-01 может подтвердить владение голым IP-адресом, но Let's Encrypt выдает сертификаты для IP только в рамках своего опционального профиляshortlived(со сроком действия 160 часов), а версия Certbot 2.9.0 из репозитория apt не умеет запрашивать ни специфические профили ACME, ни сертификаты для IP-адресов, поэтому для данного руководства необходимо доменное имя.dig +short example.comдолжен указывать на адрес вашего VPS. Если вы изменили DNS-записи в течение последнего часа, дождитесь истечения TTL старой записи перед выпуском сертификата. - Если существует AAAA-запись, она должна быть корректной. Let's Encrypt всегда пытается использовать IPv6 в первую очередь, если опубликована AAAA-запись. Если соединение по IPv6 прерывается по таймауту, сервер повторяет попытку через IPv4, но никакие другие ошибки не дают второго шанса: AAAA-запись, указывающая на адрес, который отклоняет соединения, или на другой работающий сервер, приведет к провалу валидации, даже если
curlс вашего ноутбука (вероятно, по IPv4) работает корректно. Опубликуйте корректную AAAA-запись или не публикуйте её вовсе.
Порты 80 и 443 должны быть открыты в ufw, а также в сетевом файрволе вашего хостинг-провайдера; большинство панелей управления хостингом имеют второй уровень защиты, который не видит операционная система. Валидация HTTP-01 выполняется именно через 80 порт; вы не сможете выполнить её, используя только 443 порт.
sudo ufw allow "Apache Full"
sudo ufw statusПри соблюдении этих условий вся процедура займет пятнадцать минут, десять из которых уйдут на чтение.
Snap или apt для Certbot? В 24.04 apt наконец-то подходит
Проект Certbot перешел на распространение через snap несколько лет назад по веской причине: пакеты в дистрибутивах устаревали. В Ubuntu 20.04 поставлялся Certbot 0.40, который не обновлялся, и разработчики устали исправлять ошибки пятилетней давности. В 24.04 эта причина исчезла: в репозитории находится Certbot 2.9.0, релиз февраля 2024 года из современной ветки 2.x, а unattended-upgrades устанавливает любые обновления безопасности, выпускаемые для него Canonical. Основная ветка разработки уже перешла на серию 5.x, но для этого руководства это не требуется. Моя рекомендация для этой ОС: используйте apt. Вы избежите запуска демона snapd, плагин для Apache установится в рамках той же транзакции, а таймер обновления будет интегрирован в systemd стандартным для Debian способом.
sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --versionПравильный результат: certbot 2.9.0. Пакет python3-certbot-apache — это плагин, который читает и редактирует конфигурации Apache; без него certbot --apache завершится с ошибкой The requested apache plugin does not appear to be installed.
Использование snap остается оправданным в двух случаях: вам нужна самая свежая версия Certbot в день выхода или требуется DNS-плагин, который распространяется только в формате snap (некоторые плагины для провайдеров certbot-dns-* доступны только так). Если вы выбираете этот путь:
sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotКакой бы вариант вы ни выбрали, никогда не используйте оба одновременно. Две установки означают два планировщика обновлений, конфликтующих из-за /etc/letsencrypt, а certbot, который ваша оболочка находит в PATH, может оказаться не тем, который управляет вашими сертификатами. Строка apt remove выше — это не просто украшение, она обязательна.
Виртуальный хост, который редактирует Certbot, должен существовать, а ServerName — это ключевой элемент
certbot --apache работает путем поиска виртуального хоста на 80 порту, чей ServerName или ServerAlias совпадает с каждым доменом -d, который вы передаете. Он подтверждает контроль над доменом через этот хост, а затем создает SSL-копию этого виртуального хоста. Если нет соответствующего ServerName, совпадения не будет, а стандартный 000-default.conf в Ubuntu поставляется с закомментированным ServerName. Эта единственная закомментированная строка — самая частая причина, по которой основная команда из этого руководства завершается ошибкой.
Поэтому перед тем, как использовать Certbot, создайте для сайта полноценный виртуальный хост на основе имени. Создайте /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 -Sconfigtest должен вывести Syntax OK. Если он также выводит AH00558: apache2: Could not reliably determine the server's fully qualified domain name, это предупреждение о глобальном параметре 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-enabled, которую он фактически прочитал, а не о файле, который вы редактировали в sites-available. Если example.com не указан для 80 порта, Certbot также не сможет его найти.
Выпуск сертификата: certbot --apache
sudo certbot --apache -d example.com -d www.example.comПри первом запуске утилита запрашивает три параметра: адрес электронной почты (Let's Encrypt больше не хранит его в вашей учетной записи ACME и не отправляет уведомления об истечении срока действия, поэтому отслеживание продлений лежит на вас), согласие с условиями Let's Encrypt и разрешение на передачу вашего адреса в EFF. Вопрос о редиректе больше не задается: начиная с версии Certbot 1.0, установщик Apache по умолчанию перенаправляет HTTP на HTTPS (сам вопрос был исключен в версии 1.4), что обычно и требуется. Используйте флаг --no-redirect, если вам действительно необходимо оставить контент доступным по обычному HTTP.
Успешное завершение выглядит следующим образом, и этот вывод следует прочитать внимательно, а не просматривать бегло:
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 2027-01-09.
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: включение модуля ssl в Apache (если он не был активен), создание файла example.com-le-ssl.conf (копии вашего виртуального хоста в *:443 с директивами SSLEngine on и путями к сертификатам), активация этого хоста и добавление блока RewriteRule в исходный виртуальный хост на порту 80, который выполняет 301-й редирект всего трафика на HTTPS. Ваш исходный файл виртуального хоста редактируется, а не заменяется, а его SSL-версия создается рядом, где вы можете изучить каждую добавленную строку.
Где физически хранятся сертификаты и почему их нельзя копировать
Все файлы находятся в /etc/letsencrypt/live/example.com/: fullchain.pem (сертификат вместе с промежуточной цепочкой, на который должны ссылаться серверы), privkey.pem (закрытый ключ, доступный для чтения только пользователю root), а также cert.pem и chain.pem для программ, требующих раздельные компоненты. Эти файлы являются символическими ссылками на /etc/letsencrypt/archive/. Такая косвенная адресация обеспечивает механизм обновления: при продлении новые файлы записываются в archive/, а символические ссылки перенаправляются на них. Указывайте в настройках любого ПО пути live/, чтобы оно автоматически подхватывало обновленные сертификаты. Если вы скопируете файлы в другое место, через 90 дней вы столкнетесь с простоем сервиса.
Еще один важный файл — /etc/letsencrypt/renewal/example.com.conf. В нем фиксируются параметры выпуска сертификата, authenticator = apache, installer = apache и список доменов. Это позволяет выполнять продление в автоматическом режиме, включая последующую перезагрузку Apache.
Обновление уже запланировано, проверьте его, не создавайте заново
Сертификаты Let's Encrypt по своей архитектуре действуют 90 дней, и пакет apt уже установил необходимый механизм: systemd-таймер, который запускает Certbot дважды в день в случайное время, обновляя любой сертификат, до истечения срока которого осталось менее 30 дней. Не добавляйте поверх этого cron-задачу; второй планировщик лишь создаст лишний шум в логах и риск превышения лимитов запросов. Let's Encrypt объявили, что с 10 февраля 2027 года новые сертификаты по умолчанию будут иметь срок действия 64 дня. 30-дневное окно продолжит работать и с ними, обновление просто произойдет примерно на 34-й день вместо 60-го, поэтому на этом сервере ничего менять не нужно.
systemctl list-timers certbot.timer
sudo certbot renew --dry-runПервая команда показывает, что таймер активен, а время следующего запуска (NEXT) приходится на ближайшие 24 часа. Расписание предусматривает два запуска в сутки со случайной задержкой, поэтому точное время намеренно непредсказуемо (при установке через snap таймер называется snap.certbot.renew.timer). Пробный запуск (dry run) выполняет полную имитацию обновления в тестовой среде Let's Encrypt: проверка проходит по-настоящему, но сертификат не выдается и лимиты не расходуются. Корректный результат завершается строкой:
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)Если пробный запуск завершился ошибкой, реальное обновление через ~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 -datesПервый запрос должен вернуть HTTP/1.1 301 Moved Permanently с заголовком Location: https://example.com/ — это редирект, настроенный Certbot. Второй запрос должен вернуть HTTP/1.1 200 OK без ошибок TLS со стороны curl. Третий выводит издателя, строку O = Let's Encrypt с коротким CN, например YE1 или YE2 (для ключей ECDSA), либо YR1 или YR2 (для ключей RSA), а также notAfter с датой истечения примерно через 90 дней. Сертификат, выданный до того, как Let's Encrypt вывела из эксплуатации свои старые промежуточные сертификаты, может отображать CN вида R12 или E7 до следующего продления; это не является ошибкой. В браузере вы увидите значок замка, при нажатии на который отобразится тот же издатель. Если curl работает, а браузер выдает предупреждение, вы почти наверняка просматриваете кэшированную страницу или используете неверное имя хоста, а не столкнулись с проблемой сертификата.
Несколько сайтов: один SAN-сертификат или отдельный сертификат для каждого сайта
Оба варианта работают, процесс обновления у них одинаковый. Для независимых сайтов на одном сервере запускайте команду выпуска сертификата отдельно для каждого сайта. Каждый из них получит собственный каталог в live/ и индивидуальную конфигурацию обновления, поэтому проблема с одним доменом не помешает обновлению остальных. Это мой стандартный подход.
Для одного сайта с несколькими именами используйте один SAN-сертификат; один сертификат может содержать до 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 в этой команде, новый сертификат будет выпущен без этого домена.
Для подстановочных (wildcard) сертификатов требуется DNS-01, но обычно в них нет необходимости
Метод HTTP-01 не позволяет выпустить *.example.com, так как размещение файла на веб-сервере подтверждает контроль только над одним именем хоста, а не над всем пространством имен. Для подстановочных сертификатов требуется проверка DNS-01: Certbot устанавливает TXT-запись по адресу _acme-challenge.example.com. На практике это означает использование плагина certbot-dns-* с API-ключами вашего DNS-провайдера или ручное редактирование TXT-записей при каждом обновлении с помощью --manual (это крайне неудобно, не стоит рассчитывать на такой вариант). Полное руководство, от механики работы TXT-записей до настройки плагина для автоматического обновления, приведено в подстановочные сертификаты с Certbot через DNS-01. Совет: если у вас есть четыре известных поддомена, сертификат SAN с перечислением всех четырех будет проще, чем подстановочный, и не потребует хранения API-ключей DNS на сервере.
Типичные сбои и сообщения об ошибках
Certbot не запускается из-за поврежденной конфигурации Apache.
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 сообщает об ошибке. Строки \n являются буквальными, так как Certbot выводит строковое представление исключения. Запустите 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 просканировал все активные vhost на 80 порту в поисках ServerName/ServerAlias, соответствующих вашему -d, и ничего не нашел. sudo apache2ctl -S показывает, как Apache фактически маршрутизирует запросы; добавьте строку ServerName в нужный vhost, перезагрузите сервер и повторите попытку. Схожая проблема возникает, когда проверка попадает не в тот vhost, и ответ на запрос проверки возвращает Invalid response ... 404, так как запрос перехватил другой сайт. Диагностика и инструмент те же: apache2ctl -S.
Тайм-аут при проверке.
Certbot failed to authenticate some domains (authenticator: apache).
...
Detail: ...: Timeout during connect (likely firewall problem)Let's Encrypt не удалось установить TCP-соединение с 80 портом по адресу, указанному в вашем DNS. Наиболее вероятные причины в порядке убывания: сетевой брандмауэр провайдера (отдельный от ufw, настраивается в панели управления хостингом), правила ufw, разрешающие только 443 порт или только SSH, либо DNS, все еще указывающий на старый сервер. Устаревшая запись AAAA сама по себе обычно не вызывает эту ошибку, так как при тайм-ауте попытки по IPv6 Let's Encrypt повторяет запрос через IPv4; проблемы с AAAA чаще проявляются как Connection refused или Invalid response от другого сервера. Протестируйте доступность снаружи VPS: curl -I http://example.com с вашего ноутбука воспроизведет то, что видит их валидатор.
Вы превысили лимит запросов из-за частых повторных попыток.
Error creating new order :: too many failed authorizations (5) for "example.com" in the last 1h0m0s, retry after ... UTC: see https://letsencrypt.org/docs/rate-limits/...Let's Encrypt разрешает 5 неудачных проверок на имя хоста для одной учетной записи в час. Это работает как «ведро», которое восстанавливает примерно одну попытку каждые 12 минут, поэтому постоянные повторы при неисправном брандмауэре быстро исчерпывают лимит. Ожидание помогает, но правильный подход — изменить тактику: после любой ошибки проводите отладку в тестовой среде (staging), пока проверка не пройдет успешно.
sudo certbot certonly --apache --dry-run -d example.com -d www.example.comОбратите внимание на certonly: --dry-run принимается только подкомандами certonly и renew, а обычная форма certbot --apache --dry-run вообще отказывается работать, сообщая --dry-run currently only works with the 'certonly' or 'renew' subcommands. Тестовый запуск (dry run) проверяет конфигурацию через staging-среду, у которой свои мягкие лимиты и которая не выпускает реальные сертификаты, поэтому там можно ошибаться сколько угодно. Запускайте реальную команду только после успешного прохождения теста в staging. С другими лимитами — 50 сертификатов на зарегистрированный домен в неделю и 5 дубликатов одного набора имен в неделю — вы столкнетесь только в том случае, если скрипт перевыпускает сертификаты в бесконечном цикле.
Когда HTTPS заработает, помните, что сертификат защищает транспорт, а не сам сервер: порт 22 по-прежнему открыт для попыток подбора пароля. Следующим логичным шагом будет настройка Fail2ban в Ubuntu 24.04, что займет еще около тридцати минут.
FAQ
Стоит ли устанавливать Certbot через snap или apt для Apache в Ubuntu 24.04?
Используйте apt. В Ubuntu 24.04 поставляется Certbot 2.9.0, версия которого достаточно актуальна для всех задач из этого руководства. Она получает все обновления безопасности, выпускаемые Ubuntu через unattended-upgrades, и не требует наличия snapd. Выбирайте snap только в том случае, если вам немедленно требуется самая свежая версия или DNS-плагин, распространяемый исключительно через snap. Если вы переходите на snap, сначала выполните apt remove certbot python3-certbot-apache, чтобы два планировщика обновления не работали одновременно.
Почему Certbot сообщает "Unable to find a virtual host listening on port 80"?
Потому что ни один активный vhost на 80 порту не содержит ServerName или ServerAlias, соответствующих домену, который вы передали через -d. В стандартном vhost Ubuntu директива ServerName закомментирована. Выполните sudo apache2ctl -S, найдите (или создайте) vhost, который должен отвечать за это имя, добавьте ServerName example.com, перезагрузите Apache и запустите Certbot снова.
Как исправить ошибку "Timeout during connect (likely firewall problem)"?
Let's Encrypt не удалось подключиться к 80 порту по адресу, который указан в ваших DNS. Проверьте сетевой брандмауэр на уровне панели управления провайдера, а также ufw. Убедитесь, что dig +short example.com возвращает IP-адрес этого VPS, и исправьте или удалите устаревшие AAAA-записи, так как проверка сначала пытается использовать IPv6 и переходит на IPv4 только после тайм-аута. Проверьте исправление снаружи сервера с помощью curl -I http://example.com, а затем выполните пробный запуск с sudo certbot certonly --apache --dry-run -d example.com перед реальным получением сертификата.
Обновляет ли Certbot сертификаты автоматически в Ubuntu 24.04?
Да. Пакет apt устанавливает certbot.timer — таймер systemd, который запускается дважды в день и обновляет любой сертификат, если до истечения срока его действия осталось менее 30 дней, после чего перезагружает Apache. Версия из snap использует для этой же задачи snap.certbot.renew.timer. Проверьте статус с помощью systemctl list-timers certbot.timer и выполните пробный запуск через sudo certbot renew --dry-run; не добавляйте собственные задания cron поверх существующих.
Как получить wildcard-сертификат с помощью Certbot и Apache?
Для wildcard-сертификатов требуется проверка DNS-01: Certbot должен разместить TXT-запись в _acme-challenge.example.com. Это означает использование плагина certbot-dns-* с API-ключами вашего DNS-провайдера (альтернатива --manual требует ручного редактирования TXT-записей при каждом обновлении). Если у вас всего несколько известных поддоменов, проще использовать SAN-сертификат с их явным перечислением — это позволит не хранить API-ключи DNS на сервере.