Von Let’s Encrypt zu Actalis

nocci

Zertifikatskrimi mit NPMplus

Es gibt Tage, da möchte man eigentlich nur „mal eben“ ein paar SSL-Zertifikate umstellen. Nichts Großes. Kein Infrastrukturdrama. Kein nächtliches Logfile-Yoga. Einfach statt Let’s Encrypt künftig die kostenlosen ACME-Zertifikate von Actalis nutzen. Klingt nach einer Sache von zehn Minuten.

Natürlich lachte irgendwo im Maschinenraum bereits ein Container.

Die Ausgangslage war eigentlich sauber: NPMplus läuft im Docker-Container, die Daten liegen brav unter /opt/npmplus, im Container gemountet als /data. In der compose.yaml wurden die passenden Actalis-Werte eingetragen:

ACME_SERVER=https://acme-api.actalis.com/acme/directory
ACME_EAB_KID=...
 ACME_EAB_HMAC_KEY=...
 ACME_PROFILE=none

So weit, so ordentlich. NPMplus startete, Certbot wurde auf Actalis losgelassen, und dann kam unter anderem auch dieser Gruß aus der Unterwelt:

Not enough quota

Ein Fehler, der klingt, als hätte man beim Zertifikatsautomaten zu viele Knöpfe gedrückt. Tatsächlich stellte sich heraus: Alte Renewal-Dateien zeigten noch auf Let’s Encrypt. Die Bestandszertifikate hatten ihre Vergangenheit nicht losgelassen. In den Certbot-Renewal-Dateien stand außerdem noch:

server = https://acme-v02.api.letsencrypt.org/directory

Also: alte Certbot-Konfigurationen raus, Actalis rein, Container neu starten. Kurz sah alles gut aus. Ich hab dann vorher noch was rum gewurstelt.
Dann war "auf einmal" der Renewal-Ordner leer. Ups.
Wie, den sollte ich gar nicht löschen? 👀

Das brachte NPMplus in eine kleine Identitätskrise. Die Datenbank kannte noch Zertifikate wie npm-1, npm-15 oder npm-38, aber die passenden Dateien unter live/ waren bereits Geschichte.

Nginx war entsprechend wenig begeistert:

cannot load certificate "/data/tls/certbot/live/npm-1/fullchain.pem"

Also wurden Dummy-Zertifikate gebaut, damit NPMplus überhaupt wieder starten konnte. Kein Schmuckstück, aber ein solider Feuerwehrschlüssel.
Naja... nach dem Neustart des Containers war der dann auch wieder da. Hui.
(PS, macht diesen Fehler einfach nicht....)

Danach begann der eigentliche Actalis-Teil. Die Dokumentation sprach von EAB-KID, HMAC-Key und einem Certbot-Aufruf mit --nginx. In NPMplus passt das aber nicht direkt, denn dort läuft Certbot mit Webroot. Also wurde manuell getestet:

certbot certonly \
  --server https://acme-api.actalis.com/acme/directory \
  --eab-kid "..." \
  --eab-hmac-key "..." \
  --webroot \
  -w /data/tls/certbot/acme-challenge \
  -d cyber77.de

Und siehe da: Mit dem vermeintlichen „1-Tages-Key“ funktionierte es. Noch schöner: Das Zertifikat war gar nicht nur einen Tag gültig, sondern ganz normal bis September. Der Name des Keys war also ungefähr so hilfreich wie ein Straßenschild mit „irgendwo links“. (Es gibt einen 1-Jahres- und einen 1-Tages-Key... ratet, welchen ich vorher dauernd versucht hatte)

Nachdem auch das erledigt war, kam als Zugabe noch ein herrlich unspezifisches:

Internal server error

An diesem Punkt ist man versucht, dem Server eine Tasse Tee hinzustellen und ihn zu fragen, ob er darüber reden möchte.

Die entscheidende Spur lag dann in /etc/certbot.ini. NPMplus nutzte standardmäßig ECDSA mit secp384r1. Manuell hatte es funktioniert, über NPMplus aber nicht. Also wurde auf zunächst auf RSA und letztendlich auf ecdsa umgestellt:

- "ACME_KEY_TYPE=ecdsa"
- "ACME_KEY_SIZE=secp256r1"

Container neu erstellt, Zertifikat erneut angefordert, und plötzlich war Ruhe im Maschinenraum:

Successfully received certificate.
Certificate is saved at: /data/tls/certbot/live/npm-65/fullchain.pem
This certificate expires on 2026-09-17.

Der Browser bestätigte anschließend freundlich nicht nur irgendein Zertifikat, sondern den finalen kleinen Sieg:

Actalis Domain Validated TLS Server ECC CA 2025
Actalis S.p.A.
EC 256 bits

