LinuxOpen Source SoftwareSecurityTLSTutorials

How to make Linux trust your own self-signed certificates

If you are working with self-signed SSL/TLS certificates, e.g. in your internal test or lab environment, the communication is well encrypted but you have another problem: The certificate cannot be verified.

Trusted certificates on Linux

In this tutorial we show how to add the self-signed certificate to your local list of trusted CA (Certificate Authorities) certificates.

Signed by unknown authority / Unable to get local issuer

This may lead to application issues when the application is communicating with your service with a self-signed certificate installed. For example when an application runs against an API with a self-signed certificate, the application might bail out with an error because the underlying operating system is not able to verify the certificate:

2024/04/15 02:08:02 ERROR : : error reading destination directory: RequestError: send request failed
caused by: Get "https://minio.lab.local:9000/backup?delimiter=%2F&encoding-type=url&max-keys=1000&prefix=bucket%2F": x509: certificate signed by unknown authority

In this example, an application wanted to access a locally installed Minio with a self-signed certificate – and the application refused to talk to the Minio server.

Depending on the application, the error may show a different error, for example:

unable to get local issuer certificate

The reason for these errors is that there was no local certificate found inside /etc/ssl/certs which would be at the top of the certificate chain and therefore used as certificate authority.

Manual verification with openssl

A manual verification can be done with the openssl command. The first few lines already reveal that the certificate runs into a verify error because a self-signed certificate was detected:

ck@linux:~$ openssl s_client -connect minio.lab.local:9000
CONNECTED(00000003)
depth=0 CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
verify return:1
---
Certificate chain
 0 s:CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
   i:CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
---
Server certificate
-----BEGIN CERTIFICATE-----
[...]

Further down in the output (after the certificate), a verification error is also showing up:

-----END CERTIFICATE-----
subject=CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH

issuer=CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1887 bytes and written 373 bytes
Verification error: self signed certificate
---
[...]

Add certificate to local CA certificates

If the certificate was created by a CA (even your own CA), the CA's certificate could be used and placed under /usr/local/share/ca-certificates with a .crt suffix. In this situation we have a self-signed certificate without a CA, meaning a standalone server certificate.

We can use the openssl command from before again to retrieve the server certificate:

ck@linux:~$ openssl s_client -connect minio.lab.local:9000
[...]
Server certificate
-----BEGIN CERTIFICATE-----
MIIEvzCCAyegAwIBAgIUPw06iGutptld4uLkf1GpkIL3yMYwDQYJKoZIhvcNAQEL
[...]
O/V6qxj2gECEuP4dcUiaWuioiA==
-----END CERTIFICATE-----
[...]

Copy the certificate (including the lines —–BEGIN CERTIFICATE—– and —–END CERTIFICATE—–) and create a new crt file in /usr/local/share/ca-certificates/, for example /usr/local/share/ca-certificates/minio.lab.local.crt.

Then run the update-ca-certificates command. This command should detect your newly added crt file and add it to the global list of CA certificates (in /etc/ssl/certs/ca-certificates.crt):

root@linux:~# update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

Now that you added the self-signed server certificate to the ca-certificates, any TLS connection to the server using this certificate should now be verified.

Did it work?

You can verify the difference with openssl, once again.

root@owiland:~# openssl s_client -connect minio.lab.local:9000
CONNECTED(00000003)
depth=0 CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
verify return:1
---
Certificate chain
 0 s:CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
   i:CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEvzCCAyegAwIBAgIUPw06iGutptld4uLkf1GpkIL3yMYwDQYJKoZIhvcNAQEL
[...]
O/V6qxj2gECEuP4dcUiaWuioiA==
-----END CERTIFICATE-----
subject=CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH

issuer=CN = *.lab.local, OU = Minio, O = Minio, L = Zurich, ST = Zurich, C = CH

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1887 bytes and written 373 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Server public key is 3072 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
[...]

As we can see from the output, the certificate verification for the self-signed certificate is now working.

Other use cases

Of course the same procedure can also be applied to other kinds of certificates. For example if you are running a very outdated Linux machine (which we hope you don't) or your Linux machine runs in an air-gapped (= no Internet access) environment, you might need to manually add (new) Root CA certificates to the list of ca-certificates.

Claudio Kuenzler
Claudio has been writing way over 1000 articles on his own blog since 2008 already. He is fascinated by technology, especially Open Source Software. As a Senior Systems Engineer he has seen and solved a lot of problems - and writes about them.

You may also like

Leave a reply

Your email address will not be published. Required fields are marked *

More in:Linux