Let’s Encrypt!, nginx und WordPress
21. Februar 2017 um 23:59 Uhr von Atari-Frosch
Es ist wirklich schade, daß CAcert mit seiner Assurance-Policy es immer noch nicht geschafft hat, in die CA-Listen der großen Browser zu kommen. Ich benutze die Zertifikate von dort immer noch – zum Beispiel in meinem Mailserver, wo nur wenige User mit draufhängen, denen ich noch problemlos einzeln erklären kann, warum ihre Software vielleicht anfangs wegen des Zertifikats meckert. Aber für Websites usw. ist es so halt nicht wirklich brauchbar.
„Wir Nerds“ wissen, wo man das passende Root-Certifikat runterziehen kann, aber der Durchschnittsbenutzer wird das eher nicht wissen. Er sieht nur von seinem Browser den Hinweis, daß da Pöhse Dinge™ passieren könnten, wenn er weitermacht, und wird sich dann eher eine andere Informationsquelle suchen. Daher habe ich mich dann letztendlich doch für LetsEncrypt! entschieden, um allgemein alle Websites auch mit ordentlichem https anbieten zu können.
Allerdings stellte sich heraus, daß das im Zusammenhang mit nginx nicht so einfach ist wie mit apache2, und daß der Certbot, den man sich dafür installieren muß, an ein paar Stellen ein wenig pingelig ist.
Zunächst kann man genauso anfangen, wie das auf Let's Encrypt! Getting Started beschrieben wird. Da hier ein Debian Jessie läuft, konnte ich ganz einfach den Certbot aus den Debian-Quellen heraus installieren. Dabei ist es nicht ganz unwichtig, die Installation tatsächlich so anzustoßen, wie es dort steht. Nach dem Eintrag der Backports-Quelle in die sources.list muß die Installation mit
:~$ apt-get install certbot -t jessie-backports
durchgeführt werden. Läßt man den Teil ab -t weg, meckert apt wegen nicht erfüllbarer Abhängigkeiten. (Nein, mir ist es nicht passiert. Ich hab's nur mitbekommen.)
Der Certbot zieht dann noch ein bißchen Python-Zeugs nach, und dann kann er so benutzt werden, wie dort beschrieben. Allerdings nur bis vor den Punkt, an welchem der Certbot eine Site authentifizieren soll. Hier ist dann, wenn die Site nicht nur eine einfache statische Website ist, noch ein Extra-Schritt nötig, denn der Certbot legt ein Unterverzeichnis namens .well-known in das Document Root der Website und schreibt da eine temporäre Datei rein, die er dann vom Checkbot von Lets Encrypt! überprüfen läßt.
Ist das Verzeichnis standardmäßig für WordPress konfiguriert, dann wird der Checkbot hier auf einen Statuscode 403 (Permission denied) stoßen. Das gleiche könnte auch bei anderen Webanwendungen passieren. Das Problem ist, daß der Verzeichnisname mit einem Punkt anfängt, was ja bekanntermaßen für ein verstecktes Verzeichnis steht.
Deshalb muß in die Konfigurationsdatei für die Site ein zusätzlicher Block Anweisungen eingetragen werden:
Datei: /etc/nginx/sites-available/$vhost (wobei $vhost für die Datei steht, welche die Site mit dem WordPress konfiguriert):
# This location block is for the LetsEncrypt authentication.
location ^~ /.well-known {
root /srv/$wp-directory;
autoindex off;
index index.html;
try_files $uri $uri/ =404;
}
(Geklaut von rowanthorpe auf Github und etwas modifiziert.) $wp-directory steht für das Verzeichnis mit der WordPress-Installation.
Diese Anweisung darf auch nicht einfach irgendwo hin, sondern muß unbedingt vor den primären Location-Block, der auf / zeigt. Wenn man diesen Block für den Checkbot weiter unten einfügt, geht's nicht. BTDT.
Erst wenn diese Ergänzung eingetragen und service nginx reload (hoffentlich) erfolgreich ausgeführt wurde, kann der Certbot damit beauftragt werden, ein Zertifikat anzufordern:
:~$ certbot certonly --webroot -w /srv/$wp-directory -d $domain
Damit das Zertifikat ab sofort auch genutzt werden kann, müssen wir jetzt ein zweites Mal in die VHost-Konfiguration. Einfach den Server-Teil für http nochmal nach darunter kopieren (falls es da bereits einen https-Teil gibt, besser löschen und die Kopie des http-Teils nehmen, damit es nicht versehentlich zu Differenzen kommt). Nach der öffnenden geschweiften Klammer kommt dann erstmal noch eine Zeile, die den Port festlegt:
listen 443;
Dann wird zusätzlich nach der Zeile include global/restrictions.conf; folgendes eingefügt:
ssl on;
ssl_certificate /etc/letsencrypt/live/$domain/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
$domain muß natürlich durch den Domainnamen (nicht Verzeichnisnamen!) ersetzt werden.
Jetzt nochmal ein service nginx reload, und dann gilt der kürzeste Computerwitz aller Zeiten: Müßte laufen 😉
[Update 2017-02-22 16:35]
Die Let's Encrypt! Certs gelten nur 90 Tage. Damit sie weiterlaufen, müssen sie entsprechend regelmäßig erneuert werden. Praktischerweise kann man das einem Cronjob überlassen: einfach als root crontab -e aufrufen und da eintragen:
00 03 * * * /usr/bin/certbot renew --post-hook "service nginx reload"
Die Uhrzeit ist natürlich nur ein Beispiel, aber morgens um drei finde ich 'ne gute Zeit.
Der Certbot überprüft dann alle installierten Zertifikate auf ihre Gültigkeit und erneuert sie bei Bedarf. Der Webserver muß dabei seine Konfiguration nur neu starten, wenn es notwendig ist. Liegen also keine neuen Zertifikate an, dann gibt es auch keinen reload.
[/Update]
22. Februar 2017 at 7:22
Dieses riesige python-Monster certbot, was sich erstmal ne Tonne Dependencies nachzieht nehme ich nicht. Ich empfehle dehydrated, das funktioniert mit bash und openssl. Für Apache gibts dazu noch dehydrated-apache2, was sich als konfigschnippsel integriert. Für nginx muss man etwas mehr Handarbeit machen
22. Februar 2017 at 16:57
@Cord: Let’s Encrypt schlägt den Certbot bevorzugt vor, also habe ich natürlich den genommen. Da ich bislang noch keine Erfahrungen mit solchen Bots hatte, folge ich natürlich einer solchen Empfehlung. dehydrated wurde mir auch schon anderweitig empfohlen – aber da hatte ich meine „Diskussionen“ mit dem Certbot schon durch.
22. Februar 2017 at 17:28
Und dazu noch fastcgi_cache vom nginx: https://www.datenklause.de/blog/5770/howto-wordpress-mit-nginx-und-fastcgi_cache/
22. Februar 2017 at 18:04
Nimm mal lieber ssl_ciphers ‚EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH‘;
22. Februar 2017 at 18:53
@Sirko: Ich weiß, da muß ich nochmal drüber; die Auflistung bei mir ist schon älter. Aber ich möchte wenigstens grob verstehen, was ich da eintrage, deshalb mach ich da jetzt nicht einfach copy & paste.