Die Situation
Ich habe tech-tales.blog
bei World4You gekauft. Hier habe ich die Challenge, dass World4You mir keinen API-Zugang zum DNS Server bietet, ich kann also primär keine DNS Verifizierung für ein Wildcard-Zertifikat machen. Trotzdem würde ich gerne automatisch ein Wildcard-Zertifikat generieren, da alle meine internen Services via *.tech-tales.blog
erreichbar sind.
Zusätzlich ist es mir aus verschiedenen Gründen nicht möglich, den DNS Server einfach zu wechseln. Insbesondere betreibt World4You aktuell meinen eMail Server, und das Ändern des DNS Servers würde das umstellen. Das möchte ich (noch) nicht machen.
Die Lösung: Eine zweite Domain!
Ich habe schon länger eine alternative Domain bei Hetzner geshoppt, nennen wir sie tech-tales-alternative.blog
.
Mit acme.sh
kann ich diese zweite Domain nutzen, um eine DNS Challenge auf der ersten Domain zu beantworten! Dieser Post soll erklären wie ich das mache.
Die Erklärung
Wenn ich Let’s Encrypt um ein Zertifikat für *.tech-tales.blog
frage und dafür die DNS-Challenge nutzen möchte, muss ich einen TXT DNS-Eintrag auf _acme-challenge.tech-tales.blog
erzeugen, mit einem von Let’s Encrypt bereitgestelltem Inhalt. Sobald ich das gemacht habe verifiziert Let’s Encrypt dass dieser Eintrag korrekt existiert und stellt dann mein Zertifikat aus.
Ich kann jetzt das folgende machen: Statt einem TXT Record auf _acme-challenge.tech-tales.blog
erzeuge ich diesen TXT Eintrag auf _acme-challenge.tech-tales-alternative.blog
. Zusätzlich erzeuge ich einen CNAME Eintrag wie folgt:
_acme-challenge.tech-tales.blog IN CNAME _acme-challenge.tech-tales-alternative.blog.
Let’s Encrypt versteht das und folgt dem CNAME, und so funktioniert auch die Erstellung meines Zertifikats!
Das Skript
Ich gehe davon aus dass acme.sh
bereits installiert ist. Dann hole ich mir über die Hetzner DNS Console einen API Key, und dann führe ich das folgende im Terminal aus:
# Token hier einfügen
EXPORT HETZNER_TOKEN=abcdefghijklmnopqrstuvwxyz
acme.sh \
--issue \
--server letsencrypt_test \
-m admin@tech-tales.blog \
-d *.tech-tales.blog \
--dns dns_hetzner \
--challenge-alias tech-tales-alternative.blog
Beachte dass ich zur Zeit --server letsencrypt_test
setze, also den Test-Server verwende. Sobald ich mir sicher bin dass alles klappt wie vorgesehen, wechsel ich zu --server letsencrypt
.
Dieser Befehl wartet einige Sekunden, bis alles klappt. Im Wesentlichen gibt es ein paar relevante Zeilen im Output:
Adding TXT value: ... for domain: _acme-challenge.tech-tales-alternative.blog
- Dadurch wird der DNS Eintrag dort erzeugt, wo er benötigt wird.Success for domain tech-tales.blog '_acme-challenge.tech-tales-alternative.blog
- Der DNS Eintrag wurde erfolgreich erzeugt.- Als nächstes verifiziert die CA, also Let’s Encrypt, die Domain. Das könnte ein bisschen dauern, antwortet aber schlussendlich hoffentlich mit
Success
.
Der DNS Eintrag selbst wird dann von acme.sh
automatisch wieder gelöscht, und der Zustand ist der gleiche wie vorher.
Profit
In ~/.acme.sh/*.tech-tales.blog
gibt es jetzt ein ca.cer
und ein fullchain.cer
File; diese beiden kann ich auf allen meinen Servern nutzen!
Addendum: Automatisches Deployment mit einem Renew Hook
Ich nutze im acme.sh
Befehl zusätzlich das Argument --renew-hook /path/to/some/script.sh
. Dadurch passiert das Folgende: Jedes Mal wenn das Zertifikat tatsächlich erneuert wird, wird das angegebene Skript anschließend ausgeführt. Ich nutze diesen Befehl, um das Skript überall zu deployen wo es benötigt wird.
Addendum: Die CA von Test auf Pro ändern
Let’s Encrypt empfiehlt, ihr Test-Environment zu nutzen (was passiert ist, per --server letsencrypt_test
), solange noch getestet wird. Das TLS Zertifikat das vom Test-Environment ausgestellt wird, wird von Browsern typischerweise nicht akzeptiert. Trotzdem sollte der Test-Server zuerst genutzt werden, weil der produktive Server Rate Limits definiert hat.
Der Wechsel auf den produktiven Server ist etwas schwierig, weil ich dafür den vollständigen Befehl noch einmal eingeben müsste. Ich habe aber eine etwas hacky Alternative gefunden:
- Navigiere nach
~/.acme.sh/*.tech-tales.blog
- In diesem Ordner gibt es die Datei
*.tech-tales.blog.conf
. - Und darin insbesondere eine wesentliche Zeile:
LE_API=https://acme-staging-v2.api.letsencrypt.org/directory
. Wechsle diese URL aufhttps://acme-v2.api.letsencrypt.org/directory
. Der Rest der Datei bleibt unverändert.
Beachte insbesondere dassLE_OrderFinalize
,LE_LinkOrder
undLE_LinkCert
nicht verändert werden müssen! - Führe jetzt den Befehl
acme.sh --renew --force *.tech-tales.blog
aus, beachte hier insbesondere--force
. Dadurch wird das Zertifikat neu ausgestellt, diesmal von der korrekten CA.