Damit war klar: RSA war nur der Umweg mit Warnweste, nicht das Ziel. Der eigentliche Sweet Spot war ecdsa mit secp256r1, also ECDSA P-256. secp384r1 hatte sich noch verhalten wie ein Türsteher mit schlechter Laune, RSA funktionierte als Fallback, aber P-256 ging dann sauber durch.

Und weil man nach so einer Reise natürlich nicht einfach glaubt, was ein einzelnes Browserfenster erzählt, ging es danach zu SSL Labs. Ergebnis: A+.

Das Setup steht damit jetzt ziemlich ordentlich da:

Actalis ACME
ECDSA P-256 / EC 256 bits
TLS 1.3
HSTS
SSL Labs A+
OCSP-Stapling: successful

Auch OCSP-Stapling ließ sich erfolgreich prüfen:

OCSP Response Status: successful (0x0)
Responder Id: Actalis Domain Validated TLS Server ECC CA 2025 OCSP Responder
Cert Status: good

Das war dann der Moment, in dem aus „Warum hasst mich ACME?“ endlich „Okay, das sieht sogar richtig gut aus“ wurde.

Noch eine kleine Performance-Nebenquest gab es auch. Auf dem Proxmox-Host zeigte openssl speed, warum ECDSA P-256 nicht nur hübsch modern klingt, sondern auch praktisch sinnvoll ist:

RSA-2048 sign/s:       2213.3
RSA-4096 sign/s:        318.4
ECDSA P-384 sign/s:    5438.8
ECDSA P-256 sign/s:   64362.1

Anders gesagt: ECDSA P-256 war beim Signieren auf dieser Hardware rund 29-mal schneller als RSA-2048 und ungefähr 200-mal schneller als RSA-4096. Für einen Webserver, der viele neue TLS-Handshakes sieht, ist das kein kosmetischer Unterschied, sondern eine kleine CPU-Urlaubsreise.

Sicherheitlich ist P-256 für normale TLS-Webdienste absolut solide. RSA-2048 bleibt ein brauchbarer Fallback, RSA-4096 ist eher der schwere Tresor, den man unnötig durchs Treppenhaus trägt. P-384 wäre kryptografisch stärker, war in dieser Actalis/NPMplus-Kombination aber der zickige Pfad. P-256 war am Ende die gute Mischung aus modern, schnell, kompatibel und tatsächlich funktionierend.

Damit war der Umstieg geschafft. Nicht direkt, nicht elegant, aber am Ende mit einem sehr sauberen Ergebnis.

Browser Screenshot: Ausgestellt für  Allgemeiner Name (CN) <Gehört nicht zum Zertifikat>  Organisation (O) <Gehört nicht zum Zertifikat>  Organisationseinheit (OU) <Gehört nicht zum Zertifikat>  Ausgestellt von  Allgemeiner Name (CN) Actalis Domain Validated TLS Server ECC CA 2025  Organisation (O) Actalis S.p.A.  Organisationseinheit (OU) <Gehört nicht zum Zertifikat>  Gültigkeitsdauer  Ausgestellt am Mittwoch, 17. Juni 2026 um 15:45:42  Gültig bis Donnerstag, 17. September 2026 um 15:44:42

Die Kurzfassung für alle, die sich den Logfile-Pullover nicht selbst stricken wollen

Für NPMplus mit Actalis funktionieren die relevanten Compose-Werte am Ende ungefähr so:

- "ACME_EMAIL="
- "ACME_SERVER=https://acme-api.actalis.com/acme/directory"
- "ACME_EAB_KID=dein-funktionierender-kid"
- "ACME_EAB_HMAC_KEY=dein-funktionierender-hmac"
- "ACME_PROFILE=none"
- "ACME_KEY_TYPE=ecdsa"
- "ACME_KEY_SIZE=secp256r1"
- "ACME_OCSP_STAPLING=true"

Wichtig: Bei den Actalis-EAB-Credentials funktionierte hier ausgerechnet der vermeintliche „1-Tages-Key“. Das Zertifikat selbst war trotzdem ein normales 90-Tage-Zertifikat. Der Name dieses Keys ist also eher ein Nebelwerfer als eine hilfreiche Beschriftung.

Falls CAA-Records gesetzt sind, muss Actalis in der jeweiligen DNS-Zone erlaubt werden:

CAA 0 issue "actalis.it"

Für Wildcard-Zertifikate zusätzlich:

CAA 0 issuewild "actalis.it"

Nicht actalis.com, sondern actalis.it.

Und ganz wichtig: Alte Let’s-Encrypt-Renewal-Dateien lassen sich nicht magisch in Actalis-Zertifikate verwandeln. Bestehende Zertifikate müssen sauber neu erstellt werden. Wer dabei zu motiviert in /data/tls/certbot aufräumt, darf eventuell Bekanntschaft mit fehlenden fullchain.pem-Dateien und beleidigtem Nginx machen.