Вступление

Я пользуюсь сертификатами Let's Encrypt с незапамятных времён... ладно, с 2016 года, на самом деле. До выхода этого сервиса в "широкие массы" я использовал бесплатный сертификат, выданный сроком на год (от другой конторы). И так совпало, что Let's Encrypt позволил мне продолжить предоставление доступа (возможно, после некоторого небольшого перерыва) к контенту по протоколу HTTPS. Но надо понимать, что я - совсем не админ, и в то время делал только свои первые шаги в мире Linux, да и сейчас себя особо опытным пользователем не считаю. И требование обновлять сертификат каждые три месяца меня довольно сильно напрягало, несмотря на то, что уже тогда существовали многочисленные руководства. Я же просто не мог полноценно ими воспользоваться, так как, банально, не имел опыта и знаний. Поэтому, первое время, ставил себе напоминалки и вручную перевыпускал сертификат.

Как известно, лень - двигатель прогресса. Обновлять сертификат вручную надоело достаточно быстро и я принялся углубляться в тему автоматизации повторяющихся задач на Linux. Да, речь про cron и всё такое. На самом деле, автоматизировать обновление сертификата было не самой большой проблемой, в большей степени меня смущал вопрос, как обеспечить его использование для моих серверов. Поясню подробнее.

Основным программным обеспечением, которым должен был использоваться сертификат, являлся (и является) HAProxy, работающий у меня как в качестве обратного прокси сервера (reverse proxy), так и в качестве сервера для терминирования SSL трафика (SSL termination server). Вот именно эта вторая роль и предполагает использование сертификата.

Как известно, Let's Encrypt предлагает целый ряд клиентов. Конечно, изначально их было меньше - это сейчас в списке есть клиент для HAProxy и даже для Mako Server-а (продукт авторства той же компании, что и используемый мною FuguHub). Но основным рекомендуемым клиентом (и тогда, и сейчас) является Certbot. У Certbot-a достаточно подробная документация, в которой можно найти ответы если не на все, то на очень многие вопросы. Основной проблемой тут является способность эти вопросы сформулировать[1]. Есть в ней и информация о том, как автоматизировать процесс перевыпуска (обновления) сертификатов[2].

Моей целью не является повторение того, что написано в документации или в разнообразных статьях, разбросанных по интернету. Я хочу описать свой опыт, который может оказаться полезным, а может и нет. Решение, которое я сейчас использую - результат развития используемого клиента, углубления (надеюсь) моих знаний и изменения набора используемого у меня софта, и, естественно, оно (решение) претерпевало модификацию и модернизацию по мере изменения этих вводных. Поэтому в данном тексте будет довольно много "воды", в которой отражаются мои метания и "путь воина", что не всегда бывает нужно и интересно читателю. Если вы пришли сюда за результатом всей этой продолжительной истории - следуйте прямиком к нему.

Первые шаги

Для начала, я решил (для себя), что буду использовать при перевыпуске сертификата простейший сценарий. И первым пунктом в этом решении шло использование рекомендуемого клиента (Certbot), а вторым - использование плагина standalone. Эти пункты не вызвали особых затруднений: тогда, в 2016-ом, больше доверия вызывал именно рекомендуемый клиент, ну а то, что я хотел использовать сертификат с HAProxy (и уж тем более с FuguHub), делало невозможным использование каких бы то ни было специализированных плагинов, как в случае, если бы речь шла об Apache или Nginx (сторонний плагин для HAProxy появился позже).

Освобождение 80-го порта

Следующей задачей, которую мне пришлось решать, было обеспечение условий для работы standalone плагина. Проблема заключалась в том, что при использовании этого плагина взаимодействие клиента (Certbot) и сервиса Let's Encrypt осуществляется через 80-ый порт, который, в свою очередь, используется HAProxy. А, как известно, один порт - одна программа. Поэтому, на время, пока производится обновление сертификата, HAProxy надо "погасить"[3].

К счастью, практически с самого начала существования клиента Certbot, у него есть параметры командной строки --pre-hook и --post-hook, которые позволяют указать действия перед и после взаимодействия с сервисом Let's Encrypt. Как не сложно догадаться, именно ими я и воспользовался: в --pre-hook я останавливаю HAProxy, используя команду service haproxy stop (позже я заменил её на systemctl stop haproxy), а в --post-hook вновь запускаю его при помощи service haproxy start (эту команду я тоже позже заменил на systemctl start haproxy). Помимо использования параметров командной строки имеется также возможность конфигурировать параметры обновления для сертификатов при помощи конфигурационных файлов в каталоге /etc/letsencrypt/renewal. Клиент постоянно развивается, в нём происходят изменения. Так, --renew-hook был постепенно заменён на --deploy-hook, а сами hook-и стало возможным настраивать, размещая нужные командные файлы в подкаталогах deploy, pre и post каталога /etc/letsencrypt/renewal-hooks.

