Welcher Weg passt?
- Reverse Proxy davor: nginx, Apache oder Caddy übernehmen TLS, die Java-Anwendung läuft intern auf HTTP. Das ist meist der einfachste Weg, Zertifikate und Erneuerung bleiben beim Proxy. Eine passende Konfiguration erzeugt der TLS-Konfigurationsgenerator.
- Tomcat oder Spring Boot direkt: sinnvoll ohne Proxy, etwa bei kleinen Diensten oder Containern. Dafür ist dieser Artikel.
Das Zertifikat holen
Let's Encrypt prüft per HTTP-01 auf Port 80 oder per DNS-01. Läuft auf Port 80 nichts, geht es mit certbot im Standalone-Modus, sonst mit Webroot oder DNS. Die passenden Befehle liefert der ACME-Helfer. Danach liegen die Dateien unter /etc/letsencrypt/live/example.com/:
cert.pem,chain.pem,fullchain.pem: Zertifikat, Zwischenzertifikat und beides zusammenprivkey.pem: der private Schlüssel. certbot erzeugt seit Version 2.0 standardmäßig ECDSA-Schlüssel.
Die Rechte-Falle
Die Verzeichnisse live und archive sind nur für root lesbar. Tomcat und Spring Boot laufen aber als eigener Benutzer und bekommen „Permission denied“. Statt die Rechte aufzuweichen, kopiert ein Deploy-Hook die Dateien nach jeder Erneuerung an einen Ort, den die Anwendung lesen darf:
#!/bin/sh # /etc/letsencrypt/renewal-hooks/deploy/tomcat.sh (ausführbar machen) for f in cert.pem chain.pem fullchain.pem privkey.pem; do install -o tomcat -g tomcat -m 0600 "$RENEWED_LINEAGE/$f" /opt/tomcat/conf/tls/$f done systemctl restart tomcat
Tomcat mit PEM-Dateien
Tomcat 9, 10 und 11 lesen PEM direkt, ein Keystore ist nicht nötig. In conf/server.xml:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true" maxParameterCount="1000">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig protocols="TLSv1.2+TLSv1.3">
<Certificate certificateFile="conf/tls/cert.pem"
certificateKeyFile="conf/tls/privkey.pem"
certificateChainFile="conf/tls/chain.pem" />
</SSLHostConfig>
</Connector>
Über certificateChainFile liefert Tomcat das Zwischenzertifikat mit aus. Ohne Neustart lädt Tomcat das Zertifikat über den Manager neu: /manager/text/sslReload. Dafür braucht der Benutzer die Rolle manager-script.
Spring Boot mit SSL-Bundle
Ab Spring Boot 3.1 beschreibst du Zertifikate als SSL-Bundle. Ab 3.2 lädt Spring Boot sie bei Änderungen selbst neu, der Neustart im Hook entfällt:
server.port=8443 server.ssl.bundle=web spring.ssl.bundle.pem.web.keystore.certificate=file:/opt/app/tls/fullchain.pem spring.ssl.bundle.pem.web.keystore.private-key=file:/opt/app/tls/privkey.pem spring.ssl.bundle.pem.web.reload-on-update=true
Bei Spring Boot 2.7 und 3.0 gibt es noch keine Bundles, aber PEM geht trotzdem:
server.ssl.certificate=file:/opt/app/tls/fullchain.pem server.ssl.certificate-private-key=file:/opt/app/tls/privkey.pem
Ältere Versionen: Keystore erzeugen
Ältere Tomcat- oder Spring-Boot-Versionen brauchen einen Keystore. Der Hook erzeugt ihn dann bei jeder Erneuerung neu:
openssl pkcs12 -export -in "$RENEWED_LINEAGE/fullchain.pem" -inkey "$RENEWED_LINEAGE/privkey.pem" \ -name tomcat -out /opt/app/tls/keystore.p12 -passout pass:geheim
server.ssl.key-store=file:/opt/app/tls/keystore.p12 server.ssl.key-store-type=PKCS12 server.ssl.key-store-password=geheim server.ssl.key-alias=tomcat
Im Browser geht dasselbe mit dem Java-Keystore-Helfer: Zertifikat und Schlüssel einfügen, als PKCS#12 speichern.
Port 443 ohne root
Java sollte nicht als root laufen und darf deshalb keine Ports unter 1024 öffnen. Üblich ist, die Anwendung auf 8443 zu starten und 443 per Firewall weiterzuleiten:
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
Alternativ AmbientCapabilities=CAP_NET_BIND_SERVICE in der systemd-Unit. Danach mit dem SSL-Check prüfen, ob Kette und Protokolle stimmen, und den Server in die Zertifikats-Ablaufübersicht aufnehmen.
FAQ
Muss ich nach jeder Erneuerung Tomcat neu starten?
Bei Tomcat ja, oder du nutzt sslReload im Manager. Spring Boot ab 3.2 mit reload-on-update lädt geänderte Dateien selbst.
Geht Let's Encrypt auch für interne Server?
Ja, mit der DNS-01-Prüfung. Der Server muss dafür nicht aus dem Internet erreichbar sein, nur ein TXT-Eintrag im öffentlichen DNS ist nötig.
Tomcat meldet „Cannot recover key“ oder „keystore password was incorrect“.
Kennwort des Keystores und des Schlüssels unterscheiden sich, oder der Alias stimmt nicht. Bei PKCS#12 müssen beide Kennwörter gleich sein.
Funktioniert ein ECDSA-Schlüssel mit Java?
Ja, alle aktuellen Java-Versionen unterstützen ECDSA. Für sehr alte Clients kann certbot mit --key-type rsa ein RSA-Zertifikat holen.