Hogyan állítsd be a webhelyedet az édes, édes HTTPS-hez a Docker, az Nginx és a Letencecript segítségével

Régebben a letencecrptet használtam ingyenes tanúsítványokhoz. Amióta átkerültem a docker / kestrel / nginx-re, nem használtam sikeresen. Ez mind megváltozott ma, és pokolian sok időm volt kitalálni, mit tettem, hogy működjön.

Ez az egész Unix, dokkoló, nginx, cucc meglehetősen új (számomra), szóval talán csak valami egyszerű dolog hiányzott nekem egész idő alatt. Mindazonáltal remélem, hogy ez segít másnak, vagy nekem több hónapon keresztül, ha úgy döntök, hogy újra megteszem.

Eredeti beállítás

Van egy .net központi webhelyem, amelyet a kestrelen keresztül tárolnak, dokkolón futnak, fordított proxyval az nginx-en keresztül. Eddig ez a fordított proxy az nginx-től csak a http / 80-as porton működött. Nem sokat tudok a fordított proxikról. A hangja alapján befogadhatja a kéréseket, és továbbíthatja azokat a kérelmező nevében egy adott helyre. Esetemben az nginx tároló http kéréseket fogad, és az nginx továbbítja ezeket a kéréseket a kestrel által tárolt .net törzshelyemre. Igaz? Remélhetőleg!

Mint korábban említettük, az nginx csak a http forgalommal működött. Nagyon sok problémám volt a https-sel való együttműködéssel, az eredeti konfiguráció a következő:

dokkoló-ír:

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:

A docker-compose fájlban két különálló tárolót használok - a weboldalt, amely az 5000-es portot teszi közzé (a dokkoló hálózatán, nem nyilvánosan), és az nginx-et, amely a 80-as porton működik.

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; } }}

A config fájlban egy upstream kiszolgálót állítunk be ugyanazzal a névvel, mint amelyet a docker-compose fájlból hívunk a tároló szolgáltatásunknak kritner-website-web:5000.

Ne feledje, hogy a fentiek a webhelyem adattárának ezen a pontján találhatók.

Írja be a HTTPS-t

A Letsencrypt egy tanúsító hatóság, amely ingyenes tanúsítványokat kínál a webhely biztonságának elősegítése érdekében. Miért fontos a TLS-en keresztüli HTTPS? Nos, ebben nagyon sok minden van, és hogy működik. Az alapötlet az, hogy a felhasználó forgalma mindkét oldalon titkosítva legyen, mielőtt elküldené a másik végére. Ez azt jelenti, hogy ha nyilvános wifi-n van, és a https-en valaki, aki úgymond „szippantotta a vezetéket”, látná, hogy forgalom zajlik, de nem az említett forgalom tartalma. Mivel mindkét vége ugyanannak a titkosítási kulccsal titkosítja / dekódolja az említett forgalmat.

Ha egy http webhelyen tartózkodna, akkor ezt a forgalmat egyszerű szövegként továbbítanák. Ez azt jelenti, hogy az adatait kihallgatás veszélye fenyegeti! Talán valamikor írok még egy kicsit a titkosításról. (* megjegyzés magamnak *) Különösen azért, mert ezt valami napi munkámként csinálom!

A letsencrypt egy olyan szolgáltatás, amelyet korábban használtam. Különböző megvalósítások vannak, amelyek megkísérlik a lehető legegyszerűbb használatát. Ennek a bejegyzésnek a kutatásával erre gondoltam.

Bár eddig nem találtam meg ezt az oldalt, a kalandozás megkezdése előtt hasznos lett volna. A letencryptet akartam használni a dokkoló konténer webhelyemmel és az nginx-szel együtt, a lehető legkevesebb karbantartással. A letecrypt tanúsítványok csak 90 napig jók.

