كيفية إعداد موقع الويب الخاص بك لبروتوكول HTTPS الرائع والرائع باستخدام Docker و Nginx و Letsencrypt

لقد استخدمت Letsencrypt في الماضي للحصول على شهادات مجانية. لم أستخدمه بنجاح منذ الانتقال إلى docker / kestrel / nginx. لقد تغير كل هذا اليوم ، وكان لدي وقت طويل في معرفة ما كنت أفعله لإنجاحه.

هذا Unix ، docker ، nginx ، أشياء جديدة جدًا (بالنسبة لي) ، لذلك ربما يكون مجرد شيء بسيط كنت أفتقده طوال الوقت. ومع ذلك ، آمل أن يساعد هذا شخصًا آخر ، أو سيساعدني بعد عدة أشهر إذا قررت القيام بذلك مرة أخرى.

الإعداد الأصلي

لديّ موقع ويب أساسي .net ، يتم استضافته عبر kestrel ، يعمل على عامل ميناء ، مع وكيل عكسي عبر nginx. حتى الآن ، كان هذا الوكيل العكسي من nginx يعمل فقط عبر http / port 80. لا أعرف الكثير عن البروكسيات العكسية. من صوتها ، يمكن أن تأخذ في الطلبات ، وتحويلها إلى موقع محدد نيابة عن الطالب. في حالتي ، تستقبل حاوية nginx طلبات http ، ويقوم nginx بإعادة توجيه هذا الطلب إلى موقع kestrel. هل هذا صحيح؟ نأمل!

كما ذكرنا سابقًا ، كان nginx يعمل فقط مع حركة مرور http. كنت أواجه الكثير من المشاكل في العمل مع https ، التكوين الأصلي كالتالي:

عامل ميناء يؤلف:

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 //app_servers; 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-website-web:5000.

ملاحظة ، يمكن العثور على كل ما سبق في نقطة الالتزام هذه في مستودع موقع الويب الخاص بي.

أدخل HTTPS

Letsencrypt هي سلطة تصديق تقدم شهادات مجانية للمساعدة في تأمين موقع الويب الخاص بك. لماذا يعد HTTPS عبر TLS مهمًا؟ حسنًا ، هناك الكثير من ذلك ، وكيف يعمل. الفكرة الأساسية هي أن حركة مرور المستخدم مشفرة على أي من الطرفين قبل إرسالها إلى الطرف الآخر. هذا يعني أنك إذا كنت تستخدم شبكة wifi عامة وعلى https ، فسيرى شخص ما "يستنشق الأسلاك" إذا جاز التعبير ، أن حركة المرور تحدث ، ولكن ليس محتوى حركة المرور المذكورة. نظرًا لأن كلا الطرفين يقومان بتشفير / فك تشفير حركة المرور المذكورة باستخدام مفتاح التشفير نفسه.

إذا كنت في موقع http ، فسيتم إرسال هذه الحركة ذهابًا وإيابًا بنص عادي. مما يعني أن بياناتك معرضة لخطر التنصت عليها! ربما سأكتب المزيد عن التشفير في مرحلة ما. (* ملاحظة لنفسي *) خاصة وأن هذا شيء أقوم به كعملي اليومي!

Letsencrypt هي خدمة استخدمتها من قبل. هناك العديد من التطبيقات لمحاولة جعله سهل الاستخدام قدر الإمكان. من خلال البحث في هذا المنشور ، حدث ذلك.

على الرغم من أنني لم أجد هذه الصفحة حتى الآن ، إلا أنها كانت مفيدة قبل أن أبدأ مغامرتي. أردت استخدام Letsencrypt مع موقع حاوية عامل الإرساء و nginx مع أقل قدر ممكن من الصيانة. شهادات Letsencrypt صالحة لمدة 90 يومًا فقط.

في بحثي ، صادفتُ صورة عامل تشغيل linuxserver / letencrypt التي تعد باستخدام nginx ، وتوليد الشهادة ، وتجديد تلقائي. يبدو رائع! بينما يبدو توثيق الصورة مناسبًا في الغالب - لشخص ضليع في كل هذه العملية. لقد وجدت أنها تفتقر. استغرقت عملية الإعداد بأكملها بعض الوقت لمعرفة ذلك. ومن هنا فإن هذا المنشور ، نأمل أن يساعد الشخص التالي ، أو مرة أخرى لي في المستقبل!

النضالات

