
Содержание статьи
автор Рассел Хэммет-младший (Критнер)

Раньше я использовал letsencrypt для бесплатных сертификатов. Я не использовал его успешно после перехода на docker/kestrel/nginx. Сегодня все изменилось, и я очень долго выяснял, что я делаю, чтобы это заработало.
Весь этот Unix, docker, nginx, вещи достаточно новые (для меня), поэтому, возможно, это просто что-то простое, чего мне не хватало все время. Тем не менее, я надеюсь, что это поможет кому-нибудь другому или мне через несколько месяцев, если я решу это сделать снова.
Оригинальная установка
У меня есть основной веб-сайт .net, который размещается через kestrel, работает на докере с обратным прокси через nginx. До этого времени обратный прокси-сервер с nginx работал только через http/port 80. Я не очень знаю об обратных прокси. По его звуку он может принимать запросы и пересылать в определенное место от имени запросчика. В моем случае контейнер nginx получает http-запросы и nginx пересылает этот запрос на мой основной сайт .net, размещенный в Kestrel. Это так? Надеюсь!
Как упоминалось ранее, nginx работал только с http-трафиком. У меня возникло много проблем с тем, чтобы он работал с https, оригинальная конфигурация такова:
docker-compose:
version: '3.6'services: kritner-website-web: image: ${DOCKER_REGISTRY}/kritnerwebsite expose: - "5000" networks: - frontend restart: always container_name: kritnerwebsite_web kritner-website-nginx: image: nginx:latest ports: - "80:80" volumes: - ../src/nginx/nginx.conf:/etc/nginx/nginx.conf depends_on: - kritner-website-web networks: - frontend restart: always container_name: kritnerwebsite_nginx
networks: frontend:
В файле docker-compose я использую два отдельных контейнера – веб-сайт, открывающий порт 5000 (в сети docker, а не публично), и nginx, работающий на порту 80.
nginx.conf
worker_processes 4; events { worker_connections 1024; } http { sendfile on; upstream app_servers { server kritner-website-web:5000; } server { listen 80; location / { proxy_pass proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } }}
В конфигурационном файле мы настраиваем верхний сервер с тем же именем, что мы называем наш контейнерный сервис из файла docker-compose kritner-website-web:5000
.
Заметьте, все вышеперечисленное можно найти в этой точке фиксации в репозитории моего веб-сайта.
Введите HTTPS
Letsencrypt – это центр сертификации, который предлагает бесплатные сертификаты для защиты вашего веб-сайта. Почему HTTPS через TLS важен? Что ж, этого много и как это работает. Основная идея состоит в том, что пользовательский трафик шифруется на обоих концах перед отправкой на другой конец. Это значит, что если вы находитесь в общедоступном Wi-Fi и на https, кто-то, так сказать, «нюхает проволоку», увидит, что происходит трафик, но не содержимое указанного трафика. Поскольку обе стороны шифруют/дешифруют указанный трафик с помощью одного ключа шифрования.
Если бы вы были на http-сайте, этот трафик отправлялся вперед и назад в виде простого текста. Это означает, что ваши данные под угрозой подслушивания! Возможно, когда-нибудь я напишу немного больше о шифровании. (*Примечание для себя*) Тем более что это то, что я делаю как ежедневную работу!
letsencrypt – это сервис, которым я пользовался раньше. Существуют разные реализации, чтобы попытаться сделать его максимально простым в использовании. Исследовав этот пост, я наткнулся на это.
Хотя я не нашел эту страницу до сих пор, она была бы полезна до начала моего приключения. Я хотел использовать letsencrypt вместе с моим веб-сайтом-контейнером докеров и nginx с минимальным обслуживанием. Сертификаты letsencrypt действительны только в течение 90 дней.
В своем исследовании я наткнулся на образ докера linuxserver/letsencrypt, который обещает использовать nginx, генерацию сертификатов letsencrypt и автоматическое обновление. Звучит потрясающе! Хотя документация изображения кажется в основном адекватной для тех, кто хорошо разбирается во всем этом процессе. Я нашел, что его не хватает. Весь процесс настройки занял у меня некоторое время, чтобы понять. Поэтому этот пост, чтобы, надеюсь, помочь следующему человеку или снова мне в будущем!

