Placing the root certificate into the trust stores of systems, browsers, and applications such as Java and Python, understanding CA bundles, and verifying the chain with openssl verify using -CAfile and -untrusted.

In episode 4 you already had a private CA issuing certificates. However, a CA is useless if no one trusts it. This closing episode covers how to spread trust: installing the root certificate into the trust store, distributing the certificate chain, and verifying that everything works.
This episode's roadmap: installing the root into the Linux system trust store, understanding the behavior of Firefox and Chrome browsers, planting the root into applications such as Java and Python, assembling CA bundles, and verifying the chain with openssl verify. By the end of this episode you will be able to connect the entire series from beginning to end.
The system trust store is the list of CAs trusted by all processes on the machine. On Debian and Ubuntu, certificates are stored in /etc/ssl/certs and managed with update-ca-certificates:
sudo cp root-ca/certs/ca.cert.pem /usr/local/share/ca-certificates/
sudo update-ca-certificatesThe first command copies the root into the directory scanned by the system; the second updates the list of trusted certificates. After that, OpenSSL-based tools on that machine will trust certificates signed by your CA.
Verify the installation with sudo update-ca-certificates --verbose to see the latest status, then test the chain:
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
leaf/server.cert.pemAn OK output means the chain is trusted by the system. If an error appears, check whether the intermediate chain is complete.
Browsers have their own trust stores that do not always read the system trust store.
Firefox uses its own store. To trust the lab root, import it manually through Settings, open Privacy and Security, then the Certificates section, and choose Import to add the CA. In organizations, this import is usually automated through policy.
Chrome (and Chromium) uses the system trust store on Linux and macOS, so installing the root via update-ca-certificates is sufficient. On Windows and macOS, use the respective operating system store mechanism.
Info
Browsers are the strictest testers: most reject certificates without a SAN, reject roots installed the wrong way, and mark validity based on the system date. If the browser refuses to trust, check these three things before blaming the CA.
Java uses a cacerts file containing trusted roots for the JVM. Import the lab root with the keytool tool:
keytool -import -trustcacerts \
-alias lab-root -file root-ca/certs/ca.cert.pem \
-keystore $JAVA_HOME/lib/security/cacertsOn Java 9 and above, cacerts is stored in PKCS12 format. Use a descriptive alias so it is easy to manage when many roots are installed.
Python uses the certifi package, which provides its own CA bundle, and many HTTP libraries such as requests use it by default. To trust your CA, append the root to the certifi bundle:
cp $(python3 -m certifi) certifi-with-lab.pem
cat root-ca/certs/ca.cert.pem >> certifi-with-lab.pemThe combined bundle can be pointed to via the SSL_CERT_FILE variable or set directly in the application that uses requests. This approach is per-process, so it does not disturb other systems.
Servers using a leaf certificate usually need to send the full chain to clients, i.e. the leaf certificate combined with the intermediate:
cat leaf/server.cert.pem intermediate-ca/certs/intermediate.cert.pem \
> leaf/fullchain.pemSeveral terms to distinguish:
The order in the fullchain matters: the leaf certificate goes on top, then the intermediate below it.
Once everything is installed, test trust from the client side:
openssl verify -CAfile root-ca/certs/ca.cert.pem \
-untrusted intermediate-ca/certs/intermediate.cert.pem \
leaf/server.cert.pem-CAfile points to the trusted root, -untrusted provides the intermediate certificate that helps build the chain without needing to be trusted. An OK output means the leaf is trusted.
The most common case: verification fails because the intermediate is not included. Compare the two commands below:
openssl verify -CAfile root-ca/certs/ca.cert.pem leaf/server.cert.pem
openssl verify -CAfile root-ca/certs/ca.cert.pem \
-untrusted intermediate-ca/certs/intermediate.cert.pem \
leaf/server.cert.pemThe first command fails because the leaf was signed by an intermediate that cannot be found; the second succeeds because the chain is built completely. This explains why servers must always send the intermediate to clients.
In episode 5 you closed out the Learn PKI series: installing the root certificate into the trust stores of systems, browsers, and applications; assembling fullchain and CA bundles; and verifying the chain with openssl verify. You now have a personal CA that your environment truly trusts.
Key takeaways:
That concludes the six episodes of Learn PKI, from pre-requisites to trust distribution. Now it is your turn to practice the entire flow in your own lab, then try advanced challenges such as short-lived certificates, mTLS between services, or the post-quantum transition. Happy building your digital trust!