de Russell Hammett Jr. (Kritner)

Cum să vă configurați site-ul web pentru HTTPS dulce, dulce cu Docker, Nginx și letsencrypt

Cum sa va configurati site ul web pentru acel HTTPS dulce

Am folosit letsencrypt în trecut pentru certificatele gratuite. Nu l-am folosit cu succes de când m-am mutat la docker / kestrel / nginx. Totul s-a schimbat astăzi și am avut un timp drăguț să-mi dau seama ce făceam pentru ca să funcționeze.

Întregul întreg Unix, docker, nginx, este destul de nou (pentru mine), deci poate că este doar ceva simplu, care îmi lipsea tot timpul. Cu toate acestea, sper că acest lucru va ajuta pe altcineva sau pe mine câteva luni pe drum, dacă decid să o fac din nou.

Configurare originală

Am un nucleul .net site-ul web, fiind găzduit prin cerneală, alergând mai departe docher, cu un proxy invers via nginx. Până în prezent, acea proxy inversă de la nginx funcționa doar pe http / port 80. Nu știu multe despre proxy-urile inverse. Din sunetul acestuia, acesta poate primi cereri și le poate transmite către o anumită locație în numele solicitantului. În cazul meu, containerul nginx primește solicitări http și nginx redirecționează această solicitare pe site-ul meu de bază .net găzduit de kestrel. Este corect? In speranta!

După cum sa menționat anterior, nginx funcționa numai cu trafic http. Am avut o mulțime de probleme pentru a funcționa cu https, configurația originală este următoarea:

docker-compune:

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:

În fișierul docker-compose, folosesc două containere separate – site-ul web, care expune portul 5000 (în rețeaua de andocare, nu public) și nginx care funcționează pe portul 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         http://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;        }    }}

În fișierul de configurare, configurăm un server în amonte cu același nume pe care îl apelăm la serviciul nostru de containere din fișierul docker-compose kritner-website-web:5000.

Rețineți, toate cele de mai sus pot fi găsite la aceasta punctul de comitere în depozitul site-ului meu web.

Introduceți HTTPS

Letsencrypt este o autoritate de certificare care oferă certificate gratuite pentru a vă securiza site-ul web. De ce este important HTTPS prin TLS? Ei bine, există o mulțime de lucruri și cum funcționează. Ideea de bază este că traficul utilizatorului este criptat la ambele capete înainte de a fi trimis la celălalt capăt. Aceasta înseamnă că, dacă sunteți pe Wi-Fi public și pe https, cineva care „adulmecă firul”, ca să spunem așa, ar vedea că se produce trafic, dar nu conținutul respectivului trafic. Deoarece ambele capete criptează / decriptează respectivul trafic cu aceeași cheie de criptare.

Dacă ați fi pe un site http, acest trafic ar fi trimis înainte și înapoi în text simplu. Adică datele dvs. sunt în pericol de a fi ascultate! Poate că voi scrie ceva mai mult despre criptare la un moment dat. (* notă pentru sine *) Mai ales că este ceva ce fac ca slujba mea de zi cu zi!

letsencrypt este un serviciu pe care l-am folosit anterior. Există diferite implementări pentru a încerca să fie cât mai ușor de utilizat. Prin cercetări pentru acest post, m-am întâmplat acest.

Deși nu găsisem această pagină până acum, ar fi fost utilă înainte de a începe aventura mea. Am vrut să folosesc letsencrypt împreună cu site-ul meu container docker și nginx, cu o întreținere cât mai mică posibilă. certificatele letencriptate sunt bune numai timp de 90 de zile.

În cercetarea mea, m-am întâmplat cu o imagine docker linuxserver / letsencrypt care promite să utilizeze nginx, lasă să cripteze generarea certificatului ȘI reînnoirea automată. Sună fabulos! În timp ce documentația imaginii pare în mare parte adecvată – pentru cineva bine versat în tot acest proces. Mi s-a părut că lipsește. Întregul proces de configurare mi-a luat ceva timp să-mi dau seama. De aici, această postare, pentru a ajuta, sperăm, pe următoarea persoană, sau din nou pe mine în viitor!

1611932347 167 Cum sa va configurati site ul web pentru acel HTTPS dulce
Sigla Linux Server.IO

Lupte

Lucrurile cu care m-am luptat cel mai mult atunci când am obținut acest linuxserver / lasă să criptăm imaginea și să funcționăm au ​​fost:

  • Cum „funcționează” volumele docker și relația lor cu acest container
  • Cum să setez volume pentru a utiliza configurația mea (legat de punctul de mai sus) – Am avut inițial o mulțime de probleme pentru a afla de ce setările mele modificate pe container erau schimbate la reîncărcarea containerului menționat (pentru că asta este ceea ce sunt ele ar trebui să facă)
  • Cum să configurați configurația corectă nginx – unde să o puneți și ce să puneți în ea.

