How to Use mkcert Certificates with Java Applications: A Complete keytool Integration Guide
Set the JAVA_HOME environment variable and run mkcert -install to automatically add the mkcert root CA to your Java trust store, then generate PKCS#12 bundles with mkcert -p12 for seamless TLS in JVM applications.
mkcert (FiloSottile/mkcert) generates locally-trusted development certificates by maintaining a private root Certificate Authority. When JAVA_HOME is properly configured, mkcert automatically integrates with the Java keytool utility to install this root CA into the system cacerts keystore, eliminating SSL handshake errors during local development without manual certificate management.
How mkcert Detects and Modifies the Java Trust Store
According to the mkcert source code in truststore_java.go, the tool detects Java installations by checking the JAVA_HOME environment variable. When present, mkcert locates the keytool binary and the cacerts file within $JAVA_HOME/lib/security/ (or the legacy jre subdirectory on older installations).
The integration relies on four core functions defined in the source:
checkJava(): Executeskeytool -listto verify if the mkcert root CA is already present by comparing SHA-1 or SHA-256 fingerprints of the stored certificates.installJava(): Builds and runs thekeytool -importcertcommand to addrootCA.pemusing the unique alias returned bycaUniqueName().execKeytool(): Handles command execution with automaticsudoescalation on Unix systems if permission is denied when writing to the system trust store.uninstallJava(): Removes the CA alias from the keystore when runningmkcert -uninstall.
The default keystore password is hard-coded as changeit in truststore_java.go (line 31), which mkcert uses both for importing the CA into the Java trust store and for protecting generated PKCS#12 files.
Installing the mkcert Root CA for Java
Before generating certificates for your applications, install the mkcert root CA into the Java trust store:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
mkcert -install
Internally, as implemented in installJava() at truststore_java.go#L81-L89, this executes the equivalent of:
keytool -importcert -noprompt \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit \
-file $(mkcert -CAROOT)/rootCA.pem \
-alias "mkcert development CA"
If checkJava() detects the CA fingerprint is already present in the keystore, the installation is skipped to avoid duplicate entries. The main.go file (lines 97-100) controls whether the Java trust store is touched based on environment detection.
Generating and Using Certificates in Java Applications
Once the root CA is trusted by the JVM, create certificates for your specific development domains.
Creating a PKCS#12 Bundle
Generate a certificate and private key packaged for Java consumption:
mkcert -p12 localhost 127.0.0.1 ::1
This produces localhost+3.p12 containing the leaf certificate and its private key, encrypted with the password changeit. This format is ready for direct use with Java's KeyStore API without additional conversion.
Loading the Keystore Programmatically
Load the PKCS#12 file in your Java application code:
import java.io.FileInputStream;
import java.security.KeyStore;
public class SslConfig {
public static KeyStore loadMkcertKeystore() throws Exception {
KeyStore ks = KeyStore.getInstance("PKCS12");
try (FileInputStream fis = new FileInputStream("localhost+3.p12")) {
ks.load(fis, "changeit".toCharArray());
}
return ks;
}
}
Configuring JVM SSL Properties
For servers like Spring Boot, Jetty, or Tomcat, pass the keystore via system properties without writing code:
java -Djavax.net.ssl.keyStore=localhost+3.p12 \
-Djavax.net.ssl.keyStorePassword=changeit \
-Djavax.net.ssl.keyStoreType=PKCS12 \
-jar application.jar
Adding the CA to Custom Client Trust Stores
For Java clients using isolated trust stores rather than the global cacerts file, manually import the root CA:
keytool -importcert -keystore client-truststore.jks \
-storepass changeit \
-file $(mkcert -CAROOT)/rootCA.pem \
-alias mkcert-root
Clients then reference this store with -Djavax.net.ssl.trustStore=client-truststore.jks to validate server certificates issued by mkcert.
Summary
- mkcert automatically integrates with Java when
JAVA_HOMEis set, as implemented intruststore_java.goand coordinated bymain.go. - The
checkJava()andinstallJava()functions manage root CA installation using keytool with the default passwordchangeit. - Use
mkcert -p12to generate PKCS#12 bundles compatible with Java'sKeyStore.getInstance("PKCS12")loader. - Both the generated keystores and the Java system trust store use the password
changeitby default. - The root CA PEM file is located at
$(mkcert -CAROOT)/rootCA.pemfor manual import scenarios.
Frequently Asked Questions
Does mkcert work with all Java versions and distributions?
Yes. mkcert detects any JDK or JRE through the JAVA_HOME environment variable and locates the cacerts file regardless of whether you use OpenJDK, Oracle JDK, or Amazon Corretto. The keytool command syntax has remained consistent since Java 8, and mkcert's execKeytool() function handles execution across platforms, ensuring compatibility from Java 8 through Java 21 and beyond.
What is the default password for mkcert-generated PKCS#12 files?
The default password is changeit. This value is defined as the storePass constant in truststore_java.go and is used both when mkcert creates the PKCS#12 bundle via the -p12 flag and when it imports the root CA into the Java trust store via installJava().
How do I remove the mkcert CA from my Java installation?
Run mkcert -uninstall with JAVA_HOME set to your JDK path. This triggers the uninstallJava() function in truststore_java.go, which executes keytool -delete to remove the CA alias from the cacerts keystore. Alternatively, manually run: keytool -delete -alias <ca-unique-name> -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit, replacing <ca-unique-name> with the output of mkcert -CAROOT inspection.
Can I use mkcert certificates inside Docker containers running Java?
Yes. Mount the generated PKCS#12 file into the container and pass it via JVM system properties, or copy the rootCA.pem into a custom trust store during the Docker build. Ensure the container's Java installation trusts the CA by importing it with keytool during image construction, or mount the host's modified cacerts file if the Java versions match exactly.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →