Generates and keeps up-to-date your Spring Boot applications' Let's Encrypt or other ACME compliant SSL certificates.

Overview

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, especially if it is small pet application. This library solves these problems by managing certificate lifecycle directly in Java code with the help of awesome Acme4j library.

Key features:

  1. Obtain Let's Encrypt certificate on fresh start (or from other ACME compliant certificate provider)
  2. Store generated keys and certificate into single KeyStore (server.ssl.keystore)
  3. Renew Let's Encrypt certificate (it watches for certificate expiration date and updates it to new before old is expired)
  4. 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)

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.3'
}
Maven:
<repositories>
     <repository>
         <id>jitpack.ioid>
         <url>https://jitpack.iourl>
     repository>
 repositories>

<dependencies>
   <dependency>
      <groupId>com.github.valb3r.letsencrypt-helpergroupId>
      <artifactId>letsencrypt-helper-tomcatartifactId>
      <version>0.2.3version>
   dependency>
dependencies>

For Jetty:

Gradle:
 allprojects {
     repositories {
         ...
         maven { url 'https://jitpack.io' }
     }
 }

dependencies {
   implementation 'com.github.valb3r.letsencrypt-helper:letsencrypt-helper-jetty:0.2.3'
}
Maven:
<repositories>
     <repository>
         <id>jitpack.ioid>
         <url>https://jitpack.iourl>
     repository>
 repositories>

<dependencies>
   <dependency>
      <groupId>com.github.valb3r.letsencrypt-helpergroupId>
      <artifactId>letsencrypt-helper-jettyartifactId>
      <version>0.2.3version>
   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:

  1. lets-encrypt-helper.domain the domain to issue certificate for
  2. lets-encrypt-helper.contact your contact for Let's Encrypt (i.e. your email in format mailto:[email protected])

4. Configure SSL as usual for Tomcat+TLS using server.ssl.keystore for certificate and keys storage