Борьба
При запуске и работе этого образа linuxserver/letsencrypt мне больше всего пришлось бороться:
- Как «работают» тома докеров и их связь с этим контейнером
- Как настроить объемы, чтобы использовать мою конфигурацию (связано с вышеуказанным пунктом) — сначала у меня было много проблем с выяснением, почему мои настройки, измененные в контейнере, были изменены назад после перезагрузки указанного контейнера (поскольку это то, что они должно делать)
- Как настроить правильную конфигурацию nginx – куда ее разместить и что в нее вставить.
Томы Docker
Томы Docker (doc):
Томы являются лучшим механизмом для хранения генерируемых и используемых контейнеров Docker данных. Хотя подключение привязки зависит от структуры каталогов хост-машины, тома полностью управляются Docker. Томы имеют ряд преимуществ перед креплениями для привязки.
Letsencrypt имеет много конфигураций вместе с ним. Мне нужно некоторое время, чтобы осознать, но мне нужен том, который будет отображаться из каталога на хост докера в определенный каталог на изображении letsencrypt. В конце концов я сделал это в файле сборки так:
volumes: - ${DOCKER_KRITNER_NGINX}:/config - ./nginx.conf:/config/nginx/site-confs/default
Первый элемент в массиве (${DOCKER_KRITNER_NGINX}:/config
) принимает новую переменную среды, которая отображает каталог хоста (определен в переменной) на /config
внутри самого контейнера докеров. Это означает, что хост докера (в пути env var) будет содержать ту же конфигурацию, что и файл докер-контейнер во вторичной части отображения объема (/config
)
Второй пункт (./nginx.conf:/config/nginx/site-confs/default
) сопоставляет мои локальные репозитории файл nginx.conf (файл, где я настроил обратный прокси-сервер), чтобы заменить /config/nginx/site-confs/default
файл на хосте и контейнере докера.
Полный список файлов, которые мне нужно было изменить для моей конкретной ситуации, был:
/config/dns-conf/dnsimple.ini
/config/nginx/site-confs/default
The dnsimple.ini
конфигурации: добавить мой ключ API и …/default
содержащая конфигурацию nginx.
Финал default
конфигурация, с которой я кончился:
upstream app_servers { server kritnerwebsite:5000;}
## Version 2018/09/12 - Changelog: https://github.com/linuxserver/docker-letsencrypt/commits/master/root/defaults/default
# listening on port 80 disabled by default, remove the "#" signs to enable# redirect all traffic to httpsserver { listen 80; server_name kritnerwebsite; return 301 https://$host$request_uri;}
# main server blockserver { listen 443 ssl;
# enable subfolder method reverse proxy confs include /config/nginx/proxy-confs/*.subfolder.conf;
# all ssl related config moved to ssl.conf include /config/nginx/ssl.conf; # enable for ldap auth #include /config/nginx/ldap.conf;
client_max_body_size 0;
location / { proxy_pass proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; }
}
# enable subdomain method reverse proxy confsinclude /config/nginx/proxy-confs/*.subdomain.conf;# enable proxy cache for authproxy_cache_path cache/ keys_zone=auth_cache:10m;
Есть несколько изменений по сравнению со стандартными, которые я попытаюсь выделить дальше.
upstream app_servers { server kritnerwebsite:5000;}
Выше очень круто, поскольку у докера есть свой внутренний DNS (я считаю?). Вы можете настроить восходящий сервер под названием контейнера в моем случае «kritnerwebsite». (Примечание: я изменил его по сравнению с предыдущим сообщением, которое было «kritner-website-web».)
# listening on port 80 disabled by default, remove the "#" signs to enable# redirect all traffic to httpsserver { listen 80; server_name kritnerwebsite; return 301 https://$host$request_uri;}
Раскомментировал этот раздел по умолчанию, применил имя_сервера «kritnerwebsite»
# main server blockserver { listen 443 ssl;
# enable subfolder method reverse proxy confs include /config/nginx/proxy-confs/*.subfolder.conf;
# all ssl related config moved to ssl.conf include /config/nginx/ssl.conf; # enable for ldap auth #include /config/nginx/ldap.conf;
client_max_body_size 0;
location / { proxy_pass proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; }
}
В вышеприведенном, это в основном от «по умолчанию», за исключением «расположения» и всего в этом объекте. Здесь мы настраиваем обратный прокси для пересылки запросов на «/» (что угодно) в наш (Веб-сайт kritner в соответствии с нашим upstream).
docker-compose.yml
Наш файл Docker compose не изменил *целиком* много по сравнению с начальным. Было несколько заметных изменений, которые я также опишу:
version: '3.6'services: nginx: image: linuxserver/letsencrypt ports: - "80:80" - "443:443" volumes: - ${DOCKER_KRITNER_NGINX}:/config - ./nginx.conf:/config/nginx/site-confs/default depends_on: - kritnerwebsite networks: - frontend container_name: nginx environment: - PUID=1001 # get on dockerhost through command "id <user>"" - PGID=1001 - EMAIL=kritner@gmail.com - URL=kritner.com - SUBDOMAINS=www - TZ=America/NewYork - VALIDATION=dns # using dns validation - DNSPLUGIN=dnsimple # via dnsimple, note there is additional configuration require separate from this file # - STAGING=true # this should be uncommented when testing for initial success, to avoid some rate limiting
kritnerwebsite: image: ${DOCKER_REGISTRY}/kritnerwebsite networks: - frontend expose: - "5000" restart: always container_name: kritnerwebsite networks: frontend:
для новых деталей:
nginx: image: linuxserver/letsencrypt
Использование другого изображения – linuxserver/letsencrypt вместо nginx. Это изображение содержит nginx, certbot и cronjob для запуска certbot во время запуска программы.
ports: - "80:80" - "443:443"
Теперь мы используем как http, так и https порты (хотя заметьте, что мы перенаправляем вызовы http на https через конфигурацию nginx).
volumes: - ${DOCKER_KRITNER_NGINX}:/config - ./nginx.conf:/config/nginx/site-confs/default
Уже обсуждалось ранее в сообщении, мы используем эти тома, чтобы правильно настроить конфигурацию nginx с помощью нашего ключа dnsimple api, а также нашего обратного прокси-сервера на веб-сайт kritner.
environment: - PUID=1001 # get on dockerhost through command "id <user>" - PGID=1001 - EMAIL=kritner@gmail.com - URL=kritner.com - SUBDOMAINS=www - TZ=America/NewYork - VALIDATION=dns # using dns validation - DNSPLUGIN=dnsimple # via dnsimple, note there is additional configuration require separate from this file # - STAGING=true # this should be uncommented when testing for initial success, to avoid some rate limiting
Сменные среды, необходимые в соответствии с документацией letsencrypt, можно найти здесь.
- PUID/PGID – попасть на dockerhost с помощью команды «id
» - Электронная почта – ну, ваша электронная почта (очевидно, используется для писем об истечении срока действия сертификата)
- URL — URL-адрес основного домена
- субдомены — любые субдомены к URL-адресу, подлежащему сертификации
- TZ — часовой пояс
- Проверка – тип проверки – я использую DNSimple, поэтому мне нужен был DNS в этом поле. Другие варианты: html, tls-sni
- dnsplugin — dnsimple — другие варианты
cloudflare
,cloudxns
,digitalocean
,dnsmadeeasy
,google
,luadns
,nsone
,rfc2136
иroute53
согласно документации letsencrypt - Staging=true — я использовал это для тестирования всех своих попыток, прежде чем запустить его. У letsencrypt есть ограничение скорости, когда он не работает в промежуточном режиме (или, по крайней мере, в стадийном режиме с ним труднее столкнуться).
Все вышеперечисленные изменения, эксперименты, неудачи, а затем, наконец, успех можно найти в этом запросе на подъемник.
Конечный результат?

и из —

Не A+, но действительно неплохо для использования одного предварительно созданного образа докера для моих нужд HTTPs!
Связанные: