Discourse не удалось обновить сертификат

Продолжаем обсуждение отсюда:

Я получил уведомление от Redsift о том, что мои сертификаты истекут через неделю. Обычно Discourse обновляет сертификаты задолго до истечения срока действия. В этот раз всё иначе: прежде чем я начну пересборку (которая, как ожидается, решит проблему), @Falco, есть ли что-то, что мне стоит проверить и сообщить здесь, чтобы помочь выявить причину, по которой сертификаты не были обновлены?

Корневой сертификат — ISRGX1, а вот информация об истекающем сертификате:

Общее имя (CN) E6
Организация (O) Let’s Encrypt
Организационное подразделение (OU) <Не входит в сертификат>
Выдан Среда, 16 июля 2025 г., 19:36:45
Истекает Вторник, 14 октября 2025 г., 19:36:44

Текущая сборка — 3.6.0.beta1-dev (7ee52c8f85)

1 лайк

В определённый период времени endpoint, необходимый Let’s Encrypt, был перенаправлен. Это исправляется при пересборке.

5 лайков

Примерно через сколько времени после обновления должен быть продлён сертификат?

Если память мне не изменяет, сертификаты действительны в течение 3 месяцев, и теперь они попытаются автоматически продлить срок действия до истечения этого срока.

1 лайк

Да, я знаю, как это должно работать.

Но с момента обновления программного обеспечения форума прошло уже больше суток, и сертификат, похоже, так и не обновился. До его истечения осталось 5 дней, поэтому его срочно нужно продлить.

Я использую стабильную ветку Discourse, если это имеет значение. Возможно, исправление конечной точки еще не было перенесено в эту ветку?

Для меня сертификат обновился сразу после пересборки

Вы пересобрали через веб-интерфейс или через командную строку?

1 лайк

Да, объяснение было здесь:

1 лайк

Мой форум наконец обновил сертификат после того, как я выполнил пересборку через командную строку.

3 лайка

У нас возникла та же проблема с невозобновлением SSL.

Будет здорово, если кто-нибудь проверит, корректно ли работает web.ssl.template в discourse-docker. Мне показалось, что порт 80 не обслуживает URL-адреса в формате /.well-known/, используемые Let’s Encrypt: все запросы перенаправлялись на SSL, включая тестовые файлы, которые я вручную разместил в /var/www/discourse/public/.well-known/. Пришлось напрямую отредактировать файл /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf внутри контейнера приложения.

Возможно, это началось после коммита ae4887a в репозитории discourse-docker?

2 лайка

В последнее время снова возникла ошибка с известным маршрутом.

Когда вы последний раз выполняли пересборку?

2 лайка

У меня то же самое. Я не получил предупреждения о сроке действия сертификата. Перезапуск сервера и запуск пересборки /var/discourse % ./launcher rebuild помогли.

2 лайка

При тестировании на чистой установке nginx (версия 1.18.0, но, думаю, то же самое для 1.26.3) строка конфигурации nginx return 301 https://thehostname$request_uri;, расположенная вне блока location, полностью перекрывает любой предшествующий блок location, вместо того чтобы работать как универсальный обработчик. Мне кажется, что /.well-known/ просто не обслуживается на порту 80, если перенаправление 301 явно не настроено для другого расположения, например /, в конце блока server. Возможно, это та же проблема, что и в этом посте на Stack Overflow?

Рад, что пересборка работает, но поскольку сертификат уже был продлён для меня, я не мог подтвердить, что пересборка позволит серверам валидации Let’s Encrypt получить доступ к нужным ресурсам, если бы сертификат истёк. Возможно, пересборка запускает процесс продления сертификата до того, как в шаблоне появится соответствующая строка, или что-то подобное, а не исправляет сами шаблоны, но я не могу подтвердить, что именно поэтому пересборка позволяет продлению сработать.

Если вы считаете, что это связано с Discourse, то, возможно, вам стоит ответить на коммит в GitHub или открыть новый отчет об ошибке.

1 лайк

Могу подтвердить, что обновление сертификата Let’s Encrypt не выполняется. Я уже несколько лет использую самохостинговую установку Discourse, и очень странно, что за последние пару месяцев обновление не сработало дважды подряд. Второй раз это произошло сегодня утром, и я начал расследование.

Я проследил проблему до следующих двух коммитов:

И соответствующая строка по ссылке:

