nginx-LetsEncrypt Reverse Proxy in der Praxis

Um auf einem Server mehrere Webservices mit entsprechenden SSL-Zertifikaten zu betreiben, bietet sich der Letsencrypt-nginx-proxy-companion an. Bei dem Setup handelt es sich um einen Reverse-Proxy, welcher SSL-Offloading und die Zertifikats-Verwaltung übernimmt. Ist der Proxy einmal gestartet, kümmert sich der Companion um die Bereitstellung mehrerer Webseiten über eine gemeinsame IP und um dessen Zertifikatsverwaltung: Für das Ausstellen der Zertifikate für neue Container und das Erneuern dieser für bestehende Container: Alles im laufenden Betrieb und innerhalb weniger Sekunden.  

Schematische Darstellung

Hier schematisch dargestellt, anhand der Seiten www.libe.net und www.script-example.com:

Der nginx-Reverse-Proxy horcht nach dem Starten der Container auf Port 80 und 443. Die beiden Ports müssen im Internet unter einer öffentlichen IP verfügbar sein:
Als Webserver kann ein virtueller oder Cloud- Server eines shared Hosters verwendet werden, oder der eigene PC zu Hause mit einer eingerichteten Port-Weiterleitung am Router, siehe: port-forwarding

Installation - Nginx Letsencrypt Proxy

Als Voraussetzung für das Setup wird natürlich Docker benötigt, siehe: Docker Installation Linux oder Docker Installation Windows.

Für einen schnellen Start kann folgendes Repo geklont werden: https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion. Konkret habe ich auf meinem Linux-Rechner und am V-Server des Hosting-Provider folgenden Befehle für die Inbetriebnahme verwendet:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git 
cd /var
mkdir docker
git clone https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion.git proxy
cp .env.sample .env
./start.sh

Nach dem Start können zusätzlich beliebig viele Webseiten gestartet werden. Der nginx-Proxy passt seine Konfiguration automatisch anhand der Eigenschaften der Container an. Damit die Webserver für dessen Domains auch ein Zertifikat bekommen, bzw. aus dem Internet erreichbar sind, reicht es als Eigenschaften für die Container folgende Werte zu hinterlegen:

  • -e VIRTUAL_HOST=xxx.libe.net 
  • -e LETSENCRYPT_HOST=xxx.libe.net 
  • -e LETSENCRYPT_EMAIL=bernhard@libe.net 
  • --network=webproxy

Die Variable "VIRTUAL_HOST" gibt vor auf welchen Container der Reverse-Proxy den Traffic für diese Domäne durchstellen soll. "LETSENCRYPT_HOST" ist der DNS-Name für das Lets Encrypt-Zertifikat (sollte gleich "VIRTUAL_HOST" sein) und "LETSENCRYPT_EMAIL" die Mail-Adresse die beim Ausstellen des Zertifikats angegeben wird. Das Netzwerk "webproxy" wurde als Backend-Netzwerkname in der zuvor heruntergeladenen Docker-Compose-Konfig verwendet. Nachdem die Domains im nginx-Proxy bekannt gemacht wurden, werden die Anfragen auf den Container über das Netzwerk webproxy des Reverse-Proxy geleitet.

Beispiel: Start einer Webseite

Bevor wir die erste Webseite starten, muss ein A-Record im DNS hinterlegt werden, welcher auf die öffentliche IP-Adresse des Webservers zeigt. Im Anschluss kann ein einfacher Webserver mit folgenden Befehlen im Internet zur Verfügung gestellt werden, inkl. SSL-Zertifikat:

docker run -d -e VIRTUAL_HOST=xxx.libe.net \
              -e LETSENCRYPT_HOST=xxx.libe.net \
              -e LETSENCRYPT_EMAIL=bernhard@libe.net \
              --network=webproxy \
              --name xxx \
              -v /var/www/xxx/httpdocs:/var/www \
              httpd:alpine

Was macht der Companion genau?

Der Letsencrypt-nginx-proxy-companion verwendet die Eigenschaften anderer Container und trägt diese als Upstream-Server ein. Er fungiert als Reverse-Proxy und leitet sämtliche Anfragen weiter. Für die Weiterleitung kann Port 80 verwendet werden, für den Zugriff auf die gehosteten Seiten 80 oder 443. Für https, Port 443 wird das SSL-Zertifikat vom Reverse-Proxy verwaltet und verlängert: SSL-Offloading.

