Android doesn't trust the certificate

I have created a certificate for with Let’s Encrypt, and it seems to be working fine in Chrome, Firefox and Safari on Mac, but not on Android v. 6.0.1 on Nexus 5. It shows all the URLs as untrusted. Any help please?

The same issue with another domain -

URLs to check:

How the links look like on Android:

1 Like

Hi csbubbles,

Some days ago, i resolved this issue by adding the SSLCertificateChainFile to my apache vhost, i use these settings:

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/domain.tld/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.tld/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain.tld/chain.pem

I hope it helps.

EDIT: changed fullchain.pem to chain.pem (thanks to Osiris)


The SSLCertificateChainFile “should” only contain chain.pem :wink:

If you’re using Apache version 2.4.8 or higher, you can use fullchain.pem (which is a concatenation of cert.pem and chain.pem) in the SSLCertificateFile directive. In that case you won’t need SSLCertificateChainFile, which is deprecated since that version.

Looking at it’s indeed a problem with your server as @F0x06 suggested: you’re not sending the intermediate certificate. Please follow @F0x06 advice (combined with the info in my post above) to fix your server configuration.


Technically, some browsers cache intermediate certificates which they already saw on connections to other sites. Then these browsers typically don’t bother the missing intermediate certificate sent by the server but use their cached copy, and everything looks right. Only browsers which don’t have the cached certificate are out of luck, which happens typically if you don’t use that browser regularly. Then it looks as if that browser had a bug because your site can be visited by other browsers and perhaps a lot of people flawlessly.

1 Like

It looks like adding SSLCertificateChainFile worked… Thank a lot F0x06!

Just out of curiosity, how does this happen to solve the issue and why none of the desktop browsers needs this, but Chrome on Android only?

1 Like

See what wrote right before your post Android doesn't trust the certificate

Also, Microsoft’s browsers do this trick where they can go fetch intermediate certificates they think they might need using data fields in the certificates they do have. So you’re most likely to see problems with non-Microsoft browsers. This trick adds even more moving parts to the already very complicated process of setting up a working SSL / TLS connection and it has negative privacy implications (you visit site A, but your browser automatically asks site B for a certificate…) so don’t expect other companies to want to introduce this just to allow server operators to be lazier.

I don’t think it was a problem of caching. I didn’t have the certificate before utilizing Let’s Encrypt facilities so F0x06 on Android had nothing to cache earlier. And what Osiris suggested actually helped right away after I restarted Apache and refreshed the page on Nexus.

Anyway, thanks for trying to help. I actually a bit surprised that the community here is so alive and prompt. This is really great.

I suppose that would be nice if all this info was among the lines in “Getting Started” or something. So one would know about the potential issues right away and could take care of well-known ones. Maybe it’s already written somewhere, but I couldn’t figure it out on my own. I am not a network security guy, by the way, just needed to get SSL certificates for few domains, so I guess the other folks may bump into the same problem.

@csbubbles, this is the most common post-issuance problem (dozens of other people have had the same trouble), so I wonder where we could best explain this to people.

If (in Certbot) you’re using Apache and you use the Apache installer, it automatically sets the correct chain file. If you used certonly, the “Congratulations!” message should have pointed you to fullchain.pem instead of cert.pem. So, I’m wondering where users are getting the idea of just using cert.pem without chain.pem. Is it just the filename? Is there some of our documentation that refers to the cert without also mentioning the chain? Is there a clear place where our messages could be improved?

@schoen, I guess originally (at least in my case) it all comes from the tutorials online for how to manage the certificates in Apache. I have created and installed multiple certificates before on my own, and every time I used some article like this one - How to Create and Install an Apache Self Signed Certificate. Again, I am not a security engineer, and, honesty, I would prefer to know as little as possible about all this stuff, so I typically just follow some instructions online. Most of those that I saw approach Apache through SSLCertificateFile and SSLCertificateKeyFile parameters, not SSLCertificateChainFile. Let’s Encrypt’s “apache” mode doesn’t work with virtual hosts (for example, I host various domains on the same server, so I got several VirtualHost sections in httpd.conf file, and Let’s Encrypt tool doesn’t happen to understand that). So I had to use “certonly” and then just followed the steps to attach the certificate to a virtual host the same way I always had done before.

I see. In this case there is a pretty fundamental difference between a self-signed certificate and a non-self-signed certificate (which is exactly the problem): the self-signed certificate doesn’t have a chain and the CA-signed certificate does, which is what lets end-users trust the CA-signed certificate.

So I see the problem, but I’m not sure what we could do to discourage people from using tutorials that were written to cover the self-signed cert case. Maybe we could write to the authors of some such tutorials and ask them to add a note like “This advice only applies when using self-signed certs; if you got your cert from a CA, please consult a different tutorial”?

Note that it does work if you have the individual virtual hosts in separate files (but that's not everyone's configuration).

@schoen You know, I can tell you from my user experience. I opened the Getting Started page and followed what is written there. I’ve tried --apache first, it didn’t work for me because of all the virtual hosts being kept in the same file. Then I tried --webroot and something didn’t work for me either for some reason. Then I used certonly, and it did create certificates. But after that you need to go and manually configure Apache (or whichever web server you use). I guess that would be nice if on the same page you guys provided examples of how to configure most popular web servers after the user got the certificate. If you added such a section in Getting Started, people would not hit this kind of issues. And you could refer them to those examples if they missed those. I suppose it’s just that document could’ve been improved to cover such typical scenarios.

Longer term: Maybe Apache can be taught to warn users about this mistake?

If it sees that the specified certificate is signed by some other certificate and no chain is provided, it could warn that this may be a configuration mistake.

Self-signed certs wouldn’t trigger this (so no annoying warning for them)

Mozilla and/or the BRs oblige public CAs to not issue from their root, so an intermediate will always be needed (there may be old certs this isn’t true for, but not new ones) and so it’s OK to warn for almost all non-self-signed cases.

It seems as though web servers will need to learn to inspect the contents of the certificates they serve anyway, to implement things like OCSP stapling sensibly, so they might as well warn the administrator about goofs like missing intermediates, or the use of certificates which have already expired or don’t match the configured name.


@csbubbles, thanks for the explanation! That Getting Started page definitely doesn’t discuss how to use the cert that’s issued with certonly; it just says it “will obtain a single cert” (and then doesn’t mention the chain, probably then encouraging people to use outside tutorials to learn how to install or configure it). I can see where the page could use improvement.

1 Like

Just for help:

In NodeJS, configure your httpserver with:

    var privateKey = fs.readFileSync('path/to/your/private-key.pem'), 'utf8');
    var certificate = fs.readFileSync('path/to/your/cert.pem', 'utf8');

    // this is so important. Many tutorials forget to include chain.pem
    var ca = fs.readFileSync('path/to/your/chain.pem', 'utf8');

    var credentials = { 
        key: privateKey, 
        cert: certificate,
        ca: ca

    httpsServer = https.createServer(credentials, yourExpressInstance);

That is incorrect.

It should be

{ key: privateKey
, cert: certificate + chain
, ca: null

In node.js the ca option is used for peer authentication (in the https server) and non-authoritative root ca validation (as a client request). Don’t worry about it. You don’t need to know anything about those, unless you do - and when you do, you generally know that you do.

The issue is that the chain must be concatenated after the certificate.

Also, you can prove this to be the case (or not) if you use openssl for debugging:

openssl s_client -showcerts -connect -servername

You will see whether or not the cert and intermediate (chain) are both present and lead to a valid Root CA.

1 Like

use fullchain.pem rather than using cert.pem as certificate.
i tested in nginx. it’s working.

I can confirm that it worked!