Import Certificate into Java cacerts on Ubuntu, Debian, RHEL, Rocky Linux

Import a CA or TLS certificate into Java cacerts on Ubuntu, Debian, RHEL, and Rocky Linux with keytool -importcert: locate cacerts, use a copy for safe testing, default password changeit, and distro-specific system trust paths.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

Import certificate into Java cacerts on Linux banner with distro paths and keytool command

You need Java to trust a corporate root, lab CA, or TLS intercept certificate. The JDK default truststore is cacerts, and keytool is the standard tool to add entries — but the file location and update mechanism differ between Debian-family and RHEL-family Linux.

This guide shows how to find cacerts on Ubuntu 26.04 (tested live), documents the equivalent paths on Debian, RHEL, and Rocky Linux from official sources, and imports a certificate into a copy of cacerts so you do not break the system bundle. For why a custom truststore is often better than editing the live file, read Custom Java truststore vs cacerts.

Tested on: Ubuntu 26.04 LTS; OpenJDK 25.0.3; kernel 7.0.0-27-generic. RHEL and Rocky paths documented from Red Hat and man-page sources (not live-tested here).


Default cacerts facts

Before you edit anything, confirm these defaults match your JDK package — most Linux OpenJDK builds use the same values:

Property Value
Keystore type Check with keytool -list -cacerts -storepass changeit; many Debian-family Java cacerts files report JKS, while new Java keystores default to PKCS12
Default password changeit (unless your admin or vendor changed it)
Entry type after import trustedCertEntry
Import command keytool -importcert

Install keytool on Ubuntu (or your distro’s java-*-openjdk-devel package) before running the commands below.


Ubuntu and Debian: locate cacerts

On Debian-family distros, $JAVA_HOME/lib/security/cacerts is usually a symlink to the distro-managed bundle. Resolve the JDK that owns your keytool binary and inspect where it points:

bash
KEYTOOL=$(readlink -f "$(command -v keytool)")
JAVA_HOME=$(dirname "$(dirname "$KEYTOOL")")
ls -la "$JAVA_HOME/lib/security/cacerts"
text
lrwxrwxrwx 1 root root 27 Apr 26 15:14 /usr/lib/jvm/java-25-openjdk-amd64/lib/security/cacerts -> /etc/ssl/certs/java/cacerts

The symlink confirms the JDK reads /etc/ssl/certs/java/cacerts, not a private copy under /usr/lib/jvm.

If several JDK versions are installed, list every cacerts path:

bash
find /usr/lib/jvm -name cacerts
text
/usr/lib/jvm/java-25-openjdk-amd64/lib/security/cacerts

Each result should resolve to the same /etc/ssl/certs/java/cacerts file on a single-JDK host. The real file is owned by the ca-certificates-java package, so package upgrades can refresh it from the distro CA bundle.


RHEL and Rocky Linux: locate cacerts (documented)

On RHEL-family systems, Java trusts the system-wide store at /etc/pki/java/cacerts, maintained by update-ca-trust. Typical OpenJDK packages expose it through a symlink:

text
/usr/lib/jvm/java-<version>/lib/security/cacerts  ->  /etc/pki/java/cacerts

Exact JDK directory names vary (java-17-openjdk, java-21-openjdk, etc.). After installing OpenJDK, confirm the canonical path and any JVM symlinks:

bash
find /usr/lib/jvm -name cacerts 2>/dev/null
ls -la /etc/pki/java/cacerts

You should see /etc/pki/java/cacerts as a regular file (not a broken symlink) and one or more JDK paths pointing at it. Red Hat build of OpenJDK documentation references /etc/pki/java/cacerts as the global trust anchor repository. For CAs that every Java app on the host should trust, copy PEM files to /etc/pki/ca-trust/source/anchors/ and run update-ca-trust extract instead of manual keytool edits on the live file.


Safe lab import: copy cacerts first

WARNING
Editing /etc/ssl/certs/java/cacerts or /etc/pki/java/cacerts directly normally requires root and affects all JVMs that read that file. Back it up and prefer distro trust tools or a custom truststore.

Never practice on the production symlink target without a backup. Work on a copy so a typo cannot break every JVM app on the host:

bash
mkdir -p ~/cacerts-lab
cd ~/cacerts-lab
cp /etc/ssl/certs/java/cacerts cacerts-copy

cacerts-copy is a private truststore file you can delete when the lab ends. On this tested Ubuntu host, keytool -list reports Keystore type: JKS.

Import a PEM-encoded root CA with -importcert (replace root-ca.crt with your file):

bash
keytool -importcert -alias labroot-test -file root-ca.crt \
  -keystore cacerts-copy -storepass changeit -noprompt
text
Certificate was added to keystore

keytool stored the CA as a trustedCertEntry under alias labroot-test.

Confirm the new entry and note the SHA-256 fingerprint for your change ticket:

bash
keytool -list -alias labroot-test -keystore cacerts-copy -storepass changeit
text
labroot-test, Jul 2, 2026, trustedCertEntry,
Certificate fingerprint (SHA-256): FF:AB:35:9A:78:4D:E2:E9:3E:44:33:D0:05:42:E2:2A:C3:9E:5E:79:EB:88:23:DE:9C:7F:17:3F:8F:74:30:7A

The entry type trustedCertEntry confirms this is a trust anchor, not a private key.

Remove the test entry from your copy when the lab ends:

bash
keytool -delete -alias labroot-test \
  -keystore cacerts-copy \
  -storepass changeit -noprompt

See Change alias, password, delete for more keystore maintenance commands.

