Skip to main content

Linux certificate store: adding your own root CA

Security · 31.10.2026 · 5 min read
Illustration for “Linux certificate store: adding your own root CA”

When an internal service or a test environment uses a certificate from its own certificate authority, curl and system services answer "unable to get local issuer certificate". The solution is to add the root certificate to the system trust store. Below: where it lives on Debian, Ubuntu and the RHEL family, how to extend it and why some programs still do not trust it. SSH certificates work differently, see the article SSH certificates and your own CA.

Where the store lives

The system store consists of a directory for your files and a final bundle assembled by a dedicated command. Programs read the final bundle, so after copying a file you must run the command.

FamilyDirectory for your certificatesCommandFinal bundle
Debian, Ubuntu/usr/local/share/ca-certificates/update-ca-certificates/etc/ssl/certs/ca-certificates.crt
RHEL, AlmaLinux, Rocky/etc/pki/ca-trust/source/anchors/update-ca-trust/etc/pki/tls/certs/ca-bundle.crt

The ca-certificates package brings the list of publicly recognized certificate authorities. Your files are kept separately, and a package update does not erase them.

Adding a certificate on Debian and Ubuntu

You need the root certificate in PEM format (a text file with a BEGIN CERTIFICATE block) and with the .crt extension: files with another extension are skipped by the command. If you were given a .cer file in binary DER format, convert it first. The update-ca-certificates command should report that one certificate was added.

openssl x509 -inform der -in myca.cer -out myca.crt
openssl x509 -in myca.crt -noout -subject -dates
sudo cp myca.crt /usr/local/share/ca-certificates/myca.crt
sudo update-ca-certificates

To remove a certificate, delete the file and rebuild the bundle with the --fresh option.

sudo rm /usr/local/share/ca-certificates/myca.crt
sudo update-ca-certificates --fresh

Adding a certificate on the RHEL family

On AlmaLinux, Rocky Linux and other systems of this family the file goes into the anchors directory and you run update-ca-trust. The .crt extension and the PEM format work here too.

sudo cp myca.crt /etc/pki/ca-trust/source/anchors/myca.crt
sudo update-ca-trust

If you delete a file from anchors, run update-ca-trust again so that it disappears from the final bundle as well.

Checking the result

A curl request to the internal address should return a response code without complaints about the certificate, and the Verify return code line in openssl should show 0. If the error remains, examine the chain following the article How to check an SSL certificate.

curl -sS -o /dev/null -w "%{http_code}\n" https://internal.example.com/
openssl s_client -connect internal.example.com:443 -servername internal.example.com </dev/null 2>/dev/null | grep "Verify return code"

Why the system store does not always help

Many programs bring their own set of trusted authorities and do not read the system store. Typical cases:

  • Java uses the cacerts file and the keytool utility, so the certificate is imported for it separately;
  • Python with the requests library takes the bundle from the certifi package unless the REQUESTS_CA_BUNDLE variable is set;
  • Node.js contains a built-in list, and your own file is attached with the NODE_EXTRA_CA_CERTS variable;
  • Firefox and Docker containers keep their own stores.
curl --cacert myca.crt https://internal.example.com/
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/myca.crt
sudo keytool -importcert -alias myca -file myca.crt -keystore "$JAVA_HOME/lib/security/cacerts"

For a one-off call curl has the --cacert option. Do not disable verification with options like -k: it stops protecting the connection.

Caution: a root certificate means trust in everything

An added root certificate allows its owner to issue a certificate for any name, and the system will accept it as genuine. Add only your own authority or one you trust completely, and keep the private key in a safe place. A public site does not need its own authority: see the article on DV, OV and EV certificate types. Binding a certificate to DNS is covered in the article TLSA and DANE.

Frequently asked questions

Where is the certificate store in Ubuntu?

The final bundle is the file /etc/ssl/certs/ca-certificates.crt, and individual certificates are in the /etc/ssl/certs directory. Your own files go into /usr/local/share/ca-certificates/ and then you run update-ca-certificates. Do not edit the final bundle by hand: your changes disappear the next time the command runs.

How do I add a certificate to the trusted ones in Ubuntu?

Put the root certificate in PEM format with the .crt extension into /usr/local/share/ca-certificates/ and run sudo update-ca-certificates. The command reports that one certificate was added. After that curl and system services start accepting certificates issued by this authority without any extra options.

Why does curl trust the certificate while Java or Python does not?

These programs have their own stores or built-in sets of authorities. Java reads cacerts, Python with requests uses the certifi package, Node.js has a built-in list. Specify the certificate using the program's own means: through keytool or the REQUESTS_CA_BUNDLE and NODE_EXTRA_CA_CERTS variables.

Do I need to restart services after update-ca-trust?

The store is read when a process starts, so services that are already running may keep using the old bundle. Restart the services that call internal addresses over HTTPS and check the connection. New processes, such as curl, need no restart.

Was this article helpful?
← Back to Knowledge Base Ask Support