What is this
If you have ever tried getting Let’s Encrypt certificate for Spring Boot application, you know that it is painful as it involves using either CertBot or Docker-sidecar/Cron-job to manage certificate lifecycle. This library solves these problems by managing certificate lifecycle directly in Java code with the help of awesome Acme4j library.
Key features:
- Obtain Let’s Encrypt certificate on fresh start
- Store generated keys and certificate into single KeyStore (
server.ssl.keystore
) - Renew Let’s Encrypt certificate (it watches for certificate expiration date and updates it to new before old is expired)
- No JVM restart needed when certificate gets updated
Application requirements
To perform HTTP-01 ACME (Automatic Certificate Management Environment) challenge, the application must listen on port 80
, this library will automatically create
Tomcat connector to this port, so the only thing needed on your side is to open 80
port for the application.
Servlet containers supported (embedded)
- Tomcat
- Jetty
Usage
From JitPack maven repository
1. Import this library:
For Tomcat:
Gradle:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.valb3r.letsencrypt-helper:letsencrypt-helper-tomcat:0.2.4'
}
Maven:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.valb3r.letsencrypt-helper</groupId>
<artifactId>letsencrypt-helper-tomcat</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
For Jetty:
Gradle:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.valb3r.letsencrypt-helper:letsencrypt-helper-jetty:0.2.4'
}
Maven:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.valb3r.letsencrypt-helper</groupId>
<artifactId>letsencrypt-helper-jetty</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
2. Declare on your configuration
Tomcat:
@Import(TomcatWellKnownLetsEncryptChallengeEndpointConfig.class)
Jetty:
@Import(JettyWellKnownLetsEncryptChallengeEndpointConfig.class)
3. Define following properties in your application configuration or environment:
lets-encrypt-helper.domain
the domain to issue certificate forlets-encrypt-helper.contact
your contact for Let’s Encrypt (i.e. your email in formatmailto:john.doe@example.com
)
4. Configure SSL as usual for Tomcat+TLS using server.ssl.keystore
for certificate and keys storage
Configuration
Property | Description | Default value, if any |
---|---|---|
server.ssl.key-store | Path to the KeyStore, where Let’s Encrypt certificates and account key are to be stored (or are already there) | |
server.ssl.key-store | KeyStore type (i.e. PKCS12) | |
server.ssl.key-store-pasword | Password for KeyStore with Let’s Encrypt certificate and account key | |
server.ssl.key-alias | Let’s Encrypt certificate key alias in the keystore | |
server.port | Port (secure SSL/TLS) on which your application is deployed | |
lets-encrypt-helper.domain | Your applications’ domain (i.e. example.com) | |
lets-encrypt-helper.contact | The contact of person responsible for the domain (i.e. mailto:john@example.com) | |
lets-encrypt-helper.account-key-alias | Account key alias | letsencrypt-user |
lets-encrypt-helper.letsencrypt-server | Let’s Encrypt server to use | acme://letsencrypt.org |
lets-encrypt-helper.key-size | Certificate and Account key RSA key size | 2048 |
lets-encrypt-helper.update-before-expiry | Start trying to update certficate this time before expiration | P7D (7 days) |
lets-encrypt-helper.busy-wait-interval | Busy wait interval for thread that checks if the certificate is valid | PT1M (1 minute) |
lets-encrypt-helper.account-cert-validity | Validity duration for Account key | P3650D (3650 days) |
lets-encrypt-helper.enabled | Is the helper enabled | true |
lets-encrypt-helper.development-only.http01-challenge-port | For development only, port for HTTP-01 ACME challenge | 80 |
Example configuration
Launch your application with -Dspring.profiles.active=ssl
application-ssl.yaml
:
server:
port: 443
ssl:
key-store: file:/home/user/letsencrypt/application-keystore # Path to KeyStore with certificates and keys
key-store-password: change-me # Password for KeyStore protection
key-store-type: PKCS12
key-alias: tomcat # Certificate name in KeyStore
enabled: true # Important to place this explicitly
lets-encrypt-helper:
domain: my-domain.example.com # Domain to issue certificate for
contact: mailto:john.doe@mymail.example.com # Your contact for Let's Encrypt
Note: On your server ensure you have opened port 80
for Java (i.e. in Firewall) and Java can bind to it (i.e. follow Linux allow listening to low port without sudo to open ports 80,443 for java
)
Example project with SSL and Let’s Encrypt management using this library for Tomcat is located here
Alternative
The library is itself just 1 Java class. You can add library dependencies and:
- For Tomcat this java file to your configuration
- For Jetty this java file to your configuration
Testing locally
The library has integration tests in:
directories. One can adapt these tests according to own needs, as they use Pebble - LetsEncrypt testing server.