Zertifikat ausstellen und verlängern

Die Zertifikatsverwaltung läuft mit diesem Setup automatisch. Ein Blick in die Logs verrät, was im Hintergrund passiert: Der Container nginx-letsencrypt kontrolliert beim Start und alle 60 Minuten die Zertifikate. Sollte ein neues Zertifikat notwendig sein, wird dieses angefordert und verwendet:

nginx-letsencrypt    | /etc/nginx/certs/www.libe.net /app
nginx-letsencrypt    | Creating/renewal www.libe.net certificates... (www.libe.net)
nginx-letsencrypt    | 2021-03-14 11:09:24,871:INFO:simp_le:1414: Generating new certificate private key
nginx-web            | www.libe.net 18.196.96.172 - - [14/Mar/2021:11:09:26 +0000] "GET /.well-known/acme-challenge/xxx HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
nginx-web            | www.libe.net 3.128.26.105 - - [14/Mar/2021:11:09:26 +0000] "GET /.well-known/acme-challenge/xxx HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
nginx-web            | www.libe.net 34.211.6.84 - - [14/Mar/2021:11:09:26 +0000] "GET /.well-known/acme-challenge/xxx HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
nginx-web            | www.libe.net 66.133.109.36 - - [14/Mar/2021:11:09:26 +0000] "GET /.well-known/acme-challenge/xxx HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
nginx-letsencrypt    | 2021-03-14 11:09:29,190:INFO:simp_le:396: Saving key.pem
nginx-letsencrypt    | 2021-03-14 11:09:29,191:INFO:simp_le:396: Saving chain.pem
nginx-letsencrypt    | 2021-03-14 11:09:29,193:INFO:simp_le:396: Saving fullchain.pem
nginx-letsencrypt    | 2021-03-14 11:09:29,193:INFO:simp_le:396: Saving cert.pem

Rate-Limit: here were too many requests of a given type :: Error creating new order

Sollte zum Beispiel der DNS noch nicht auf die öffentliche IP-Adresse zeigen und der Container dennoch bereits laufen, ist etwas Geduld gefragt. Ich hatte an dieser Stelle nicht so viel Geduld und den Letsencrypt-nginx-proxy-companion mehrfach neugestartet, woraufhin dieser bei jedem Start um ein Zertifkat angefragt hat, welches aufgrund des DNS-Eintrags aber nicht ausgestellt werden konnte. An dieser Stelle habe ich gelernt, dass pro Stunde nur 5 Anfragen für ein neues Zertifikat erlaubt sind, in den Logs spiegelt sich das wie folgt wieder:

Attaching to nginx-letsencrypt, nginx-gen, nginx-web
...
nginx-gen            | 2021/03/14 10:09:12 Generated '/etc/nginx/conf.d/default.conf' from 12 containers
...
nginx-gen            | 2021/03/14 10:09:12 Contents of /etc/nginx/conf.d/default.conf did not change. Skipping notification ''
...
nginx-letsencrypt    | Creating/renewal www.script-example.com certificates... (www.script-example.com)
nginx-letsencrypt    | 2021-03-14 10:09:19,372:INFO:simp_le:1546: Certificates already exist and renewal is not necessary, exiting with status code 1.
...
nginx-letsencrypt    | Creating/renewal www.libe.net certificates... (www.libe.net)
nginx-letsencrypt    | 2021-03-14 10:09:17,961:INFO:simp_le:1414: Generating new certificate private key
nginx-letsencrypt    | ACME server returned an error: urn:ietf:params:acme:error:rateLimited :: There were too many requests of a given type :: Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/
...
nginx-letsencrypt    | Sleep for 3600s

Die Lösung: eine Stunde warten. Der Letsencrypt-nginx-proxy-companion versucht es in der nächsten Stunde wieder und wenn der DNS dann passt, wird auch ein Zertifikat ausgestellt und verwendet. 

Die beschriebene Lösung kann dann zum Beispiel für den Betrieb anderer Websevices verwendet werden, z.B. Nextcloud, siehe: /docker-nextcloud-ssl

positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE für deine Bewertung!



Fragen / Kommentare


Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Außerdem geben wir Informationen zu Ihrer Nutzung unserer Website an unsere Partner für soziale Medien, Werbung und Analysen weiter. Details anzeigen.