5. Ensure your security layer (i.e. Spring security) allows anonymous access to /.well-known/acme-challenge/* paths

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:[email protected])
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.store-cert-chain Store entire trust chain or only domain certificate (for browsers domain ceritificate is enough) true
lets-encrypt-helper.enabled Is the helper enabled true
lets-encrypt-helper.return-null-model If challenge endpoint should return null model (i.e. true is sane default for cases with Thymeleaf rendering the page) 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:[email protected] # 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 is located here

Alternative

The library is itself just 1 Java class. You can add library dependencies and:

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.

Comments
  • Order status invalid

    Order status invalid

    I get always this error org.shredzone.acme4j.exception.AcmeServerException: Order's status ("invalid") is not acceptable for finalization at finalizeOrder. Certbot with same ports as standalone works fine and Spring Boot App delivers at port 80. Any suggestions?

    bug 
    opened by bhoeferlin 5
  • Protocol org.apache.coyote.http11.Http11NioProtocol:443 has different KeyStore file

    Protocol org.apache.coyote.http11.Http11NioProtocol:443 has different KeyStore file

    I've been trying all day to try and get this working but I keep encountering the same issue. I've setup my application.properties file as below:

    server.port=443
    server.ssl.enabled=true
    server.ssl.protocol=TLS
    server.ssl.key-store=/path/to/custom/file.keystore
    server.ssl.key-store-type=pkcs12
    server.ssl.key-store-password=xxx
    server.ssl.key-alias=name
    
    lets-encrypt-helper.domain=xxx
    lets-encrypt-helper.contact=xxx
    

    When the application boots up it seems to get to:

        var sslConfig = Arrays.stream(protocol.findSslHostConfigs())
            .filter(it -> null != it.getCertificateKeystoreFile())
            .filter(it -> it.getCertificateKeystoreFile().contains(serverProperties.getSsl().getKeyStore()))
            .filter(it -> serverProperties.getSsl().getKeyStorePassword().equals(it.getCertificateKeystorePassword()))
            .findFirst()
            .orElse(null);
    

    And this method chain always returns null. I added the class file to my project, added additional logging and rebuilt and by printing out the value of the SSL host configs I get:

    Keystore file for _default_ (protocols TLSv1,TLSv1.3,TLSv1.2,SSLv2Hello,TLSv1.1) = null
    

    Where _default_ is the SSL host config getHostName(). I've followed all the steps verbatim from the readme but I'm unable to work out how to fix this problem. Do you have any idea whether additional configuration is needed? I even generated a dummy certificate with the matching alias name but it still produces a null keystore file.

    Edit

    Worth noting that this is Spring Boot 4.7.2

    Thanks

    bug 
    opened by Panallox 3
  • Certificate chain stored?

    Certificate chain stored?

    The issued certificate works great when using a browser, but it seems that some intermediate certificates are missing, this the certificate chain is not stored in the keystore. Could this be? I'm not that deeply familiar with the topic... When checking against openssl, I retrieve these issues:

    openssl s_client -connect www.example.com:443
    CONNECTED(00000005)
    depth=0 CN = www.example.com
    verify error:num=20:unable to get local issuer certificate
    verify return:1
    depth=0 CN = www.example.com
    verify error:num=21:unable to verify the first certificate
    verify return:1
    ---
    Certificate chain
     0 s:CN = www.example.com
       i:C = US, O = Let's Encrypt, CN = R3
    
    enhancement 
    opened by bhoeferlin 3
  • Anybody could help me?

    Anybody could help me?

    java.lang.NullPointerException: Cannot invoke "java.security.KeyStore$PrivateKeyEntry.getCertificate()" because "accountKeyEntry" is null
    	at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.updateCertificateAndKeystore(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:395) ~[letsencrypt-helper-tomcat-0.2.4.jar:na]
    	at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.executeCheckCertValidityAndRotateIfNeeded(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:336) ~[letsencrypt-helper-tomcat-0.2.4.jar:na]
    	at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.letsEncryptCheckCertValidityAndRotateIfNeeded(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:308) ~[letsencrypt-helper-tomcat-0.2.4.jar:na]
    	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
    
    opened by suchorski 0
  • subscriber agreement error -

    subscriber agreement error - "WARN lKnownLetsEncryptChallengeEndpointConfig : Please review carefully and accept TOS https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"

    I'm testing on a server with an already existing certificate from letsencrypt. However, the sample program cannot be run. I am attaching the log. ``:: Spring Boot :: (v2.3.4.RELEASE)

    2022-07-30 09:25:36.481 INFO 895693 --- [ main] example.SpringBootApp : Starting SpringBootApp on **** with PID 895693 (/home/alex/letsencrypt-helper-example-0.1.3-SNAPSHOT.jar started by root in /home/***) 2022-07-30 09:25:36.490 INFO 895693 --- [ main] example.SpringBootApp : No active profile set, falling back to default profiles: default 2022-07-30 09:25:39.248 INFO 895693 --- [ main] lKnownLetsEncryptChallengeEndpointConfig : KeyStore exists: /etc/letsencrypt/live/************/keystore.p12 2022-07-30 09:25:39.571 INFO 895693 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 443 (https) 80 (http) 2022-07-30 09:25:39.659 INFO 895693 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-07-30 09:25:39.660 INFO 895693 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.38] 2022-07-30 09:25:39.960 INFO 895693 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-07-30 09:25:39.964 INFO 895693 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3338 ms 2022-07-30 09:25:40.556 WARN 895693 --- [ificate Watcher] lKnownLetsEncryptChallengeEndpointConfig : Please review carefully and accept TOS https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf 2022-07-30 09:25:40.608 WARN 895693 --- [ificate Watcher] lKnownLetsEncryptChallengeEndpointConfig : Failed updating KeyStore

    java.lang.NullPointerException: null at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.updateCertificateAndKeystore(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:395) ~[letsencrypt-helper-tomcat-0.2.4.jar!/:na] at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.executeCheckCertValidityAndRotateIfNeeded(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:336) ~[letsencrypt-helper-tomcat-0.2.4.jar!/:na] at com.github.valb3r.letsencrypthelper.tomcat.TomcatWellKnownLetsEncryptChallengeEndpointConfig.letsEncryptCheckCertValidityAndRotateIfNeeded(TomcatWellKnownLetsEncryptChallengeEndpointConfig.java:308) ~[letsencrypt-helper-tomcat-0.2.4.jar!/:na] at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]` The library and its functionality is what I need. I would love to resolve any issues.

    enhancement 
    opened by yarrou 1
  • Instructions/code on how to redirect http to https would be helpful

    Instructions/code on how to redirect http to https would be helpful

    Hi! This is a useful project, thanks!

    Instructions/code on how to redirect http to https would be helpful especially given that this is for small pet projects. I've been able to apply it to my pet project and now I don't have this 301 https redirect. Googling gave me too many ways and it's interesting what would be the best way for spring-boot.

    enhancement 
    opened by metaruslan 1
  • Explicitly store LE account ID

    Explicitly store LE account ID

    Due to some issues on LE side it is useful to be able to access LE accountID in unencrypted way for diagnostics (to prevent future issues): Example issue as motivation (it does not affect this lib)

    Hello,
    
    Please immediately renew your TLS certificate(s) that were issued from
    Let's Encrypt using the TLS-ALPN-01 validation method and the following
    ACME registration (account) ID(s):
    
     111111111  22222222 
    
    We've determined that an error made it possible for TLS-ALPN-01
    challenges, completed before today, to not comply with certificate
    issuance requirements. We have remediated this problem and will revoke
    all unexpired certificates that used this validation method at 16:00 UTC
    on 28 January 2022. Please renew your certificates now to ensure an
    uninterrupted experience for your site visitors.
    
    We apologize for any inconvenience this may cause. If you need support
    in the renewal process, please comment on our forum post. Our staff and
    community members are available to help:
    

    ID 111111111 should be accessible for diagnostics

    enhancement 
    opened by valb3r 0
Releases(0.2.5)
循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Batch、Spring Cloud、Spring Cloud Alibaba、Spring Security & Spring Security OAuth2,博客Spring系列源码:https://mrbird.cc

Spring 系列教程 该仓库为个人博客https://mrbird.cc中Spring系列源码,包含Spring Boot、Spring Boot & Shiro、Spring Cloud,Spring Boot & Spring Security & Spring Security OAuth2

mrbird 24.8k Jan 6, 2023
A library to create, read and validate ZUGFeRD compliant invoices. Available for Java and .NET

Konik ZUGFeRD Library Is an easy to use open source implementation of the ZUGFeRD data model including various enhancements. Features Easy and underst

Konik 42 Dec 20, 2022
Decipher-pad - Encrypt and secure your text files with Decipher Pad!

Welcome to Decipher Pad ?? Encrypt and secure your text files with Decipher Pad! Table of Contents About The Project Tech Stack Prerequisites Developm

Md Ausaf Rashid 4 Feb 24, 2022
A joint research effort for building highly optimized Reactive-Streams compliant operators.

reactive-streams-commons A joint research effort for building highly optimized Reactive-Streams compliant operators. Current implementors include RxJa

Reactor 350 Dec 23, 2022
Two Spring-boot applications registering themselves to an spring-boot-admin-server application as separate clients for the purpose of monitoring and managing the clients

Spring-boot-admin implementation with 1 Server and 2 clients Creating a Server application to monitor and manage Spring boot applications (clients) un

null 6 Dec 6, 2022
This project uses the artificial potential field method to realize the path planning of the robot, and completes the trajectory optimization through other settings. It can also be combined with laser SLAM, target recognition and other technologies for path planning.

FRCAutoDriver 项目说明 Project Instruction 本项目利用人工势场法,实现机器人的路径规划,并通过其他设置完成轨迹优化,还可以结合激光SLAM、目标识别等技术进行路径规划 This project uses the artificial potential field

ZhangzrJerry 2 Sep 9, 2022
Keep up to date with your legal speedrunning mods!

ModCheck Keep up to date with your legal speedrunning mods! If you are just starting out, you can use this to download all legal mods! Or, you can use

Meera 2 Apr 10, 2022
Fall is an app that lets your phone scream if you throw it somewhere.

Fall Fall is an app that lets your phone scream if you throw it somewhere. License Copyright (C) 2022 Gh05t-1337 This program is free software: you ca

null 15 Oct 31, 2022
Spring Boot Login and Registration example with MySQL, JWT, Rest Api - Spring Boot Spring Security Login example

Spring Boot Login example with Spring Security, MySQL and JWT Appropriate Flow for User Login and Registration with JWT Spring Boot Rest Api Architect

null 58 Jan 5, 2023
Generates a Proguard mapping file for use in obfuscating your Java projects.

Reaper Generates a Proguard mapping file for use in obfuscating your Java projects. Features Automatically checks for duplicate names. Interactive, in

Nox 12 Dec 29, 2022
Restler is a library that automatically generates a client for a web service at run time, by analyzing the respective annotated Spring controller interface

Restler Overview Restler is a library that automatically generates a client for a web service at run time, by analyzing the respective annotated Sprin

Excelsior LLC 29 Oct 24, 2022
Create your Java crypto trading bot in minutes. Our Spring boot starter takes care of exchange connections, accounts, orders, trades, and positions so you can focus on building your strategies.

Quick Start | Documentation | Discord | Twitter Create and run your java crypto trading bot in minutes Our Spring boot starter takes care of exchange

Cassandre 442 Jan 3, 2023
Android Application for a user’s favorite Movies, TV shows and Anime while keeping up to date with the latest releases.

MovieDroid Native Android Application for organized and categorized list of a user’s favorite movies and TV shows while keeping up to date with the la

PEC ACM CSS 20 Dec 26, 2022
The Spring Boot Sample App on K8S has been implemented using GKE K8S Cluster, Spring Boot, Maven, and Docker.

gke-springboot-sampleapp ?? The Spring Boot Sample App on K8S has been implemented using GKE K8S Cluster, Spring Boot, Maven, and Docker. Usage To be

KYEONGMIN CHO 1 Feb 1, 2022
A library that automatically generates and manages configuration files based on classes.

sc-cfg SC-CFG is a simple, yet powerful library that automatically generate configuration files based on your classes. Compatible with Java 8+ and Kot

null 10 Nov 28, 2022
Just-In-Time Access is an AppEngine application that lets you manage just-in-time privileged access to Google Cloud projects.

Just-In-Time Access Just-In-Time Access is an AppEngine application that lets you manage just-in-time privileged access to Google Cloud projects. Syno

Google Cloud Platform 36 Jan 3, 2023
This project is a backend that lets you create to-do lists.

PROJECT This project is a backend service developed for the todo application. Stack Technologies Java 16 Spring Boot Spring Security Spring Data JPA L

Murat Akbıyık 2 Jun 3, 2022
about learning Spring Boot via examples. Spring Boot 教程、技术栈示例代码,快速简单上手教程。

Spring Boot 学习示例 Spring Boot 使用的各种示例,以最简单、最实用为标准,此开源项目中的每个示例都以最小依赖,最简单为标准,帮助初学者快速掌握 Spring Boot 各组件的使用。 Spring Boot 中文索引 | Spring Cloud学习示例代码 | Spring

纯洁的微笑 28.3k Jan 1, 2023
spring boot 实践学习案例,是 spring boot 初学者及核心技术巩固的最佳实践。另外写博客,用 OpenWrite。

推荐工具: 微信公众号 Markdown 编辑器 - OpenWrite:Markdown 微信编辑器是一款专业强大的微信公众平台在线编辑排版工具,提供手机预览功能,让用户在微信图文 、文章、内容排版、文本编辑、素材编辑上更加方便。 - 更多介绍 博客群发平台 一、支持泥瓦匠 Spring Boot

泥瓦匠BYSocket 15.2k Jan 5, 2023