Netcraft: Nginx führt bei Webservern
Netcraft hat in seiner monatlichen Analyse zu den aktiven Webservern bei Cloudflare den größten Zuwachs gemessen.
Netcraft hat in seiner monatlichen Analyse zu den aktiven Webservern bei Cloudflare den größten Zuwachs gemessen.
Seit vielen Jahren verwende ich Let’s Encrypt-Zertifikate für meine Webserver. Zum Ausstellen der Zertifikate habe ich in den Anfangszeiten das Kommando certbot
genutzt. Weil die Installation dieses Python-Scripts aber oft Probleme bereitete, bin ich schon vor vielen Jahren auf das Shell-Script acme.sh
umgestiegen (siehe https://github.com/acmesh-official/acme.sh).
Kürzlich bin ich auf einen Sonderfall gestoßen, bei dem acme.sh
nicht auf Anhieb funktioniert. Die Kurzfassung: Ich verwende Apache als Proxy für eine REST-API, die in einem Docker-Container läuft. Bei der Zertifikatausstellung/-erneuerung ist Apache (der auf dem Rechner auch als regulärer Webserver läuft) im Weg; die REST-API liefert wiederum keine statischen Dateien aus. Die Domain-Verifizierung scheitert. Abhilfe schafft eine etwas umständliche Apache-Konfiguration.
Ausgangspunkt ist also ein »gewöhnlicher« Apache-Webserver. Dieser soll nun zusätzlich eine REST-API ausliefern, die in einem Docker-Container läuft (localhost:8880). Die erste Konfiguration sah ziemlich simpel aus:
# zusätzliche Apache-Proxy-Konfigurationsdatei
# für einen Docker-Container
<VirtualHost *:443>
ServerName api.example.com
# SSL
SSLEngine on
SSLCertificateFile /etc/acme-letsencrypt/api.example.com.pem
SSLCertificateKeyFile /etc/acme-letsencrypt/api.example.com.key
# Proxy: localhost:8880 <-> https://api.example.com
ProxyPreserveHost On
ProxyPass / http://localhost:8880/
ProxyPassReverse / http://localhost:8880/
# Logging Konfiguration ...
</VirtualHost>
# HTTP -> HTTPS
<VirtualHost *:80>
ServerName api.example.com
Redirect permanent / https://api.example.com
</VirtualHost>
Das Problem besteht darin, dass acme.sh
zwar diverse Domain-Verifizierungsverfahren kennt, aber keines so richtig zu meiner Konfiguration passt:
acme.sh ... --webroot
scheitert, weil die API eine reine API ist und keine statischen Dateien ausliefert.acme.sh ... --standalone
scheitert, weil der bereits laufende Webserver Port 80 blockiert.acme.sh ... --apache
scheitert mit could not resolve api.example.com.well-known.Die Lösung besteht darin, die Apache-Proxy-Konfiguration dahingehend zu ändern, dass zusätzlich in einem Verzeichnis statische Dateien ausgeliefert werden dürfen. Dazu habe ich das neue Verzeichnis /var/www/acme-challenge
eingerichtet:
mkdir /var/www/acme-challenge
chown www-data:www-data /var/www/acme-challenge/
Danach habe ich die Konfigurationsdatei für Apache umgebaut, so dass Anfragen an api.example.com/.well-known/acme-challenge
mit statischen Dateien aus dem Verzeichnis /var/www/acme-challenge/.well-known/acme-challenge
bedient werden:
# Apache-Konfiguration wie bisher
<VirtualHost *:443>
ServerName api.example.com
# SSL
SSLEngine on
SSLCertificateFile /etc/acme-letsencrypt/api.example.com.pem
SSLCertificateKeyFile /etc/acme-letsencrypt/api.example.com.key
# Proxy: localhost:8880 <-> api.example.com
ProxyPreserveHost On
ProxyPass / http://localhost:8880/
ProxyPassReverse / http://localhost:8880/
# Logging Konfiguration ...
</VirtualHost>
# geändert: HTTP auf HTTPS umleiten, aber nicht
# für well-known-Verzeichnis
<VirtualHost *:80>
ServerName api.example.com
# Handle ACME challenges locally
Alias /.well-known/acme-challenge /var/www/acme-challenge/.well-known/acme-challenge
<Directory /var/www/acme-challenge/.well-known/acme-challenge>
Require all granted
</Directory>
# Redirect everything EXCEPT ACME challenges to HTTPS
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
RewriteRule ^(.*)$ https://api.example.com$1 [R=301,L]
</VirtualHost>
Nach diesen Vorbereitungsarbeiten und mit systemctl reload apache2
gelingt nun endlich das Zertifikaterstellen und -erneuern mit dem --webroot
-Verfahren. Dabei richtet acme.sh
vorübergehend die Datei /var/www/acme-challenge/.well-known/acme-challenge/xxx
ein und testet dann via HTTP (Port 80), ob die Datei gelesen werden kann.
# Zertifikat erstmalig erstellen
acme.sh --issue --server letsencrypt -d api.example.com --webroot /var/www/acme-challenge
# Zertifikat installieren und Renew-Prozess einrichten
acme.sh --install-cert -d api.example.com \
--key-file /etc/acme-letsencrypt/api.example.com.key \
--fullchain-file /etc/acme-letsencrypt/api.example.com.pem \
--reloadcmd "service apache2 reload"
# Renew-Prozess testen
acme.sh --renew -d api.example.com --force
Eine noch elegantere Lösung besteht darin, den Docker-Container mit Traefik zu kombinieren (siehe https://traefik.io/traefik/). Bei korrekter Konfiguration kümmert sich Traefik um alles, nicht nur um die Proxy-Funktionen sondern sogar um das Zertifikatsmanagment. Aber diese Lösung kommt nur in Frage, wenn auf dem Host nicht schon (wie in meinem Fall) ein Webserver läuft, der die Ports 80 und 443 blockiert.
Netcraft kann in seinen Messungen zur Verteilung von Webservern weltweit im Monat April Nginx den größten Zuwachs von 8,0 Millionen Websites zusprechen.
Netcraft hat in seinen Messungen zur Beliebtheit von Webservern für den Juni Antworten von 1,1 Milliarden Websites gewertet und sieht Nginx auf Platz eins.
In der Umfrage von Netcraft monatlich gemessenen Verbreitung von Webservern hat im März 2024 Nginx vor Apache den Spitzenplatz verteidigt.
Canonical hat nach der Übernahme der LXD-Entwicklung von Linux Containers nun die Lizenz von Apache2 auf AGPLv3 gewechselt.
Debian 10 Buster liefert eine veraltete Version von Apache 2 mit dem Module mod_md für Let‘ encrypt aus. Dieses Modul unterstütz nur ACMEv1. Hier kommt es zu einem Fehler bei dem Beziehen des Zertifikats: Die Lösung ist es aus den … Weiterlesen →
Der Beitrag Debian 10 Buster mod_md invalid (missing uri scheme): accepted erschien zuerst auf Got tty.