Действия после перевыпуска сертификата

Вторая задача заключалась в том, чтобы программы, которым это нужно, могли воспользоваться перевыпущенными сертификатами. В моём случае, это были HAProxy и FuguHub. И надо отдать должное авторам Certbot - они позаботились о том, чтобы дать возможность таким, как я, выполнить необходимые действия. Для этого ими был первоначально предусмотрен параметр командной строки renew-hook, который потом, как я уже писал, был заменён на --deploy-hook[4]. Так как действий мне надо выполнить достаточно много, я написал скрипт (командный файл), который и стал указывать в качестве значения для этого hook-а. Поговорим немного (😏) про этот скрипт (командный файл).

Перевыпущенный сертификат и HAProxy

Я использую HAProxy в качестве терминального сервера для SSL/TLS трафика. То есть, до него идет зашифрованный HTTPS трафик, а после него, по локальной сети, идет обычный HTTP трафик. Я поступаю так из-за того, что не все мои self-hosted сервисы умеют работать с защищённым трафиком. Конечно, постоянно выходят обновления ПО, и, в частности, у некоторых сервисов за последнее время была добавлена возможность работы по протоколу HTTPS. Но, во-первых, это происходит совершенно непредсказуемо по времени, а во-вторых, есть ПО, которое, практически не обновляется и поддержки этого протокола для такого софта ожидать не приходится.

Важно отметить, что у меня HAProxy и Certbot используются на одном и том же хосте - это существенно упрощает командный файл. Итак, чтобы HAProxy смог воспользоваться перевыпущенным сертификатом, в скрипт, который выполняется при успешном обновлении сертификата, я добавил следующие строки:

#!/bin/bash
cd /etc/letsencrypt/live/my.domain.name
cat fullchain.pem privkey.pem > my.domain.name.pem
cp my.domain.name.pem /etc/ssl/
# Далее идут команды, связанные с FuguHub

Поясню, что тут, собственно, происходит. Для того, чтобы HAProxy мог работать с зашифрованным трафиком, ему необходимо предоставить один файл, в котором должна быть указана и полная цепочка сертификатов от конечного (выпущенного) сертификата до сертификата удостоверяющего центра (с публичными ключами, естественно) и защищенный ключ, соответствующий публичному ключу в конечном сертификате[5].

При каждом выпуске (или перевыпуске) сертификата при помощи Certbot, на хосте, с которого запускается агент (а запускается он с правами суперпользователя), в каталоге /etc/letsencrypt/archive/CERT_NAME (где CERT_NAME - имя сертификата, которое, обычно, либо совпадает с доменным именем, для которого выпускается сертификат[6], либо указывается в качестве значения для параметра командной строки --cert-name; далее в нашем примере будем считать, что CERT_NAME равен my.domain.name), создается несколько файлов, описывающих выпущенный (обновлённый) сертификат (в именах присутствует порядковый номер запроса на выпуск, чтобы не перетирались прошлые версии). В тоже время, в каталоге /etc/letsencrypt/live/CERT_NAME создаются ссылки на самые свежие версии этих созданных файлов. Ссылки всегда называются одинаково. С точки зрения HAProxy нас интересуют две ссылки. Одна из них называется fullchain.pem, и она указывает на файл, в котором сохранена цепочка сертификатов, от выпущенного (конечного) до корневого (принадлежащего удостоверяющему центру). Другая ссылка, с названием privkey.pem, указывает на файл с защищенным ключом той пары, для публичного ключа которой и выпущен конечный сертификат.

Первая команда скрипта:

cd /etc/letsencrypt/live/my.domain.name

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

Следующая команда скрипта:

cat fullchain.pem privkey.pem > my.domain.name.pem

предназначена для того, чтобы "слить" два файла - с цепочкой сертификатов и с приватным ключом - воедино (в файл с именем my.domain.name.pem).

Ну и последняя команда:

cp my.domain.name /etc/ssl/

просто копирует получившийся файл в каталог /etc/ssl/.

