Nginx SSL certificate configuration - fullchain.pem vs cert.pem

Nginx SSL configuration - fullchain.pem vs cert.pem

Recently, I was setting up a nginx server, this nginx server is being used as a reverse proxy, to pass requests to backend servers.

The configuration file looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server {
listen 80;
server_name REPLACE_ME;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
server_name REPLACE_ME;

ssl_certificate /etc/letsencrypt/live/CERTIFICATE_FQDN/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/CERTIFICATE_FQDN/privkey.pem;

include ssl_enhance.conf;

access_log /var/log/nginx/REPLACE_ME.access.log main;
error_log /var/log/nginx/REPLACE_ME.error.log;

location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass BACKEND;

proxy_buffering off;
proxy_request_buffering off;
}
}

This configuration file works well, I can use my browser to connect to my backend servers through nginx.
But when I tried to use curl to fetch my site, warning message shows up, like this:

1
2
3
4
5
6
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Hmm, weird. Never see this message before. But where’s the problem?

I checked my browser, again. My browser works. I tried another server, same message appears.
After reading the warning, I thought maybe the problem is related to CA certificates that are storied in my computer.
I am using Let’s Encrypt for my SSL certs, so if I download a copy of their intermediate certificate, and put them into my computer, it would work, right?

No, it didn’t work.

What makes me more confused is, a friend of mine tried to curl the same address, there weren’t any warning message on his computer.

I can’t figure out why, until I take a look at the folder which Let's Encrypt stores certificate in.
There are four files in a folder, like this

1
2
3
4
- cert.pem
- chain.pem
- fullchain.pem
- privkey.pem

OK, I know chain.pem and privkey.pem, but what’s the difference between cert.pem and fullchain.pem?

1
2
fullchain.pem: This is the file contains both your certificate and intermediate certificates.
cert.pem: This is the file only contains your certificate.

The problem is, when nginx respond to a HTTPS request with configuration above, it would only send your certificate back to client.
And the client won’t be able to verify the certificate, because you don’t have that certificate installed on your computer.
What you have in your computer is a bunch of CA (certificate authorities). These CA is responsible for distributing certificates, and if your client have these CA, your computer can try to verify if the cert from the server is signed (distributed) by any CA in your computer.
But it didn’t always happen, sometimes your client won’t check, like above. So you need to provide more information about your certificates, so that’s why there’s the file fullchain.pem

Change this line

1
ssl_certificate /etc/letsencrypt/live/CERTIFICATE_FQDN/cert.pem;

to this.

1
ssl_certificate /etc/letsencrypt/live/CERTIFICATE_FQDN/fullchain.pem;

Restart your nginx server, then use curl to check again if it works this time.

If you encounter error related to X.509, changing the cert your web server provide may help. Just like above.