Как настроить свой веб-сайт на этот милый, милый HTTPS с помощью Docker, Nginx и letsencrypt

1656534852 kak nastroit svoj veb sajt na etot milyj milyj https s

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

akW9m3QdmZN0DGucvlAGgzGXW1oot7zLw0IY

Раньше я использовал 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 и автоматическое обновление. Звучит потрясающе! Хотя документация изображения кажется в основном адекватной для тех, кто хорошо разбирается во всем этом процессе. Я нашел, что его не хватает. Весь процесс настройки занял у меня некоторое время, чтобы понять. Поэтому этот пост, чтобы, надеюсь, помочь следующему человеку или снова мне в будущем!

uDVdXYEOt66dbf284uuJT0gybayII2EW3lTF
Логотип Linux Server.IO

Борьба

При запуске и работе этого образа 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 есть ограничение скорости, когда он не работает в промежуточном режиме (или, по крайней мере, в стадийном режиме с ним труднее столкнуться).

Все вышеперечисленные изменения, эксперименты, неудачи, а затем, наконец, успех можно найти в этом запросе на подъемник.

Конечный результат?

8p9oqF7gDeWHXY9oqutUsEB5rmbmH8zh9D8s
Аааа, да

и из —

YcQFIv8RixHyyhSlurfdIZVZmbttLUOQi5V0

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

Связанные:

Добавить комментарий

Ваш адрес email не будет опубликован.