كانت أكثر الأشياء التي عانيت معها عند الحصول على صورة linuxserver / letencrypt هذه والعمل:

  • كيف حجم عامل الميناء "العمل" وعلاقتها مع هذه الحاوية
  • كيفية تعيين وحدات التخزين لاستخدام التهيئة الخاصة بي (المتعلقة بالنقطة أعلاه) - كنت أواجه الكثير من المشاكل في البداية في معرفة سبب تغيير إعداداتي على الحاوية مرة أخرى عند إعادة تحميل الحاوية المذكورة (لأن هذا هو من المفترض أن يفعل)
  • كيفية إعداد تكوين nginx الصحيح - مكان وضعه وما الذي يجب وضعه فيه.

مجلدات عامل ميناء

مجلدات عامل ميناء (doc):

وحدات التخزين هي الآلية المفضلة لاستمرار البيانات التي يتم إنشاؤها بواسطة حاويات Docker واستخدامها. بينما تعتمد حوامل الربط على بنية الدليل للجهاز المضيف ، تتم إدارة وحدات التخزين بالكامل بواسطة Docker. الأحجام لها مزايا عديدة على حوامل الربط

يحتوي Letsencrypt على الكثير من التكوين الذي يجب أن يتماشى معه. لقد استغرق الأمر بعض الوقت حتى أدرك ذلك ، لكنني كنت بحاجة إلى وحدة تخزين تم تعيينها من دليل على مضيف عامل الإرساء إلى دليل محدد على صورة letencrypt. لقد أنجزت هذا في النهاية في ملف الإنشاء كالتالي:

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

كان dnsimple.iniالتكوين هو إضافة مفتاح api الخاص بي ، …/defaultويضم تكوين nginx.

defaultالتكوين النهائي الذي انتهيت به هو:

upstream app_servers { server kritnerwebsite:5000;}
## Version 2018/09/12 - Changelog: //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 //$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 //app_servers; 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 //$host$request_uri;}

Uncommented out this section from the default, applied my server_name of “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 //app_servers; 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; }
}

In the above, it’s mostly from the “default” save for “location” and everything within that object. Here, we’re setting up the reverse proxy to forward requests to “/” (anything) to our //app_servers (kritnerwebsite as per our upstream).

docker-compose.yml

Our docker compose file didn’t change a *whole* lot from the initial. There were a few notable changes, which I’ll also get into describing:

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 "" - PGID=1001 - [email protected] - 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:

for the new parts:

nginx: image: linuxserver/letsencrypt

Using a different image — linuxserver/letsencrypt instead of nginx. This image has nginx included, but also certbot, along with a cronjob to run certbot at application start.

ports: - "80:80" - "443:443"

Now we’re using both http and https ports (though note, we’re redirecting http calls to https via the nginx config).

volumes: - ${DOCKER_KRITNER_NGINX}:/config - ./nginx.conf:/config/nginx/site-confs/default

Already discussed earlier in the post, we’re using these volumes to properly set up the nginx configuration, with our dnsimple api key, as well as our reverse proxying to the kritnerwebsite.

environment: - PUID=1001 # get on dockerhost through command "id " - PGID=1001 - [email protected] - 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

Environment variables needed as per the letsencrypt documentation can be found here.

  • PUID/PGID — get on dockerhost through command “id ”
  • Email — well, your email (used for cert expiration emails apparently)
  • URL — the main domain URL
  • subdomains — any subdomains to the URL to be certified
  • TZ — timezone
  • Validation — the type of validation to do — I’m using DNSimple, so i needed DNS in this field. Other options are html, tls-sni
  • dnsplugin — dnsimple — other options are cloudflare, cloudxns, digitalocean, dnsmadeeasy, google, luadns, nsone, rfc2136 and route53 as per the letsencrypt documentation
  • التدريج = صحيح - لقد استخدمت هذا لاختبار جميع محاولاتي المختلفة قبل تشغيلها. يتيح letencrypt تحديدًا للمعدل عند عدم التشغيل في وضع التدريج (أو على الأقل في التدريج يكون من الصعب مواجهة ذلك).

يمكن العثور على جميع التغييرات المذكورة أعلاه ، والتجريب ، والفشل ، ثم النجاح في النهاية في طلب السحب هذا.

النتيجة النهائية؟

ومن //www.ssllabs.com/ -

ليست "A +" ، ولكنها ليست سيئة حقًا لاستخدام صورة عامل إرساء واحدة مسبقة الصنع لاحتياجات HTTP الخاصة بي!

ذات صلة:

  • الانتقال من "A" إلى "A +" على ssllabs.com