Volume Docker

Volume Docker (doc):

Volumele sunt mecanismul preferat pentru datele persistente generate și utilizate de containerele Docker. In timp ce legați monturile sunt dependente de structura de directoare a mașinii gazdă, volumele sunt complet gestionate de Docker. Volumele au mai multe avantaje față de suporturile de legare

letsencrypt are o mulțime de configurații pentru a merge împreună cu el. Mi-a luat ceva timp să-mi dau seama, dar aveam nevoie de un volum care să fie mapat dintr-un director de pe gazdă docker la un anumit director din imaginea letsencrypt. În cele din urmă, am realizat acest lucru în fișierul compune astfel:

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

Primul element din matrice (${DOCKER_KRITNER_NGINX}:/config) ia o nouă variabilă de mediu care mapează directorul gazdă (definit în variabilă) la /config în interiorul containerului de andocare. Aceasta înseamnă că gazdă docker (la calea env var) va conține aceeași configurare ca container de andocare la porțiunea secundară a mapării volumului (/config)

Al doilea element (./nginx.conf:/config/nginx/site-confs/default) mapează depozitele mele locale fișierul nginx.conf (fișierul în care am configurat proxy-ul invers) pentru a suprascrie /config/nginx/site-confs/default fișier pe gazda și containerul de andocare.

Lista completă a fișierelor pe care am ajuns să le modific pentru situația mea particulară a fost:

  • /config/dns-conf/dnsimple.ini
  • /config/nginx/site-confs/default

dnsimple.ini configurația a fost adăugarea cheii mele API și a …/default găzduiește configurația nginx.

Finala default configurația cu care am ajuns este:

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         http://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;

Există câteva modificări față de valoarea implicită care a fost acolo, pe care voi încerca să le evidențiez în continuare.

upstream app_servers {        server kritnerwebsite:5000;}

Mai sus este destul de cool, deoarece docker-ul are propriul său DNS intern (cred?). Puteți configura un server în amonte după numele containerelor, în cazul meu „site web kritner”. (Notă: Am schimbat-o de la o postare anterioară, care era „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;}

A necomentat această secțiune din valoarea implicită, mi-a aplicat server_name pe „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         http://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;    }
}

În cele de mai sus, este în principal din salvarea „implicită” pentru „locație” și tot ceea ce se află în acel obiect. Aici, configurăm proxy-ul invers pentru a redirecționa cererile către „/” (orice) către noi http://app_servers (kritnerwebsite conform amontei noastre).

docker-compose.yml

Fișierul nostru de compunere docker nu a schimbat un lot * întreg * față de inițial. Au existat câteva modificări notabile, pe care le voi descrie și:

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:

pentru piesele noi:

nginx:    image: linuxserver/letsencrypt

Folosind o imagine diferită – linuxserver / letsencrypt în loc de nginx. Această imagine include nginx, dar și certbot, împreună cu o cronjob pentru a rula certbot la începutul aplicației.

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

Acum folosim atât porturile http, cât și porturile https (deși rețineți, redirecționăm apelurile http către https prin configurația nginx).

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

Am discutat deja mai devreme în postare, folosim aceste volume pentru a configura corect configurația nginx, cu cheia noastră API dnsimple, precum și proxy-ul nostru invers către kritnerwebsite.

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

Variabilele de mediu necesare conform documentației de tip „letencript” pot fi găsite Aici.

  • PUID / PGID – accesați dockerhost prin comanda „id
  • E-mail – bine, e-mailul dvs. (folosit pentru e-mailurile cu expirare certă aparent)
  • URL – adresa URL principală a domeniului
  • subdomenii – orice subdomenii ale adresei URL care urmează să fie certificate
  • TZ – fus orar
  • Validare – tipul de validare de făcut – folosesc DNSimple, așa că am nevoie de DNS în acest câmp. Alte opțiuni sunt html, tls-sni
  • dnsplugin – dnsimple – alte opțiuni sunt cloudflare, cloudxns, digitalocean, dnsmadeeasy, google, luadns, nsone, rfc2136 și route53 conform documentației de tip „letencript”
  • Punere în scenă = adevărat – Am folosit acest lucru pentru testarea tuturor încercărilor mele înainte de a pune în funcțiune. letsencrypt are o limitare a ratei atunci când nu rulează în modul de punere în scenă (sau cel puțin în etapă este mai greu să te confrunți).

Toate modificările de mai sus, experimentând, eșuând și apoi reușind în cele din urmă pot fi găsite în această cerere de tragere.

Rezultatul final?

1611932347 360 Cum sa va configurati site ul web pentru acel HTTPS dulce
Da, da

și din https://www.ssllabs.com/

1611932348 757 Cum sa va configurati site ul web pentru acel HTTPS dulce

Nu este un „A +”, dar chiar nu e rău pentru a folosi o imagine docker pre-construită pentru nevoile mele HTTP!

Legate de: