acme.sh¶
Siehe auch
- Verwandte Artikel
- Offizielle Dokumentation
- Linuxfabrik
acme.sh ist ein mit Bash, dash und sh kompatibles ACME-Shell-Skript, das eine vollständige Implementierung des ACME-Protokolls bietet. Es unterstützt ECDSA-, SAN- und Wildcard-Zertifikate und kommt ohne Python-Abhängigkeiten daher. Es benötigt keinen root/sudoer-Zugang.
Installation¶
email='root@example.com'
curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online \
--home /opt/acme.sh \
--config-home /etc/acme.sh \
--cert-home /etc/acme.sh/certs \
--accountemail "$email" \
--accountkey /etc/acme.sh/account.key \
--accountconf /etc/acme.sh/account.conf \
--no-cron
Dabei können folgende Fehler ignoriert werden (es versucht, UPGRADE_HASH in der config zu speichern - das wird sowieso beim nächsten Update gemacht):
touch: cannot touch '/root/.acme.sh/account.conf': No such file or directory
grep: /root/.acme.sh/account.conf: No such file or directory
grep: /root/.acme.sh/account.conf: No such file or directory
sh: line 2249: /root/.acme.sh/account.conf: No such file or directory
grep: /root/.acme.sh/account.conf: No such file or directory
Neues Zertifikat ausstellen¶
Achtung
Das Let’s Encrypt API hat gewisse Rate-Limits, es empfiehlt sich also, die Konfiguration zuerst mithilfe von curl oder gegen die staging environment zu testen. Vor allem bei „Failed Validation“ sind die Limits sehr niedrig, man wird schon bei 5 Fehlschlägen pro Account, pro Hostname und pro Stunde gesperrt.
DOMAIN=www.example.com
Die von uns favorisierte Variante ist die Erstellung per Webroot. Diese stoppt den Webserver nicht, benötigt aber auf dem Webserver oder Reverse Proxy eine Konfiguration.
Am Beispiel des Apache: Config für den Webroot anlegen (unterhalb von /etc/httpd/conf.d oder passend):
Alias /.well-known/acme-challenge/ /var/www/html/letsencrypt/.well-known/acme-challenge/
<Directory "/var/www/html/letsencrypt/">
AllowOverride None
Options None
Require method GET POST OPTIONS
</Directory>
Ein http-zu-https-Redirect in einem vHost sieht dann so aus:
<VirtualHost *:80>
ServerName www.example.com
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [redirect=301,last]
</VirtualHost>
Das Webroot-Verzeichnis für die Challenge-Antworten anlegen und eine Test-Datei hinterlegen
(die Ownership muss zum HTTPD-User passen - apache auf RHEL, www-data auf
Debian/Ubuntu):
# RHEL-based
install --directory --owner apache --group apache --mode 0755 \
/var/www/html/letsencrypt/.well-known/acme-challenge
# Debian/Ubuntu
install --directory --owner www-data --group www-data --mode 0755 \
/var/www/html/letsencrypt/.well-known/acme-challenge
echo 'it works' > /var/www/html/letsencrypt/.well-known/acme-challenge/index.html
curl http://$DOMAIN/.well-known/acme-challenge/index.html
# -> "it works"
Erst wenn die Test-Datei erreichbar ist, das Zertifikat ausstellen lassen. Für SAN-Namen
werden weitere --domain-Flags angehängt:
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --issue \
--domain "$DOMAIN" \
--webroot /var/www/html/letsencrypt \
--keylength 4096 \
--server https://acme-v02.api.letsencrypt.org/directory
Anschliessend die Zertifikats-Dateien an die gewünschten Pfade kopieren und den Reload-Hook setzen. Die Linuxfabrik-Konvention für die Zieldateinamen (aus der LFOps-Rolle):
# RHEL-based
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --install-cert \
--domain "$DOMAIN" \
--ca-file "/etc/pki/tls/certs/$DOMAIN-chain.crt" \
--cert-file "/etc/pki/tls/certs/$DOMAIN.crt" \
--fullchain-file "/etc/pki/tls/certs/$DOMAIN-fullchain.crt" \
--key-file "/etc/pki/tls/private/$DOMAIN.key" \
--reloadcmd "systemctl reload httpd"
# Debian/Ubuntu: paths /etc/ssl/certs and /etc/ssl/private, reload cmd
# "systemctl reload apache2"
Die Config wird in
/etc/acme.sh/certs/$DOMAIN/$DOMAIN.confgespeichert, dasLe_ReloadCmdist base64-encoded.install-certkann nur ein Target pro Aufruf setzen. Ein zweiter Aufruf überschreibt die zuvor hinterlegte Konfiguration.Bei einem erfolgreichen Renewal wird das hinterlegte
--reloadcmdautomatisch ausgeführt - der Webserver erkennt das neue Zertifikat ohne weiteres Zutun.
Die so abgelegten Zertifikate lassen sich direkt in Apache referenzieren:
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/www.example.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/www.example.com.key
SSLCertificateChainFile /etc/pki/tls/certs/www.example.com-chain.crt
Auf Debian/Ubuntu liegen die Dateien unter /etc/ssl/certs bzw. /etc/ssl/private:
SSLEngine on
SSLCertificateFile /etc/ssl/certs/www.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/www.example.com.key
SSLCertificateChainFile /etc/ssl/certs/www.example.com-chain.crt
Zertifikate mit acme.sh verwalten¶
Alle Kommandos unten gehen davon aus, dass acme.sh wie oben installiert wurde
(/opt/acme.sh als Home, /etc/acme.sh als Config-Home, --no-cron). Das
vereinfachende Shell-Alias, das der Installer per Default in ~/.bashrc ablegt, entfällt
beim Einsatz von --no-cron bzw. wird auf Nicht-Login-Sessions ohnehin nicht aktiv -
daher der vollständige Pfad in allen Beispielen.
Alle Zertifikate anzeigen lassen:
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --list
Renew einer Domain:
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --renew --domain "$DOMAIN"
Renew forcieren:
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --renew --domain "$DOMAIN" --force
acme.sh selbst auf den neuesten Stand bringen:
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --upgrade
Zertifikat löschen (anschliessend die Zertifikate von Hand aus den Zielpfaden entfernen und den Webserver reloaden):
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --revoke --domain "$DOMAIN"
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --remove --domain "$DOMAIN"
Automatisches Renewal per systemd-Timer¶
Die Linuxfabrik-Konvention (aus der LFOps-Rolle) ist ein wöchentlicher
systemd-Timer. Der Service macht vor jedem Renewal-Lauf ein Self-Upgrade von acme.sh
(ExecStartPre):
[Unit]
Description=acme.sh Service
[Service]
ExecStartPre=/opt/acme.sh/acme.sh --upgrade --home /opt/acme.sh --config-home /etc/acme.sh
ExecStart=/opt/acme.sh/acme.sh --cron --home /opt/acme.sh --config-home /etc/acme.sh
Type=oneshot
User=root
[Install]
WantedBy=basic.target
[Unit]
Description=acme.sh Timer
[Timer]
OnCalendar=Sun 01:17:00
Unit=acme-sh.service
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now acme-sh.timer
Der vom acme.sh-Installer angebotene --install-cronjob-Mechanismus wird bewusst nicht
verwendet, damit Service-Definition und Ausführungszeit über die oben gezeigten Unit-Dateien
reproduzierbar gepflegt werden.
Remote-Deployment per SSH¶
Soll ein frisch ausgestelltes Zertifikat nicht lokal, sondern auf einem anderen Host
installiert werden (typisch: ACME-Host in der DMZ, Webserver oder Loadbalancer im internen
Netz), nutzt acme.sh seinen --deploy --deploy-hook ssh-Mechanismus. Die Ziel-Hostparameter
kommen über Umgebungsvariablen:
DEPLOY_SSH_USER='root' \
DEPLOY_SSH_SERVER='proxy01.example.com' \
DEPLOY_SSH_CERTFILE='/etc/pki/tls/certs/www.example.com.crt' \
DEPLOY_SSH_KEYFILE='/etc/pki/tls/private/www.example.com.key' \
DEPLOY_SSH_FULLCHAIN='/etc/pki/tls/certs/www.example.com-fullchain.crt' \
DEPLOY_SSH_CAFILE='/etc/pki/tls/certs/www.example.com-chain.crt' \
DEPLOY_SSH_REMOTE_CMD='systemctl reload haproxy' \
/opt/acme.sh/acme.sh --config-home /etc/acme.sh --deploy \
--domain 'www.example.com' \
--deploy-hook ssh
Voraussetzung: SSH-Key-basiertes Login für den konfigurierten DEPLOY_SSH_USER auf dem
Zielhost. Die LFOps-Rolle setzt das Deployment bei definiertem
acme_sh__deploy_to_host automatisch um.
Troubleshooting¶
Siehe ACME und Let’s Encrypt, Abschnitt Troubleshooting. Dort sind die typischen ACME-Fehler unabhängig vom Client-Tool beschrieben (Rate-Limit, fehlgeschlagene Authorization, Port-80-Erreichbarkeit, nicht eingezogener Reload).