Table of Contents

, , ,

Nginx troubleshooting

upstream SSL certificate verify error: (21:unable to verify the first certificate) while SSL handshaking to upstream

Happened when connecting to upstream server using the self-signed certificate. Workaround can be to set proxy_ssl_verify nginx directive to off;

Better option is to add the correct certificates in the file pointed to by proxy_ssl_trusted_certificate directive. The file should contain in order, server.crt (and probably any intermediary cert if you have it) then rootCA, e.g.

/etc/ssl/certs/trusted_ca_cert.crt

-----BEGIN CERTIFICATE-----
...
server.crt data
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
rootCA cert data
...
-----END CERTIFICATE-----

Tested on

nginx seems to serve from wrong vhost?

When you visit one site let's say a.example.com and you get b.example.com, pay attention to following aspects:

listen 1.2.3.4:443 ssl;
server_name de_verticals_upstream;                                                                                                                                                                             
 
ssl_certificate     /etc/ssl/server.crt;                                                                                                                                                             
...

and somewhere else you have

...
listen 443 ssl;
...

Location matching when serving content

Remember that nginx will first match blocks defined with regular expressions(~ and ~*) and then serve prefix locations (/somelocation). Example config:

server { 
    # port 80 will be matched by default
    server_name example.org;
 
    location ~*/ {
        rewrite ^/(.*)$ https://www.example.org/$1 permanent;
    }
 
    # Letsencrypt challenge location
    location /.well-known {
      return 301 http://letsencrypt.example.org$request_uri;
    }
 
}

The request for https://www.example.org/.well-known will result in nginx serving the first location (one with the rewrite) because even though the second one is also evaluated, first one with regex also matches the /.well-known path. If it didn't match the second one would be served.

Solution to this would be to use either strict matching = or, in this letsencrypt example, a more valid modifier of ^~ which will stop regex processing and return immediately. So example would be:

   # Letsencrypt challenge location
    location ^~ /.well-known {
      return 301 http://letsencrypt.example.org$request_uri;
    }

So modifier priority matching is as follows:

1. `=`       Exact match, terminate immediately
2. `^~`      Longest-prefix-match (not regex!)
3. `~`, `~*` Regular expression case sensitive/insensitive
4. `/`       Longest-prefix-match

If you are using the grouping of URIs in parenthesis e.g.

location ^~ /(.well-known|pathA|otherslug)

This won't work. Use the `~*` modifier for that.

Tested on

See also

References