https://github.com/discourse/discourse_docker/commit/c9064be6b7a743e3d86dbc69ddaa80701766aa87#diff-b8c95dfe3760424eecc60d21538dbd785f096d46ef95764c60f4b608f40dd536R26

Кажется, есть две проблемы.

Во-первых, return 301 https://${DISCOURSE_HOSTNAME}$request_uri; преобразуется в return 301 https://<МОЁ ИМЯ СЕРВЕРА> без $request_uri в конце. Я проверил это на своей самохостинговой установке, а также на установке друга, настроенной на прошлой неделе. Я не понимаю, как работают шаблоны Discourse, поэтому не знаю, почему $request_uri теряется.

Во-вторых, как отметил @lessLost, 301-редирект находится вне блока location. Я считаю, что редирект на уровне server переопределяет все блоки location. Let’s Encrypt использует HTTP для обновления сертификатов. Однако любая попытка выполнить curl -I http://ВАШ_ДОМЕН/.well-known/acme-challenge/test возвращает 301-редирект на HTTPS вместо 404 (что является ожидаемым поведением; нам нужен 404, а не 301).

Я исправил это вручную на своей самохостинговой установке, но ожидаю, что любое обновление перезапишет мои изменения. К сожалению, я недостаточно хорошо понимаю шаблоны, чтобы отправить pull request @pfaffman — иначе я бы это сделал.

Дополнено:

Я считаю, что это ошибочно —

Я почти уверен, что Let’s Encrypt по умолчанию использует HTTP (по очевидным причинам: если сертификат истёк, он не может обновиться!). Однако размещение 301-редиректа на уровне блока server заставляет все запросы перенаправляться на HTTPS, что противоречит этой стратегии обновления.

Дополнение 2: Подтверждение стратегии обновления через HTTP, но вы также можете поискать в Google, чтобы убедиться в этом.

1 лайк

Когда вы в последний раз выполняли пересборку?

Сегодня утром, примерно через 10 минут после пробуждения, я зашёл на свой форум и обнаружил, что сертификат снова истёк. (Последний раз, когда это произошло со мной — примерно 3 месяца назад — обновление было выполнено путём пересборки.)

Похоже, что с тех пор были внесены изменения, которые исправляют эту проблему, но поскольку на проверку уходит 3 месяца, окончательного вердикта ещё нет. Возможно, стоит установить напоминание за пару недель до истечения текущего сертификата.

1 лайк

Это неверно.

  1. Ссылки, которые я приложил в комментарии выше, были из git blame. Вот последняя версия файла (ссылка на соответствующую строку): discourse_docker/templates/web.ssl.template.yml at 247c71a1e45d32b0b814a8e9d5fdaa4faaf727b9 · discourse/discourse_docker · GitHub
  2. Установка нового сайта моего друга была сделана неделю назад. Строка 37 шаблона выше содержит: return 301 https://${DISCOURSE_HOSTNAME}$request_uri;, но в контейнере Discourse Docker как у неё, так и у меня файл /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf содержит return 301 https://<our_discourse_site>;. Обратите внимание, что $request_uri удалён. Что-то вызывает его исчезновение! (Я не знаю, что именно).
  3. Сегодня утром я провёл симуляцию принудительного обновления в рамках расследования. Оно не удалось. Затем я изменил файл /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf. После этого обновление прошло успешно!

На самом деле это не проблема; я просто буду вручную редактировать 20-redirect-http-to-https.conf каждый раз при обновлении Discourse. Для тех, кто наткнулся на этот комментарий, команда для выполнения:

cat > /etc/nginx/conf.d/outlets/before-server/20-redirect-http-to-https.conf << 'EOF'
server {
  listen 80;
  listen [::]:80;

  location ~ /.well-known {
    root /var/www/discourse/public;
    allow all;
  }

  location / {
    return 301 https://<YOUR_FORUM_ADDRESS>$request_uri;
  }
}
EOF

Я не полностью уверен, что вызывает эту ошибку, но знаю, что изменение конфигурации выше решает проблему. Однако я также модифицировал уведомления, чтобы обновления letsencrypt больше не завершались неудачей без предупреждения — теперь у меня будет заблаговременное оповещение. Просто хотел, чтобы вы знали!

4 лайка

Спасибо за отчёт, я думаю, это действительно так.

(для информации @featheredtoast)

6 лайков