57

I'm new to securing a server so I don't really know much about this but I need to get my Spring Boot Application that is running on a Digital Ocean Droplet to use HTTPS.

My idea is to register a letsencrypt certificate and then tell Spring to use that.

However, I have no idea how to do that.

Thanks.

BrandenS
  • 591
  • 1
  • 5
  • 7

8 Answers8

140

I wrote 2 blog posts about Let's Encrypt and Spring Boot.

  1. Issuing a certificate. Spring Boot Application Secured by Let’s Encrypt Certificate
  2. Renewing a certificate. Let’s Encrypt Certificate Renewal: for Spring Boot

In a nutshell, steps are as follows:

  1. Pulling the Let's Encrypt client (certbot).

  2. Generating a certificate for your domain (e.g. example.com)

    ./certbot-auto certonly -a standalone -d example.com -d www.example.com

Things are generated in /etc/letsencrypt/live/example.com. Spring Boot expects PKCS#12 formatted file. It means that you must convert the keys to a PKCS#12 keystore (e.g. using OpenSSL). As follows:

  1. Open /etc/letsencrypt/live/example.com directory.
  2. `openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root`
    

The file keystore.p12 with PKCS12 is now generated in /etc/letsencrypt/live/example.com.

It's time to configure your Spring Boot application. Open the application.properties file and put following properties there:

server.port=8443
security.require-ssl=true
server.ssl.key-store=/etc/letsencrypt/live/example.com/keystore.p12
server.ssl.key-store-password=<your-password>
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=tomcat

Read my blog post for further details and remarks.

Emad Van Ben
  • 1,578
  • 1
  • 10
  • 12
  • 1
    Awesome. I think this is pretty much how I finally got it going, but I had to pull from 2 or 3 different sources and bumble my way through it. This will make it much easier when I have to renew. – BrandenS Aug 11 '16 at 14:18
  • 2
    Do I have to use server.port: 8443 in production to? Or server.port: 80 is fine? – Vitor Vezani Jun 10 '17 at 01:35
  • Where can I find/define key-store-password? – Yigal Aug 13 '17 at 17:17
  • When you're performing the steps, you'll be asked to choose a password. Then you use that password for key-store-password. – Emad Van Ben Aug 14 '17 at 18:22
  • My application said "PKCS12 not found". So I created a `JKS` from the `PKCS12` and changed the keyStoreType to `JKS`. `keytool -importkeystore -destkeystore keys.jks -deststoretype pkcs12 -srckeystore keys.p12 -srcstoretype pkcs12` from https://pubs.vmware.com/view-50/index.jsp?topic=%2Fcom.vmware.view.installation.doc%2FGUID-06A2FF09-777C-44F0-B240-497E771379F3.html – Impulse The Fox Apr 04 '18 at 07:05
  • 6
    @EmadVanBen then every time let's encrypt renew the cert, I have to recreate the p12 manually? – JavierSegoviaCordoba Aug 15 '18 at 19:43
  • save me alot of time. tks. but i recommand to remove the `-a standalone` in step 2, and put key-store in classpath instead of original folder, like this: `server.ssl.key-store=classpath:keystore.p12` for who don't know that the classpath is the `src/main/resources` folder in the spring server – Kyo Huu May 16 '19 at 10:13
  • 2
    FYI, even if your password key not provided, it throws error you should add key-store-password even fi pass is empty – shareef Jul 16 '20 at 06:42
  • I'm using windows cmd and git bash command line, how would I execute the command in step 2? – lmngn23 Nov 06 '20 at 02:06
  • @EmadVanBen - Can you please update the links in the answer? None of them are working. – Nikhil Jun 20 '21 at 19:06
  • @Nikhil, it's fixed now. – Emad Van Ben Jun 21 '21 at 20:03
  • @EmadVanBen - Thanks! – Nikhil Jun 22 '21 at 05:24
  • install.rst -> -cerbot/cerbot/docs -> We used to have a shell script named ``certbot-auto`` to help people install Certbot on UNIX operating systems, however, this script is no longer supported. If you want to uninstall ``certbot-auto``, you can follow our instructions :doc:`here `. – Federico Galimberti Jun 19 '22 at 12:40
  • The guide needs to be updated as it is no longer valid. I hope the author wishes to update his splendid work. – Federico Galimberti Jun 19 '22 at 12:42
  • @FedericoGalimberti, thanks. I am willing to update my blog. Could you please let me know which instruction? – Emad Van Ben Jun 20 '22 at 13:07
  • Unfortunately certbot-auto no longer exists. I have tested your page with Ubuntu 22.04 LTS. I can't get a certificate. – Federico Galimberti Jun 21 '22 at 14:19
9

Step 1: Download certbot from git

You need to fetch the source code of Let's Encrypt on your server which your domain address is pointing to. This step may take a couple minutes.

$ git clone https://github.com/certbot/certbot

$ cd certbot

$ ./certbot-auto --help

Remark: Python 2.7.8 (or above) should be installed beforehand.