Kutatásom során egy docker image linuxserver / letsencrypt-re kerültem, amely az nginx, a letiltás-tanúsítvány-generálás és az automatikus megújítás hasznosítását ígéri. Jól hangzik! Míg a kép dokumentálása többnyire megfelelőnek tűnik - valakinek, aki jártas ebben a folyamatban. Úgy találtam, hogy hiányzik. Az egész beállítási folyamat eltartott egy ideig, mire rájöttem. Ezért ez a bejegyzés, hogy remélhetőleg segítsem a következő embert, vagy újra a jövőben!

Küzdelmek

Azokkal a dolgokkal küzdöttem a legjobban, amikor a linuxserver / letencrypt képet feltöltöttem és működtem:

  • A dokkoló kötetek „működése” és kapcsolatuk ezzel a tárolóval
  • Hogyan állítsak be mennyiségeket a konfigurációm kihasználásához (a fenti ponthoz kapcsolódóan) - Kezdetben sok gondom volt kitalálni, hogy a tárolón megváltoztattam-e a beállításokat, miért változtattak vissza az említett konténer újratöltésekor (mert ők ezek meg kellett volna csinálni)
  • Hogyan állítsuk be a helyes nginx konfigurációt - hova tegyük, és mit tegyünk bele.

Docker kötetek

Docker kötetek (doc):

A Docker-tárolók által generált és általuk használt adatok megőrzésének előnyös mechanizmusa a kötetek. Míg a kötési felszerelések a gazdagép címtárszerkezetétől függenek, a köteteket teljesen a Docker kezeli. A köteteknek számos előnye van a kötőhöz képest

A letsencrypt sok konfigurációval rendelkezik hozzá. Eltartott egy ideig, mire rájöttem, de szükségem volt egy kötetre, amely a dokkoló gazdagépének egyik könyvtárából leképezett egy adott könyvtárba a letenckodott képen. Végül ezt az írási fájlban így hajtottam végre:

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

A tömb első eleme ( ${DOCKER_KRITNER_NGINX}:/config) egy új környezeti változót vesz fel, amely a gazdagép könyvtárát (a változóban definiálva) leképezi /configmagába a dokkoló-tárolóba. Ez azt jelenti, hogy a dokkoló gazdagép (az env var elérési útján) ugyanazt a konfigurációt fogja tartalmazni, mint a dokkoló tároló a kötetleképezés másodlagos részén ( /config)

A második elem ( ./nginx.conf:/config/nginx/site-confs/default) leképezi a helyi tárhelyeim nginx.conf fájlját (azt a fájlt, ahová a fordított proxyt állítottam be), hogy felülírja /config/nginx/site-confs/defaulta docker gazdagépen és a tárolón található fájlt.

A fájlok teljes listája, amelyeket végül módosítanom kellett az adott helyzetemhez:

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

A dnsimple.inikonfiguráció az api kulcs hozzáadása volt, és a …/defaultház tartalmazza az nginx konfigurációt.

A végső defaultkonfiguráció, amivel végül végeztem:

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;

Van néhány változás az alapértelmezett értékhez képest, amelyet megpróbálok kiemelni a következőkben.

upstream app_servers { server kritnerwebsite:5000;}

A fenti meglehetősen klassz, mivel a dokkolónak saját belső DNS-e van (gondolom?). Beállíthat egy upstream szervert a tárolók nevével, esetemben a „kritnerwebsite” néven. (Megjegyzés: A korábbi kritner-website-web nevű bejegyzésben megváltoztattam.)

# 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
  • Staging=true — I used this for testing out all my various attempts prior to getting it working. letsencrypt has rate limiting when not running in staging mode (or at least in staging it’s harder to run up against).

All the above changes, experimenting, failing, and then finally succeeding can be found in this pull request.

The final result?

and from //www.ssllabs.com/ —

Not an “A+”, but really not bad for using one pre-built docker image for my HTTPs needs!

Related:

  • Going from an “A” to an “A+” on ssllabs.com