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/1.23.0
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:
- it could be that the server_name is not defined or there's a typo
- pay attention to http vs. https and redirects; if you get redirected from http to https and this is not what you want, redirect could be done by some proxied app (for example wordpress might do this via its WP_HOME and WP_SITEURL variables) and then the request will happen to 443 port on which nginx will serve the first vhost that is listening on this port and the server_name matches, so if your b.example.com vhost does not listen on 443 as well you might get the configuration from some other vhost which does listen on 443 which will confuse you.
- Also listen directive gives precedence to IP:PORT than to only PORT, so nginx might serve for example wrong certificates (i.e. self-signed ones) if there is a config like
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
- nginx/1.23.1
The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key
Tested on
- nginx/1.23.1
- Debian 10 Buster