Сам же HAProxy настроен (в файле конфигурации /etc/haproxy/haproxy.cfg) на то, чтобы взять нужную ему для работы с зашифрованным трафиком информацию из файла /etc/ssl/my.domain.name.pem:

bind    *:443 ssl crt /etc/ssl/my.domain.name.pem

Перевыпущенный сертификат и FuguHub

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

# Перед этим идут команды, связанные с HAProxy
openssl rsa -in privkey.pem -out bdprivkey.pem
scp bdprivkey.pem root@FUGUHUB_HOST:/home/bd/server.key
scp fullchain.pem root@FUGUHUB_HOST:/home/bd/server.cert
ssh -t -t root@FUGUHUB_HOST '/etc/init.d/bdd stop'
ssh root@FUGUHUB_HOST '/etc/init.d/bdd start < /dev/null > /tmp/mylogfile 2>&1 &'

где FUGUHUB_HOST - хост, на котором крутится FuguHub.

Прежде, чем мы подробнее поговорим про эти команды, надо отметить вот какой момент. Так как работа с удалённым хостом будет вестись по протоколу SSH, то, чтобы не возникало требования по вводу пароля, на которое, очевидно, нам не удастся отреагировать (скрипт будет запускаться из deploy-hook-а, а сам hook - из команды обновления, которая, в свою очередь, будет вызываться из задачи cron), надо предварительно настроить соединение с использованием ключей (ну, или если хост находится под управлением Windows 10).

А теперь разберём приведённые выше команды. Первая:

openssl rsa -in privkey.pem -out bdprivkey.pem

предназначена для конвертации приватного ключа в формат, который понимает FuguHub. Дело в том, что файл, на который ссылается privkey.pem, создаётся Certbot-ом в формате PKCS#8, а FuguHub ожидает файл приватного ключа в формате RSA PEM. Отличаются они строками, обрамляющими непосредственно приватный ключ - у PKCS#8 это:

-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

а у RSA PEM:

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

Таким образом, приведённая выше команда просто изменяет header и footer в первоначальном файле, сохраняя получившийся результат под именем bdprivkey.pem (так как это продолжение скрипта, не забудем, что находимся в подкаталоге /etc/letsencrypt/live/my.domain.name).

Следующие две команды:

scp bdprivkey.pem root@FUGUHUB_HOST:/home/bd/server.key
scp fullchain.pem root@FUGUHUB_HOST:/home/bd/server.cert

копируют файл приватного ключа и полной цепочки сертификатов на удалённый хост с работающим FuguHub.

Нам остаётся лишь перезапустить FuguHub и для этого испольуются следующие команды:

ssh -t -t root@FUGUHUB_HOST '/etc/init.d/bdd stop'
ssh root@FUGUHUB_HOST '/etc/init.d/bdd start < /dev/null > /tmp/mylogfile 2>&1 &'

Надо признаться, я уже не помню, почему команды выглядят так, какие ошибки/проблемы привели к такому результату - скрипт писался и отлаживался достаточно давно ещё на MyBookLive, но дать некоторые пояснения постараюсь.

Первая команда нужна для остановки демона FuguHub. Использование пары ключей -t -t, согласно документации SSH, нужно для безусловного создания псевдо-терминала. Вот эта выдержка:

-t Force pseudo-terminal allocation. This can be used to exe‐
cute arbitrary screen-based programs on a remote machine,
which can be very useful, e.g. when implementing menu ser‐
vices. Multiple -t options force tty allocation, even if
ssh has no local tty.

Такое поведение потребовалось, по всей видимости, из-за того, что скрипт запускается из cron, и у ssh нет и не может быть ассоциированного с ним терминала, а команда остановки демона пытается в терминал что-нибудь, да вывести, что приводит к возникновению ошибки.

Вторая команда, как, наверное, все догадались, нужна для запуска демона FuguHub. Тут, конечно, понакручено всевозможных редиректов, скорее всего, чтобы при вводе/выводе тоже не возникало ошибок, ну а амперсанд в конце передаваемой на хост команды говорит о том, что всё должно продолжать работать после закрытия ssh сессии. Вроде так... 🤔😏🤨

Ну вот, со скриптом, который выполняется при перевыпуске сертификата, вроде, разобрались. Теперь следует разобраться с автоматизацией перевыпуска.

Автоматизация перевыпуска сертификатов

Автоматизация: версия 1

После самой первой установки Certbot на Debian Jessie и первоначального выпуска сертификата, я обнаружил в /etc/cron.d/certbot такую вот команду:

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew

