Letsencrypt mit acme.sh und Apache

Ich nutze für das Holen von Zertifikaten die Software acme.sh, ein einfaches einzelnes Shellscript.

Eigenschaften und Vorteile dieser Installation

Dieser Artikel beschreibt ein generisches Setup für Apache, was folgende Eigenschaften hat:

  • Für das Holen von Zertifikaten wird nie die Konfiguration von Apache manipuliert.
  • Port 80 wird nur noch ausschließlich für Letsencrypt verwendet.
  • Alle anderen Webzugriffe werden von zentral auf https zu den jeweiligen Webseiten umgeleitet
  • Wir benötigen keinen Zugriff auf den DNS, wie hier beschrieben.

Das ist ein großartiges Setup, weil es Komplexität vermeidet (keine dynamische Umkonfiguration von Komponenten und keine Schnittstelle zum DNS. Dadurch wird es auch sicherer.

Vorbereitungen

Damit das alles funktioniert benötigen wir folgendes:

  • Ein Linux-System, für Server verwende ich gerne Debian.
  • Einen installierten Apache Webserver
  • Dabei das mod_rewrite eingeschaltet, auf Debian mit a2enmod rewrite
  • Ebenso natürlich mod_ssl für https, auf debian mit a2enmod ssl
  • Eine installierte Version von acme.sh, die Installation habe ich hier beschrieben. Wir verwenden hier aber keine DNS-Challenge.

Einrichtung und Konfiguration

Zunächst erstellen wir ein Verzeichnis, wo acme.sh die sogenannte Challenge mit Letsencrypt ausfechten kann:

mkdir -p /var/www/letsencrypt
chown -R www-data:www-data /var/www/letsencrypt

Die Verifizierung funktioniert so, dass wir mittels acme.sh bei Letsencrypt ein Zertifikat anfragen und Letsencrypt schaut dann, ob es ein Geheimnis, was wir nach /var/www/letsencrypt legen, abrufen kann. Wenn ja, ist verifiziert, dass uns die Domain gehört. Dafür müssen wir dieses Abrufen ermöglichen. Wir machen das hier zentral für alle Webseiten bzw. virtuellen Hosts auf diesem Webserver.

Dafür richten wir im Apachen einen eigenen virtuellen zentralen Host ein, der alle Zugriffe auf Port 80, also normales HTTP, abfängt und dann eines von zwei Dingen tut:

  1. Wenn es eine Letsencrypt-Challenge ist, liefere das Geheimnis aus.
  2. Wenn es ein versehentlicher Zugriff über Port 80 ist, leite zu der angeforderten Webseite weiter, aber mit HTTPS, also ein Redirect.

Wir legen jetzt die Datei /etc/apache2/sites-available/000-default.conf an bzw. verändern diese, wenn schon vorhanden.

<VirtualHost *:80>
	# Put this in 000-default.conf
	Alias /.well-known/acme-challenge/ /var/www/letsencrypt/.well-known/acme-challenge/
    <Directory "/var/www/letsencrypt/.well-known/acme-challenge/">
        Options None
        AllowOverride None
        ForceType text/plain
        RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"
    </Directory>
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge [NC]
	RewriteCond %{HTTPS} off
	RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

Aus allen anderen ggf. konfigurierten virtuellen Hosts löschen wir bitte den Teil für Port 80, so dass es keine individuellen Konfigurationen mehr gibt, die auf etwas anderes, als auf Port 443 verweisen. Das Ganze funktioniert übrigens auch für reine Weiterleitungs-Domains, die ja auch SSL-verschlüsselt sein müssen.

Nun schalten wir unsere Konfiguration an, prüfne sie auf Richtigkeit und starten bzw. restarten den Apache Webserver, wenn alles passt:

a2ensite 000-default.conf
apachectl configtest
systemctl restart apache2

Holen der Zertifikate mit acme.sh

Jetzt ist alles vorbereitet und wir können die Zertifikate erstmalig für unsere jeweilige Domain abrufen, zunächst als Test:

/etc/acme.sh/acme.sh --test --issue -d meine.domain.de -w /var/www/letsencrypt

und wenn das funktioniert, dann wirklich:

/etc/acme.sh/acme.sh --issue -d meine.domain.de -w /var/www/letsencrypt

Das machen wir jetzt für jede Webseite, die wir auf unserem Webserver hosten.

Einbinden der Zertifikate in die VHost-Konfigurationen

Jetzt, da wir die Zertifikate haben, können wir für unsere Domains bzw. VHosts diese ergänzen bzw. einbinden, wie folgt:

<VirtualHost *:443>
        ServerName meine.domain.de:443
        DocumentRoot /var/www/sites/support
        <Directory /var/www/sites/support>
                AllowOverride All
        </Directory>
        ErrorLog /dev/null
        CustomLog /dev/null common

        SSLEngine on
        SSLCertificateFile /etc/acme.sh/certs/meine.domain.de/fullchain.cer
        SSLCertificateKeyFile /etc/acme.sh/certs/meine.domain.de/meine.domain.de.key
</VirtualHost>

Danach nicht vergessen, den Apachen durchzustarten:

systemctl restart apache2

Automatisierung mit cron

Damit das fortan alles automatisch läuft, richten wir jetzt einen Eintrag in cron ein, indem wir crontab -e aufrufen, hier jeweils nachts um 0:17 Uhr:

17 0 * * * /etc/acme.sh/acme.sh --cron --home "/etc/acme.sh" --config-home "/etc/acme.sh/config" > /dev/null

Die Parameter --home bzw. --config-home können sich unterscheiden, jenachdem, wie Ihr acme.sh eingerichtet habt.

Das war’s. Viel Spaß damit!