SSL: автоматическое обновление
Сервер Linux — nginx, Apache, Caddy, HAProxy, Docker
Скрипт для nginx, Apache, Caddy, HAProxy и Docker раз в сутки забирает свежий сертификат, сверяет его с вашим ключом и перезапускает сервер без простоя.
Обновляется сам
Подходит, если у вас есть доступ к серверу по SSH и права root (VPS, выделенный сервер, свой компьютер в стойке). Нужны curl и openssl — они есть почти в каждом Linux.
Что понадобится
- Ссылка на сертификат из кабинета:
https://api.zrazu.com/ssl-pull/zsp_ВАШ_ТОКЕН. - Закрытый ключ, с которым заказывали сертификат (файл
key.pemили похожий). Если CSR создавал кабинет ZRAZU — это файл, который вы тогда сохранили. - 10 минут.
Шаг 1. Положите ключ на сервер
sudo mkdir -p /etc/ssl/zrazu/example.com
sudo chmod 700 /etc/ssl/zrazu/example.com
sudo nano /etc/ssl/zrazu/example.com/key.pem
sudo chmod 600 /etc/ssl/zrazu/example.com/key.pemВ nano вставьте весь текст ключа вместе со строками -----BEGIN … PRIVATE KEY----- и -----END … PRIVATE KEY-----, сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X). Ключ без пароля: если ваш ключ запаролен, снимите пароль командой openssl pkey -in старый.key -out /etc/ssl/zrazu/example.com/key.pem.
Шаг 2. Скрипт обновления
Создайте файл sudo nano /usr/local/bin/zrazu-ssl-example.com.sh, вставьте текст ниже и измените только строку RELOAD под свой веб-сервер:
- nginx —
nginx -t && systemctl reload nginx(так стоит); - Apache (Debian, Ubuntu) —
apachectl configtest && systemctl reload apache2; Apache (CentOS, Rocky, Alma) —apachectl configtest && systemctl reload httpd; - Caddy —
systemctl reload caddy; - HAProxy —
systemctl reload haproxyиCOMBINED=1(HAProxy читает сертификат и ключ одним файломcombined.pem); - nginx в Docker —
docker exec ИМЯ_КОНТЕЙНЕРА nginx -s reload(каталог/etc/ssl/zrazuподключите в контейнер как том).
#!/bin/sh
# ZRAZU: обновление SSL-сертификата по личной ссылке. Запускается cron раз в сутки.
set -eu
# cron даёт короткий PATH без /usr/sbin, а nginx и apachectl лежат именно там.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PULL="https://api.zrazu.com/ssl-pull/zsp_ВАШ_ТОКЕН"
DIR="/etc/ssl/zrazu/example.com"
KEY="$DIR/key.pem"
RELOAD="nginx -t && systemctl reload nginx"
COMBINED=0
umask 077
tmp=$(mktemp "$DIR/.new.XXXXXX")
trap 'rm -f "$tmp"' EXIT
curl -fsS --retry 3 --max-time 60 -o "$tmp" "$PULL/fullchain.pem"
grep -q "BEGIN CERTIFICATE" "$tmp" || { echo "ZRAZU: по ссылке не сертификат"; exit 1; }
if [ -f "$DIR/.applied" ] && cmp -s "$tmp" "$DIR/.applied"; then
echo "ZRAZU: сертификат не изменился"
exit 0
fi
cert_pub=$(openssl x509 -in "$tmp" -noout -pubkey | openssl sha256)
key_pub=$(openssl pkey -in "$KEY" -pubout | openssl sha256)
if [ "$cert_pub" != "$key_pub" ]; then
echo "ZRAZU: сертификат выпущен на другой ключ — ничего не меняю, положите новый ключ в $KEY"
exit 1
fi
openssl x509 -in "$tmp" -noout -checkend 0 >/dev/null || { echo "ZRAZU: сертификат уже не действует"; exit 1; }
chmod 644 "$tmp"
mv -f "$tmp" "$DIR/fullchain.pem"
if [ "$COMBINED" = 1 ]; then
cat "$DIR/fullchain.pem" "$KEY" > "$DIR/combined.pem.new"
mv -f "$DIR/combined.pem.new" "$DIR/combined.pem"
fi
sh -c "$RELOAD"
cp "$DIR/fullchain.pem" "$DIR/.applied"
echo "ZRAZU: новый сертификат установлен, действует до $(openssl x509 -in "$DIR/fullchain.pem" -noout -enddate | cut -d= -f2)"Скрипт ничего не меняет, если веб-сервер уже работает с этим сертификатом, если файл по ссылке не сертификат, если сертификат не подходит к вашему ключу или уже не действует. Конфигурацию веб-сервера он проверяет перед перезапуском, так что сломанный конфиг сайт не уронит; а если перезапуск не удался, на следующий день скрипт попробует ещё раз.
Сделайте файл исполняемым и запустите один раз вручную:
sudo chmod 700 /usr/local/bin/zrazu-ssl-example.com.sh
sudo /usr/local/bin/zrazu-ssl-example.com.shДолжно появиться «новый сертификат установлен» и файл /etc/ssl/zrazu/example.com/fullchain.pem.
Шаг 3. Укажите файлы в веб-сервере (один раз)
nginx — в блоке server сайта:
ssl_certificate /etc/ssl/zrazu/example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/zrazu/example.com/key.pem;Apache 2.4.8 и новее — в <VirtualHost *:443>:
SSLCertificateFile /etc/ssl/zrazu/example.com/fullchain.pem
SSLCertificateKeyFile /etc/ssl/zrazu/example.com/key.pemCaddy — в блоке сайта tls /etc/ssl/zrazu/example.com/fullchain.pem /etc/ssl/zrazu/example.com/key.pem. HAProxy — в bind :443 ssl crt /etc/ssl/zrazu/example.com/combined.pem.
Проверьте конфиг (nginx -t или apachectl configtest) и перезапустите веб-сервер.
Шаг 4. Расписание
echo "17 4 * * * root /usr/local/bin/zrazu-ssl-example.com.sh >> /var/log/zrazu-ssl.log 2>&1" | sudo tee /etc/cron.d/zrazu-ssl-example.comСкрипт будет запускаться каждый день в 04:17 по времени сервера. Минуту можно взять любую — лучше не ровно 00.
Проверка
sudo tail /var/log/zrazu-ssl.log— завтра там появится «сертификат не изменился»: расписание работает.- Сайт отдаёт наш сертификат:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -enddateили страница https://zrazu.com/tools/ssl/example.com/. - В кабинете, в карточке сертификата, видно, что сервер забрал действующий сертификат.
Если не получилось
curl: (22) … 404— ссылка отключена или заменена. В карточке сертификата создайте новую и замените строкуPULLв скрипте.curl: (22) … 429— слишком много запросов (больше 60 в час). Раз в сутки — с большим запасом.- «сертификат выпущен на другой ключ» — сертификат перевыпускали с новым ключом. Положите новый ключ в
key.pemи запустите скрипт ещё раз. nginx: [emerg]после перезапуска — ошибка в конфигурации сайта, не в сертификате; старый сертификат остаётся в работе, пока ошибку не исправите.