SSL & Ngnix: no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking

Solution 1:

My guess is that you have another server listening on port 443. This server has no ssl_certificate defined, and it's automatically selected (SNI). Try to delete all symbolic links from /etc/nginx/sites-enabled except this one server you want to make work (if that's possible, otherwise check all of your servers for listening to 443 without being configured correctly).

Solution 2:

I fixed this same problem earlier this morning, so I'm here to clarify C.A's point (which, now that I understand the problem, was well made), you most likely have two server blocks:

# default
server {
    listen 443 default_server; # Note the lack of `ssl`
    server_name _;
    #...
}

#real site
server {
    listen 443 ssl;
    server_name ;
    #...
}

SNI will only match on those that are labelled with an ssl listener. However, the default server will grab all incoming traffic on 443, regardless of SSL or not. Hence, it's actually preveting SNI from actually working at all, right off the bat, by hoarding all of the traffic for itself.

Symptoms:

  • It will seem like nginx isn't loading your config (even with an nginx -t and a service reload)
  • Errors stating "no ssl_certificate found in server block"
  • nginx is just applying your host to the default 443 listener.

Solutions:

I fixed the problem this morning by removing the default server block, hence allowing SNI to match on SSL listeners.

Alternative solution would be to add the ssl listener and the ssl_certificate lines to the server block so that SNI is essentially enabled on your default host. You'll still get SSL errors, so it's not the best solution, but it'll let your SNI work :)


Solution 3:

You need to define a single default_server parameter in the nginx config.

Apply default_server on either example.com or www.example.com. Not both.

Hence this will work:

server {
    listen 443 ssl;
    listen 80;

    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 80 default_server;

    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl default_server;

    server_name www.example.com;
    root /var/www/example.com/public;
    index index.php index.html index.nginx-debian.html;

    ssl on;
    ssl_certificate /etc/ssl/chain.crt;
    ssl_certificate_key /etc/ssl/examplecom.key;

    (rest of your nginx config goes here....)
}

Note on virtual hosts: Make sure the default_server parameter is not defined anywhere else - if you have multiple hosts on the server.