Let's Encrypt и nginx: настройка в Debian и Ubuntu
Установка Certbot
$ sudo apt-get install certbot
Certbot и webroot
Мы будем получать сертификаты по методу webroot
без перенастройки или остановки веб-сервера, под которым подразумевается nginx
.
Нам нужен какой-то каталог, в который certbot будет писать свои файлы, и какой должен быть доступен из сети удостоверяющему серверу согласно протокола
ACME.
Запишем основные настройки в файл конфигурации /etc/letsencrypt/cli.ini
:
authenticator = webroot
webroot-path = /var/www/html
post-hook = service nginx reload
text = True
Что будет делать Certbot
Ожидается что certbot
будет создавать необходимые для проверки прав на домен файлы в подкаталогах ниже по иерархии к указанному.
Вроде таких: /var/www/html/.well-known/acme-challenge/example.html
Эти файлы должны будут быть доступны из сети на целевом домене по крайней мере по HTTP
:
http://www.example.com/.well-known/acme-challenge/example.html
Для следующих проверок создадим какой-то такой файл:
$ mkdir -p /var/www/html/.well-known/acme-challenge
$ echo Success > /var/www/html/.well-known/acme-challenge/example.html
Регистрация в Let's Encrypt
Регистрацию нужно сделать только один раз:
$ certbot register --email me@example.com
Подготовим nginx к получению сертификатов
Создадим файл /etc/nginx/acme
:
location /.well-known {
root /var/www/html;
}
Для каждого домена и поддомена, для которых нужно получить сертификаты, в блоке server
перед всеми блоками location
укажем:
include acme;
Перезагрузим nginx
и проверим что наш тестовый файл виден:
$ service nginx reload
$ curl -L http://www.example.com/.well-known/acme-challenge/example.html
Success
После проверки лучше удалить тестовый файл — certbot
любит удалять за собой всё лишнее,
а такой файл будет мешать и вызывать сообщение об ошибке (Unable to clean up challenge directory
):
$ rm /var/www/html/.well-known/acme-challenge/example.html
Получаем сертификаты
У Let's Encrypt
есть лимиты на количество обращений за сертификатами,
потому сначала попробуем получить необходимый сертификат в режиме для тестов:
$ certbot certonly --dry-run -d example.com -d www.example.com
The dry run was successful
Теперь можно смело получать сертификат уже в самом деле. Не забудьте явно указать все необходимые поддомены, такие как www
.
$ certbot certonly -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
expire on 2017-04-01. To obtain a new or tweaked version of this
certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
Если нужно добавить поддомен или домен в сертификат
Если вы вдруг забыли указать поддомен www, или вам нужно добавить другой домен или поддомен в сертификат (которых может быть до 100 в одном сертификате), то это легко сделать после получения сертификата. Просто запустите команду еще раз, добавив требуемое имя:
$ certbot certonly -d example.com -d www.example.com -d shop.example.com
Вам будет безальтернативно предложено добавить этот домен в сертификат. Если хочется избежать вопросов, то можно сразу указать одобряющий такое поведение ключ:
$ certbot certonly --expand -d example.com -d www.example.com -d shop.example.com
Проверим полученный сертификат
Убедимся что полученный сертификат — именно тот, что нам нужен:
$ openssl x509 -text -in /etc/letsencrypt/live/example.com/cert.pem
Certificate:
Signature Algorithm: ...
Validity
Not Before: Jan 3 06:00:00 2017 GMT
Not After : Apr 3 06:00:00 2017 GMT
X509v3 extensions:
...
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
Или, если подробности вам не нужны:
$ cat /etc/letsencrypt/live/*/cert.pem | openssl x509 -text | grep -o 'DNS:[^,]*' | cut -f2 -d:
Команда должна вывести список доменов в сертификате.
Установка и использование сертификатов
Certbot
не перезаписывает сертификаты, а заменяет их ссылками на самые актуальные варианты сертификатов в определенном каталоге, одноименном с первым доменом сертификата (т.е. CN). Давайте посмотрим что за файлы у нас есть:
$ find /etc/letsencrypt/live/ -type l
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/chain.pem
/etc/letsencrypt/live/example.com/privkey.pem
/etc/letsencrypt/live/example.com/cert.pem
С этим знанием мы можем задать настройки SSL
для nginx
:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
Полный рабочий пример конфига:
server {
server_name www.example.com;
listen www.example.com:443 ssl; # default_server;
# выше можно добавить default_server для клиентов без SNI
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 8.8.8.8;
# исключим возврат на http-версию сайта
add_header Strict-Transport-Security "max-age=31536000";
# явно "сломаем" все картинки с http://
add_header Content-Security-Policy "img-src https: data:; upgrade-insecure-requests";
# далее всё что вы обычно указываете
#location / {
# proxy_pass ...;
#}
}
Конфиг для переадресации с голого домена без www
:
server {
server_name example.com;
listen example.com:443 ssl;
access_log off;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 8.8.8.8;
add_header Strict-Transport-Security "max-age=31536000";
expires max;
return 301 https://www.example.com$request_uri;
}
Подразумевается что вы используете какой-то локальный сервер для кеширования DNS
запросов.
Если это не так, то 127.0.0.1
в директиве resolver
нужно заменить на IP
используемого DNS
сервера.
Настройки шифров и прочее подобное (ssl_dhparam
, ssl_session_cache
) лучше держать вне конфигов отдельных серверов.
Продление сертификатов
Сертификаты выдаются на три месяца.
Если у вас Debian
и systemd
, то посмотрите эти инструкции.
Если у вас не Debian
или нет файла, то добавим в crontab
от root
одну лишь строчку (sudo crontab -e
):
42 */12 * * * certbot renew --quiet --allow-subset-of-names
Согласно рекомендаций Let's Encrypt
следует пытаться обновить сертификаты два раза в день.
Делать это нужно в случайным образом выбранную минуту того часа,
а значит вам нужно заменить 42
в этой строке на другое число в диапазоне между 0 и 59.
Либо вы можете поступить так как это делается в /etc/cron.d/certbot
.