Естественно, на расшифровку её ушло какое-то время, но задачка была решена. Итак, установщик Certbot-а запрограммировал следующую последовательность действий:

  • каждые 12 часов (в 12:00 и в 24:00)
  • от имени пользователя root
  • в случае, если существует файл /usr/bin/certbot с правами на выполнение (условие выполняется, если Certbot был установлен обычным в те времена способом)
  • и не существует каталога /run/systemd/system (если система использует systemd, то для создания периодически повторяющихся действий должен использоваться не cron, а встроенные возможности systemd)
  • выполнить случайную задержку в пределах одного часа (чтобы все, кто установил Certbot, не ломанулись на сервера в одно и тоже время)
  • выполнить, наконец, обновление (молча 🤐).

Как видите, никаких параметров для команды renew не указано: ни тебе --pre-hook, ни --post-hook, а уж --renew-hook (или --deploy-hook) и подавно. Объясняется всё довольно просто: у клиента Certbot имеется возможность конфигурировать параметры обновления для сертификатов при помощи конфигурационных файлов в каталоге /etc/letsencrypt/renewal. Кроме того, как я отмечал ранее, клиент постоянно развивается, в нём происходят изменения. И замена --renew-hook на --deploy-hook - лишь одна из многих правок. Для облегчения жизни пользователей, клиент стал автоматически запоминать значения параметров --pre-hook, --post-hook и --deploy-hook в конфигурации. А чуть позже, hook-и стало возможным настраивать, размещая нужные командные файлы в подкаталогах deploy, pre и post каталога /etc/letsencrypt/renewal-hooks. Именно благодаря этим возможностям конфигурирования клиента Certbot (а также другому полезному функционалу), команда обновления и оказывается настолько простой:

certbot -q renew

Автоматизация: версия 2

В общем, всё каким-то образом устаканилось и работало без моего вмешательства, до тех пор пока в одном из протоколов Certbot не обнаружили уязвимость. Помню, как сейчас 😉: 27 января 2019 года получаю письмо, отправленное от имени noreply@letsencrypt.org. В этом письме мне сообщают (как, наверное, и многим другим), что используемый мною клиент (а это certbot) при запросах на выпуск сертификатов за последние 60 дней задействовал для проверки принадлежности доменов механизм с названием ACME TLS-SNI-01. Но вот незадача, использование этого механизма с 13 февраля 2019 года планируется временно прекратить, и полностью отказаться от него с 13.03.2019, так как в этом механизме была обнаружена уязвимость, позволявшая выпустить сертификат на чужой домен.

То есть, примерно за две недели до часа Ч я понимаю, что скоро все мои запросы на обновление будут отклоняться, так как мой клиент будет пробовать подтвердить принадлежность доменов с помощью этого самого механизма, который перестанет поддерживаться центром сертификации. Мир рушится - в очередной раз и, чтобы его спасти, надо просто последовать рекомендации и обновить клиента.

Я не буду тут описывать, через что мне пришлось пройти, чтобы всё-таки обновить клиента. Возможно, когда-нибудь я напишу об этом отдельный пост, но не для того, чтобы кто-то обновлялся по моим инструкциям - они уже давно потеряли актуальность, но для того, чтобы показать истинное лицо Linux с точки зрения простого пользователя. Скажу лишь, что, в конце концов, я обновил клиента, но после этого обновления у меня уже работал специальный скрипт с названием certbot-auto, так как сам Certbot для Debian Jessieобновляться перестал.

Естественно, после, по сути, смены клиента, надо было понять, что делать с автоматическим перевыпуском сертификатов - старая задача cron потеряла актуальность, так как клиента Certbot сменил клиент certbot-auto. К счастью, авторы certbot-auto не бросили своих пользователей и предложили им в качестве примера следующую задачу cron для автоматического перевыпуска сертификатов:

0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && /path/to/certbot-auto renew 

Единственное, что надо не забыть сделать, так это заменить /path/to/ на настоящий путь к certbot-auto.

Ну и, для порядка, разберем саму задачу. Она должна запускаться дважды в сутки: в полночь и полдень (0,12). Первым делом выполняется скрипт для python, который осуществляет задержку на случайное количество минут (time.sleep(random.random() * 3600)), после которой запускается собственно certbot-auto для перевыпуска сертификатов (ключ renew).

