Securing Spring Boot Apps with SSL Bundles: A Practical Guide
Learn how to configure SSL/TLS in Spring Boot 3.1+ using SSL Bundles.
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
- ✓Spring Boot 3.1 or later
- ✓Basic understanding of TLS/SSL and certificate management
- ✓Familiarity with application.properties or YAML configuration
- SSL Bundles simplify TLS configuration in Spring Boot 3.1+ by centralizing keystore/truststore setup.
- Use
server.ssl.bundleto reference a bundle instead of scattered properties. - Supports PKCS12, JKS, PEM, and reloadable certificates.
- Avoids common pitfalls like expired certs and missing intermediates.
- Production debugging requires checking bundle reload and truststore chain.
Think of SSL Bundles like a pre-assembled toolkit for securing your app's communications. Instead of manually wiring up certificates and keys (like finding the right key for a lock), you just tell Spring Boot 'use bundle A' and it handles the rest. If a certificate expires, you swap the bundle—no code changes.
If you've ever had to configure SSL/TLS in a Spring Boot app the old way—scattering server.ssl.key-store, server.ssl.key-password, server.ssl.trust-store across application.properties—you know the pain. It's error-prone, hard to maintain, and a nightmare when certificates expire. I've debugged countless production incidents where a misconfigured truststore brought down an entire microservice mesh.
Spring Boot 3.1 introduced SSL Bundles, a game-changer for TLS configuration. Instead of juggling half a dozen properties per connector, you define a named bundle once and reference it everywhere: embedded server, HTTP clients, messaging, whatever. It's cleaner, more consistent, and supports hot-reload of certificates.
This guide walks you through setting up SSL Bundles with real-world examples, common pitfalls, and a production debugging guide. By the end, you'll never go back to the old way.
What Are SSL Bundles?
SSL Bundles, introduced in Spring Boot 3.1, let you define TLS/SSL configuration in a centralized, reusable way. Instead of scattering keystore and truststore properties across your application, you create a named bundle in application.properties or application.yml and reference it wherever needed—embedded server, WebClient, RestTemplate, or messaging connectors.
- A keystore (your server certificate and private key)
- A truststore (CA certificates to validate peers)
- Both, or just one
You can define multiple bundles for different purposes: one for server-side TLS, another for outgoing HTTP calls, yet another for database connections. The bundle abstraction handles reloading when files change, so you can rotate certificates without restarting the JVM.
Here's the minimal setup for a server-side bundle using PKCS12 files:
Configuring SSL Bundles for the Embedded Server
The most common use case is securing your embedded Tomcat, Jetty, or Undertow server. With SSL Bundles, it's a two-step process: define the bundle, then reference it in server.ssl.bundle.
Let's create a bundle named server that uses a PKCS12 keystore and a separate truststore:
server.ssl.bundle and wonder why HTTPS wasn't working. The old server.ssl.key-store properties were still being picked up. Remove those legacy properties entirely when migrating to bundles.server.ssl.bundle to enable HTTPS. The server automatically uses the keystore and truststore from the bundle.Using SSL Bundles with WebClient and RestTemplate
Outgoing HTTPS calls also benefit from bundles. Instead of configuring SSLContext manually, you can inject a WebClient or RestTemplate that uses a bundle.
First, define a bundle for client-side TLS (often the same truststore but different keystore if mutual TLS is needed):
WebClient uses Netty by default, which requires a different SSL configuration than Apache HttpClient. Always test the actual client library's SSL integration.SslBundles to programmatically create SSL contexts for reactive clients. For RestTemplate, use SSLConnectionSocketFactory similarly.Hot-Reloading Certificates with Reloadable Bundles
One of the killer features of SSL Bundles is the ability to reload certificates without restarting the JVM. This is critical for zero-downtime certificate rotation.
To enable reloading, use the reloadable bundle type and set spring.ssl.bundle.reload-on-update=true. Then, you can trigger a reload by calling the Actuator endpoint POST /actuator/ssl or by updating the bundle files.
Example configuration:
cp instead of mv), the reload won't trigger. Use mv or touch the file after copy.What the Official Docs Won't Tell You
After deploying SSL Bundles across dozens of microservices, here are the gotchas that bit us:
1. Bundle names are case-sensitive and must match exactly. We once had server in properties but referenced Server in code—silent fallback to no SSL, and the app started on HTTP. No error, just no HTTPS.
2. The reloadable bundle type only supports PKCS12, not JKS. If you use JKS, you can't hot-reload. The docs mention this, but it's easy to miss. Convert to PKCS12 with keytool -importkeystore -srckeystore old.jks -destkeystore new.p12 -deststoretype PKCS12.
3. PEM bundles require the private key to be unencrypted. If your PEM key has a password, Spring Boot will fail to load it. Use openssl rsa -in encrypted.key -out decrypted.key to remove the password (but secure the file accordingly).
4. Truststore reload doesn't affect already-established connections. Only new connections will use the updated truststore. For long-lived connections (like database pools), you may need to restart the pool or the app.
5. The Actuator SSL endpoint only shows bundles after they've been loaded. If the bundle fails to load (e.g., wrong password), the endpoint returns an empty list. Check logs for SslBundleException.
6. Multiple bundles can't share the same keystore/truststore file if they require different reload triggers. Each bundle has its own file watcher. If two bundles point to the same file, only one watcher will fire. Use separate files or trigger reloads manually.
server.ssl.bundle is set, verify the bundle exists and log a warning if not.Migrating from Legacy SSL Properties
If you're already using server.ssl.key-store and friends, migration is straightforward but requires care. The old properties are deprecated in Spring Boot 3.1 and will be removed in a future version.
Steps: 1. Define a bundle with the same keystore/truststore settings. 2. Replace server.ssl.key-store etc. with server.ssl.bundle. 3. Remove all legacy server.ssl.* properties. 4. Test thoroughly—especially if you have multiple connectors (e.g., HTTP/2).
Here's a before/after example:
Testing SSL Bundle Configuration
Don't wait for production to discover your SSL config is broken. Write integration tests that verify bundles load correctly.
Spring Boot provides @SpringBootTest with auto-configured SslBundles. You can inject it and assert on bundle details:
@PostConstruct method that calls sslBundles.getBundle("server") and logs the certificate expiry. It's saved us from deploying expired certs.SslBundles catch misconfigurations early. Test both server and client bundles separately.The Midnight Certificate Chain Fiasco
spring.ssl.bundle.reload-on-update=true and a POST to /actuator/ssl.- Always include the full certificate chain (root + intermediates) in your truststore.
- Test certificate validation using openssl s_client before deploying.
- Enable SSL bundle reload in production to avoid restarts on cert rotation.
- Monitor certificate expiration and chain completeness with Actuator endpoints.
- Document the exact certificates in each bundle—don't rely on 'it worked before'.
keytool -list -keystore truststore.jks or openssl crl2pkcs7 to inspect the chain.openssl x509 -in cert.pem -noout -dates. Ensure spring.ssl.bundle.reload-on-update=true is set and the bundle files are updated.server.ssl.bundle. Test connectivity with curl -v https://localhost:8443 --cacert truststore.pem.management.endpoint.ssl.enabled=true and that the bundle has been loaded. Restart the application if necessary to force reload.keytool -list -keystore /etc/ssl/truststore.jks -storepass changeitopenssl s_client -connect example.com:443 -showcerts| File | Command / Code | Purpose |
|---|---|---|
| application.yml | spring: | What Are SSL Bundles? |
| WebClientConfig.java | @Configuration | Using SSL Bundles with WebClient and RestTemplate |
| Before vs After | server.ssl.key-store=classpath:keystore.p12 | Migrating from Legacy SSL Properties |
| SslBundleTest.java | @SpringBootTest | Testing SSL Bundle Configuration |
Key takeaways
reloadable bundles with PKCS12 for zero-downtime certificate rotation, and avoid sharing files across bundles.Interview Questions on This Topic
How do SSL Bundles improve TLS configuration in Spring Boot 3.1+?
Frequently Asked Questions
20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.
That's Spring Security. Mark it forged?
3 min read · try the examples if you haven't