Step2: generates certificates and a private key

By executing following command in your terminal, Let's Encrypt generates certificates and a private key for you.

$ ./certbot-auto certonly -a standalone \

-d example.com -d example.com

Remark:Keys are generated in /etc/letsencrypt/live/example.com directory

Step3: Generate PKCS12 Files From PEM Files

To convert the PEM files to PKCS12 version: Go to /etc/letsencrypt/live/example.com convert the keys to PKCS12 using OpenSSL in the terminal as follows.

$ openssl pkcs12 -export -in fullchain.pem \

       -inkey privkey.pem \

           -out keystore.p12 \

       -name tomcat \

       -CAfile chain.pem \

       -caname root

Enter Export Password:

Verifying - Enter Export Password:

(Note:- Write single line at a time and press enter)

Step4: Configuration of Spring Boot Application

Open your 'application.properties' Put this configuration there.

server.port=8443 security.require-ssl=true

server.ssl.key-store=/etc/letsencrypt/live/example.com/keystore.p12

server.ssl.key-store-password= password

server.ssl.keyStoreType= PKCS12

server.ssl.keyAlias= tomcat

7

Another option is to use Spring Boot Starter ACME:

https://github.com/creactiviti/spring-boot-starter-acme

ACME (Automatic Certificate Management Environment) it the protocol used by LetsEncrypt to automatically issue certs.

okrunner
  • 3,083
  • 29
  • 22
  • This was good advice, but it is deprecated now (It does not support LetsEncrypts ACME API v2). Check https://letsencrypt.org/docs/client-options/ for other clients that are up to date! – Vanheden Oct 22 '22 at 18:19
2

For spring boot webflux the configuration of properties changed

server.port=443

server.ssl.enabled=true//the changed line
server.ssl.keyAlias=netty
server.ssl.key-store=path
server.ssl.key-store-password=password
server.ssl.keyStoreType=PKCS12
ahll
  • 2,329
  • 1
  • 19
  • 22
1

letsencrypt-tomcat queries and refreshes certs via Let's encrypt at runtime (no restarts needed).
It works with standalone and embedded Tomcat as well as Spring Boot.

It's packaged into a Docker image, allowing for easy reuse. The image contains:

  • dehydrated to manage certs via Let’s Encrypt,
  • tomcat-reloading-connector for hot reloading certs at runtime after renewal,
  • an init system (dumb-init) for properly handling tomcat and dehydrated processes,
  • an entrypoint script that starts up tomcat and dehydrated as well as
  • a pre-compiled version of Apache Portable Runtime (APR) and JNI wrappers for APR used by Tomcat (libtcnative), so tomcat delivers the best TLS performance possible.

Read this blog post to learn how to use it with your application and more about the technical details.

schnatterer
  • 7,525
  • 7
  • 61
  • 80
1

I've created a small library in pure Java that allows embedded Tomcat in Spring-Boot to obtain and keep Lets Encrypt certificate fresh automatically: Spring-Boot LetsEncrypt helper

It is just one Java file + dependencies on ACME4J/BouncyCastle, so that one can re-use it as a code

In short, it does the following:

  1. On application start it creates KeyStore as defined in your server.ssl properties if it does not exist yet (and adds self-signed expired cert there).
  2. Registers Tomcat connector on port 80 for HTTP-01 ACME challenge from LetsEncrypt
  3. Launches thread that checks if the certificate in KeyStore is outdated or missing
  4. If the certificate is outdated/missing it issues an order to LetsEncrypt and passes HTTP-01 ACME challenge on port 80.
  5. After passing the challenge it stores the certificate into KeyStore defined in server.ssl and issues reloadSslHostConfigs on Tomcat HTTPS enabled connector

With these steps, the entire LetsEncrypt certificate lifecycle from the issuing to update is covered within Java application itself without any non-Java 3rd parties

Valentyn
  • 171
  • 1
  • 5
0

I've had some trouble when exporting .pem to .p12, keytool was not recognizing file format. Here follows the command that worked for me after many searches:

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root -legacy -passout pass:changeit

After that, you'll have your file keystore.p12, so set the configs in application.properties like Emad Van Ben told before

Matheus Santz
  • 538
  • 6
  • 7
-1
  1. Get an SSL certificate from letsencrypt
  2. Add it into a keystore using the keytool command in Java
  3. Configure your Spring application to use the keystore generated above

The file should look like:

 server.port = 8443
 server.ssl.key-store = classpath:sample.jks
 server.ssl.key-store-password = secret
 server.ssl.key-password = password
AlBlue
  • 23,254
  • 14
  • 71
  • 91
  • Thanks! So I was kind of on the right track it looks like. Could anyone possibly elaborate on how i add that cert with keytool? – BrandenS May 02 '16 at 21:18
  • See the keytool help pages http://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html – AlBlue May 03 '16 at 22:55
  • Maybe [this tutorials](https://www.digitalocean.com/community/tags/let-s-encrypt?type=tutorials) can help. – JrBenito May 10 '16 at 19:33