Как видим, изменения есть, но они не принципиальные: чуть изменилось программирование времени срабатывания, perl сменился python-ом, проверки исчезли, ну и клиент теперь другой. Сама команда осталась максимально простой, так как certbot-auto прекрасно работал с конфигурационными файлами Certbot.

И еше: задачу я создавал при помощи следующей команды:

crontab -e

Сама же задача создалась в подкаталоге crontabs каталога /var/spool/cron с именем файла, соотвтетствующим имени пользователя (в моем случае это был root).

Автоматизация: версия 3

Казалось бы, всё, отмучались, всё работает, как часы, в автоматическом режиме сертификаты перевыпускаются и делаются доступными для требующего их ПО. Но... 30-го сентября истёк срок действия сертификата, который выступал к качестве корневого для всей цепочки (ну, не совсем корневого, им был соподписан (cross-signed) корневой сертификат Let's Encrypt). И да, мне опять пришло письмо - 14-го мая.

Решил я посмотреть, как там с моими клиентами, автоматизациями и т.д. Вот если бы не посмотрел, не узнал бы, что certbot-auto вышел из моды и не поддерживается - если раньше обновления проверялись (и, при необходимости, осуществлялись) каждый раз при его запуске, то теперь всё, как говорится, финита ля комедия.

И решил я, что с этим надо что-то делать. Проводить upgrade операционки очень не хотелось, хотя, конечно, я понимал, что надо. Но из-за того, что много разных действий я совершал вручную, например, при обновлении клиента на certbot-auto менял библиотеки, потом ставил более свежую версию HAProxy, чем разрешено для Debian Jessie, устанавливал HAProxy-WI и так далее и тому подобное, я просто боялся, что могу получить кучу проблем. Поэтому, подумав некоторое время, я решил остановиться на варианте с использованием Docker. Надо заметить, что именно сейчас пойдёт более-менее актуальная информация, которую читатель может попробовать использовать себе во благо.🙄

Итак. Почему я выбрал именно этот вариант (с Docker). Во-первых, у меня уже есть некоторый опыт работы с ним. Во-вторых, я посчитал, что раз образ - официальный, то авторы позаботятся о том, чтобы всё в нём было прекрасно, особенно о том, чтобы в нём всегда использовалась самая свежая версия клиента. Причём, я не буду больше думать о совместимости чего-то с чем-то[7].

Почему я раньше не останавливался на этом варианте? Если честно, то я не помню. Вернее, раньше на официальном сайте Certbot такого предложения не было, и мне всё как-то попадались "пакетные" решения, при которых в контейнер упаковывается не только клиент Let's Encrypt, но и софт, который использует сертификаты, тот же HAProxy. А мне, почему-то[8], не хотелось переносить обратный прокси в docker контейнер, к тому же, docker, исходя из своих собственных представлений о добре и зле, вносит изменения в настройки межсетевого экрана, что иногда приводит, мягко говоря, к странным и не всегда желательным явлениям. Возможно, позже, когда я лучше смогу оценить и понять последствия, я и перенесу HAPRoxy в контейнер, но пока я к этому не готов.Но продолжим...

Решение о переносе процесса перевыпуска сертификатов в docker-контейнер естественным образом влечёт за собой изменения в механизмах взаимодействия клиента Certbot с другим софтом и инфраструктурой. В основном, речь идёт о hook-ах. Действительно, для того, чтобы перевыпущенный сертификат стал доступен извне контейнера достаточно к этому контейнеру примонтировать каталог хоста. А вот как заставить, например, pre-hook, выполняемый в контейнере, остановить работающий на хосте HAProxy?

Собственно говоря, простейшим ответом на поставленный выше вопрос будет остановка сервиса HAProxy до вызова процедуры перевыпуска сертификата. Точно также post-hook можно заменить на запуск сервиса после обновления сертификата. А вот с deploy-hook-ом всё несколько хитрее. Вызываемый в нём скрипт работает с файлами, расположенными не только на локальном, но и на удалённом хосте, да ещё и с использованием SSH. К тому же, особенностью deploy-hook-а является то, что вызывается он только при успешном перевыпуске сертификата, поэтому отказываться от него очень не хотелось.

В общем, после некоторых раздумий, я решил остановиться на такой схеме:

  • проводим предварительные работы:
    • правим конфигурацию, ранее используемую certbot-auto, с тем, чтобы не было pre-hook и post-hook
    • изменяем deploy-hook таким образом, чтобы в нём создавался файл с именем deployed.txt в каталоге /etc/letsencrypt/live/my.domain.name
  • правим процедуру обновления:
    • останавливаем сервис обратного прокси
    • монтируем текущий каталог, используемый клиентом certbot-auto (/etc/letsencrypt), в запускаемый docker-контейнер Certbot
    • после завершения выполнения docker-контейнера проверяем наличие файла /etc/letsencrypt/live/my.domain.name/deployed.txt и, если он там есть, выполняем манипуляции с перевыпущенным сертификатом
    • запускаем сервис обратного прокси

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

В конце концов, у меня получился вот такой скрипт:

systemctl stop haproxy
FILE=/etc/letsencrypt/live/my.domain.name/deployed.txt
if [ -f "$FILE" ]; then
    rm $FILE
fi
docker run --rm --name certbot \
            -v "/etc/letsencrypt:/etc/letsencrypt" \
            -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
            -p 80:80 \
            certbot/certbot renew
if [ -f "$FILE" ]; then
    /usr/local/bin/certupdate.sh
    echo "deployed"
else
    echo "not deployed"
fi
systemctl start haproxy

где my.domain.name - имя моего домена, а файл /usr/local/bin/certupdate.sh содержит необходимые действия с перевыпущенным сертификатом, которые я описывал выше.

На что в этом скрипте хотелось бы обратить внимание. В инструкции клиента Certbot для перевыпуска сертификата при помощи docker-контейнера указаны дополнительно ключи -i -t (вернее, -it). Но нам они не нужны, так как вызов будет осуществляться в задаче cron-а, а не в интерактивном режиме. Более того, если мы их оставим, то получим ошибку:

the input device is not a TTY

Приведённый выше скрипт я сохранил в файле /usr/local/bin/le-renew.sh. Конечно, его можно улучшать. Так, например, перед тем, как перейти к процессу перевыпуска сертификата, можно проверять факт того, что сервис HAProxy был действительно остановлен (применив, systemctl is-active или другой механизм).

Сам deploy-hook я описал, создав в подкаталоге /etc/letsencrypt/renewal-hooks/deploy файл certs-deployed.sh с таким содержанием:

touch /etc/letsencrypt/live/my.domain.name/deployed.txt

Ну и, в завершение, выполнив команду crontab -e, я отредактировал задачу cron-а:

0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/le-renew.sh >> /var/log/letsencrypt/letsencrypt.log 2>&1

Практически такую же задачу я разбирал выше, за исключением редиректа вывода:

>> /var/log/letsencrypt/letsencrypt.log 2>&1

Тут тоже всё не сложно: мы перенаправляем весь вывод, осуществляемый в стандартное устройство вывода (stdout) в нужный нам файл (/var/log/letsencrypt/letsencrypt.log), а, заодно, в этот же файл попадёт и весь вывод, производимый в стандартное устройство вывода ошибок ( stderr) - этот вывод мы перенаправляем в stdout (2>&1), который уже перенаправлен в файл.

Вот, пожалуй, и всё, что мне есть рассказать на текущий момент про перевыпуск сертификата Let's Encrypt и про автоматизацию этого процесса.


  1. Ведь общеизвестно, что правильно заданный вопрос - половина ответа ↩︎

  2. Я даю ссылки на актуальные в момент написания материалы. Раньше они были другими, и, возможно, изменятся в будущем. ↩︎

  3. Можно, конечно, поступить и иначе - сконфигурировать HAProxy так, чтобы он анализировал факт того, что производится обмен с сервисом Let's Encrypt и перенаправлял в этом случае запросы клиенту (Certbot). Но, после обновления сертификата, HAProxy всё равно придётся перегрузить. ↩︎

  4. deploy-hook отличается (в лучшую, на мой взгляд, сторону) от renew-hook тем, что срабатывает и при первичном выпуске сертификата ↩︎

  5. На самом деле, использование одного файла - не является обязательным требованием, все зависит от того, как настроен HAProxy ↩︎

  6. Если доменных имён много, то, по умолчанию, будет использовано имя домена, указанное первым. ↩︎

  7. Знаю-знаю, docker не является панацеей, и помнить о совместимости всё равно надо, да и сталкивался я уже со случаями, когда совместимость не обеспечивалась, правда, в других продуктах, но об этом - в другой раз. ↩︎

  8. Мне, чисто интуитивно, кажется, что перенос HAProxy в контейнер может плохо сказаться на быстродействии, но, возможно, тут я не прав ↩︎