acme.sh

Siehe auch

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>

Zum manuellen Testen per curl eine index.html anlegen:

mkdir -p /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

Danach per acme.sh das Zertifikat ausstellen lassen:

acme.sh --issue \
--domain "$DOMAIN" \
--webroot /var/www/html/letsencrypt \
--server https://acme-v02.api.letsencrypt.org/directory

acme.sh --install-cert \
--domain "$DOMAIN" \
--cert-file "/etc/pki/tls/certs/$DOMAIN.crt" \
--key-file "/etc/pki/tls/private/$DOMAIN.key" \
--fullchain-file "/etc/pki/tls/certs/$DOMAIN-fullchain.crt" \
--reloadcmd "systemctl reload httpd"

# Achtung: bei Debian-Systemen muss das reload-cmd auf "systemctl reload apache2" angepasst werden
  • Die Config wird in /etc/acme.sh/certs/$DOMAIN/$DOMAIN.conf gespeichert, das Le_ReloadCmd ist base64 encoded.

  • Man kann nur ein Target für install-cert setzen. Falls man es erneut ausgeführt, wird die alte Config überschrieben.

  • Wenn ein Zertifkat erneuert wurde, wird das --reloadcmd automatisch danach ausgeführt. Dadurch kann es sein, dass der Webserver mehrmals reloaded wird.

Die erhaltenen Zertifikate können dann so verwendet werden:

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-fullchain.crt

Auf Debian Systemen sieht die Config entsprechend so aus:

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-fullchain.crt

Zertifikate mit acme.sh verwalten

Standardmässig erweitert acme.sh die ~/.bashrc um folgenden Eintrag, wodurch ein alias mit den richtigen Variablen hinzugefügt wird:

. "/opt/acme.sh/acme.sh.env"

Alle Zertifikate anzeigen lassen:

acme.sh --list

Renew einer Domain:

acme.sh --home /opt/acme.sh --config-home /etc/acme.sh --domain "$DOMAIN" --renew

Renew forcieren:

acme.sh --renew --domain "$DOMAIN" --force

Zertifikat löschen (anschliessend die Zertifikate von Hand löschen und den Webserver reloaden):

acme.sh --revoke --domain "$DOMAIN"
acme.sh --remove --domain "$DOMAIN"

Automatisches Renewal per Cron:

acme.sh --install-cronjob

# creates something like this:
59 0 * * * "/opt/acme.sh"/acme.sh --cron --home "/opt/acme.sh" --config-home "/etc/acme.sh" > /dev/null

Automatisches Renewal per systemd-timer:

/etc/systemd/system/acme-sh.service
[Unit]
Description=acme.sh Service

[Service]
ExecStart=/opt/acme.sh/acme.sh --cron --home /opt/acme.sh --config-home /etc/acme.sh
Type=oneshot
User=root

[Install]
WantedBy=basic.target
/etc/systemd/system/acme-sh.timer
[Unit]
Description=acme.sh Timer

[Timer]
OnCalendar=Sun 01:17:00
Unit=acme-sh.service

[Install]
WantedBy=timers.target
systemctl enable --now acme-sh.timer

Built on 2024-04-18