Point one JVM at your copy instead of the system file. Use the store type reported by keytool -list -keystore cacerts-copy; on this tested Ubuntu host it was JKS:

bash
java -Djavax.net.ssl.trustStore=$HOME/cacerts-lab/cacerts-copy \
     -Djavax.net.ssl.trustStorePassword=changeit \
     -Djavax.net.ssl.trustStoreType=JKS \
     -jar your-app.jar

Only this process loads cacerts-copy; other Java apps on the host keep using the untouched system bundle.

Compare entry count with the untouched system file:

bash
keytool -list -cacerts -storepass changeit | head -6
text
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 121 entries

debian:ac_raiz_fnmt-rcm.pem, Jul 2, 2026, trustedCertEntry,

The system store on this host held 121 public CAs. Your copy should report one additional entry after import.


Import methods by distro goal

Pick the path that matches how widely the CA must be trusted — one app, every Java process on the host, or a quick local test:

Goal Ubuntu / Debian RHEL / Rocky Linux
One Java app trusts a private CA Custom trust.p12 + javax.net.ssl.trustStore Same
All Java apps on the host update-ca-certificates / ca-certificates-java refresh update-ca-trust extract
Quick local experiment Copy cacerts, keytool -importcert on copy Copy /etc/pki/java/cacerts, import on copy
Remove a bad import Restore from package: sudo apt install --reinstall ca-certificates-java update-ca-trust extract after removing anchor PEM

Ubuntu/Debian host-wide CA trust

For Ubuntu/Debian host-wide CA trust, place a PEM certificate with a .crt extension under /usr/local/share/ca-certificates/ and run:

bash
sudo cp corp-root.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

This updates the OS trust store. With ca-certificates-java installed, Debian-family systems can also refresh the Java truststore through package hooks, but verify /etc/ssl/certs/java/cacerts afterward with keytool -list -cacerts -storepass changeit.

NOTE
Inside containers, do not assume the host /etc/ssl/certs/java/cacerts path exists or is shared. Use the image's JDK path, build a custom truststore into the image, or mount one at runtime. See Java truststore in Docker and Kubernetes.

Common errors

These messages appear most often when importing into cacerts or a copy of it:

Error Cause Fix
Public keys in reply and keystore don't match Importing a signed leaf onto wrong alias Use -importcert for CA certs only in cacerts; see public keys mismatch fix
keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect Wrong -storepass Default is changeit unless your admin changed it
Certificate not imported, alias <name> already exists Duplicate alias Pick a unique -alias or delete the old entry with keytool -delete
Import succeeds but app still fails PKIX JVM not using your modified store Set -Djavax.net.ssl.trustStore to the file you edited

Production checklist

Before you edit a live trust bundle on a shared host, walk through this list:

  1. Prefer a dedicated PKCS12 truststore over editing live cacertscustom truststore guide.
  2. Use descriptive aliases (corp-root-2026, not cert1).
  3. Document SHA-256 fingerprints in your change ticket.
  4. On RHEL/Rocky, use update-ca-trust for host-wide CAs.
  5. On Ubuntu/Debian, let ca-certificates-java manage public CAs; add private CAs via custom truststore or /usr/local/share/ca-certificates/ + update-ca-certificates.
  6. Restart long-running JVM processes after truststore changes.

References


Summary

Java cacerts on Ubuntu and Debian lives at /etc/ssl/certs/java/cacerts, symlinked from $JAVA_HOME/lib/security/cacerts, with default password changeit. On RHEL and Rocky Linux the system file is /etc/pki/java/cacerts, exposed under /usr/lib/jvm/java-*/lib/security/cacerts. On the tested Ubuntu host, the distro cacerts file reports Keystore type: JKS. Import CAs with keytool -importcert -alias NAME -file cert.crt -keystore cacerts-copy -storepass changeit -noprompt on a copy first, then point your app with -Djavax.net.ssl.trustStore and matching -Djavax.net.ssl.trustStoreType. For production, favor a custom truststore, update-ca-certificates on Debian-family hosts, or update-ca-trust on RHEL-family hosts over editing the global bundle.


Frequently Asked Questions

1. What is the default cacerts password on Linux OpenJDK?

changeit on Ubuntu, Debian, RHEL, and Rocky Linux OpenJDK packages. Pass it with -storepass changeit or keytool will prompt interactively.

2. Where is cacerts on Ubuntu and Debian?

$JAVA_HOME/lib/security/cacerts is a symlink to /etc/ssl/certs/java/cacerts, maintained by ca-certificates-java. Use readlink -f on the JDK path or find /usr/lib/jvm -name cacerts to locate it.

3. Where is cacerts on RHEL and Rocky Linux?

/etc/pki/java/cacerts is the system Java truststore. JDK installs expose it through /usr/lib/jvm/java-*/lib/security/cacerts (often a symlink). Use update-ca-trust for system-wide CA additions.

4. Should I import directly into the live cacerts file?

For production, prefer a custom truststore or update-ca-trust on RHEL. For learning, copy cacerts to cacerts-copy, import there, and point -Djavax.net.ssl.trustStore at the copy. See java-custom-truststore-vs-cacerts.

5. What keytool command imports a CA certificate?

keytool -importcert -alias myca -file ca.crt -keystore cacerts-copy -storepass changeit -noprompt. Use a unique alias; list with keytool -list -keystore cacerts-copy -storepass changeit.

6. How do I verify the import worked?

keytool -list -alias myca -keystore cacerts-copy -storepass changeit shows trustedCertEntry and the SHA-256 fingerprint. Restart JVM applications so they reload the truststore file.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …