NGINX. How to configure a redirect without WWW to domain with Let's Encrypt SSL certificate (http/2)?

Good time.

Dumb question, but Google didn't resolve it (or "... either do not go skiing, or I'm weird"). Situation: bought a new VDS and decided to roll from the last 9 Debian x64. All updated, configured, got SSL from Let's Encrypt to domain. Set up NGINX (nginx/1.13.5), as follows (my battle config from another VDS):

server {
 listen 80;
 listen [::]:80;

 server_name example.com www.example.com;

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

server {
 listen 443 ssl http2;
 listen [::]:443 ssl http2;
 access_log off;

 server_name www.example.com;

 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 127.0.0.1 8.8.8.8;

 add_header Strict-Transport-Security "max-age=31536000";
 expires max;

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

server {
 listen 443 ssl http2;
 listen [::]:443 ssl http2;

 server_name example.com;

 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 127.0.0.1 8.8.8.8;

 add_header Content-Security-Policy "block-all-mixed-content";
 add_header Strict-Transport-Security "max-age=31536000";
 expires max;

 root /var/www/html/example.com;
 index index.html;

 include acme; # a file with the configuration file location / ... {..} for (re)generating SSL

 location / {
 try_files $uri $uri/ =404;
}
}

So the problem is that on my other VDS with Debian 8 – this config does correctly redirect:

And on the new Debian 9 – just gives a 404 error. What am I doing wrong?

P. S. I understand that Debian has nothing to do with it, but for some reason, stupid copy-paste is not working...
June 14th 19 at 20:37
2 answers
June 14th 19 at 20:39
Solution
Most likely the problem is that You have not copied some of the Nginx configs which define default_server.

View /etc/nginx/nginx.conf for include
For example:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;


For understanding how Nginx processes a request, you have to read it

For understanding the operation try_files read it

Also check for an index.html in /var/www/html/example.com, file ownership and rights.

Below one of the correct config options may be another option, to the point that server {} can do only 1 and pile up a bunch of if, but if it is evil and wrong.

server {
 listen XX.XX.XX.XX:80;
 server_name example.com;
 return 301 https://example.com$request_uri;
}
server {
 listen XX.XX.XX.XX:80;
 listen XX.XX.XX.XX:443 ssl http2;
 server_name www.example.com;
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 "ssl_session_cache" shared:SSL:50m;
 ssl_session_timeout 5m;
 ssl_dhparam /etc/nginx/ssl/dhparams.pem;
 ssl_prefer_server_ciphers on;
 ssl_session_tickets off;
 ssl_ciphers directives "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 resolver 8.8.8.8 8.8.4.4 valid=300s;
 resolver_timeout 5s;
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_trusted_certificate /etc/nginx/ssl/letsencrypt-ca.pem;
 ssl_stapling_responder http://ocsp.int-x3.letsencrypt.org;
 return 301 https://example.com$request_uri;
}
server {
 listen XX.XX.XX.XX:443 ssl http2;
 server_name example.com;
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 "ssl_session_cache" shared:SSL:50m;
 ssl_session_timeout 5m;
 ssl_dhparam /etc/nginx/ssl/dhparams.pem;
 ssl_prefer_server_ciphers on;
 ssl_session_tickets off;
 ssl_ciphers directives "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 resolver 8.8.8.8 8.8.4.4 valid=300s;
 resolver_timeout 5s;
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_trusted_certificate /etc/nginx/ssl/letsencrypt-ca.pem;
 ssl_stapling_responder http://ocsp.int-x3.letsencrypt.org;

 add_header Strict-Transport-Security "max-age=31536000";
 add_header X-Content-Type-Options nosniff;
 add_header X-XSS-Protection "1; mode=block";

 root /var/www/html/example.com;
 index index.html index.htm;

 include acme;

 location / {
 try_files $uri $uri/ /index.html;
}

}


Instead of XX.XX.XX.XX enter IP address of your VPS.

Additional commands to my configuration:
mkdir /etc/nginx/ssl/
openssl dhparam -out /etc/nginx/ssl/dhparams.pem 2048

The file /etc/nginx/ssl/letsencrypt-ca.pem
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2olheyncdanbgkqhkig9w0baqsfada/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdhvyzsbucnvzdcbdby4xfzavbgnvbamt
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxnze2nda0nloxdtixmdmxnze2nda0nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTduxldcdzievuy3j5chqxizahbgnvbamt
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5ifgzmiibijanbgkqhkig9w0baqefaaoc
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7noyzdq1zumgsxhvb418xcsl7e4s0ef
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gwaf15gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671b5tayucv9btywan8jkkkqdiz0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2Pmtivfrqom7hd8befwzb/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2h3dkwidaqabo4ibftccaxkwegydvr0t
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwybbquhaqeeczbxmdig
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnvzdglklm9jc3auawrlbnrydxn0lmnv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2Fwchmuawrlbnrydxn0lmnvbs9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwfoauxkexphsscfrb4uuqdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLkwybbagc3xmbaqewmdaubggrbgefbqcc
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldhnlbmnyexb0lm9yzza8bgnvhr8entaz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnvzdc5jb20vrfnuuk9pvenbwdndukwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRobemrwxv86jsotanbgkqhkig9w0baqsf
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRhgjo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcmyo5jmd6jmewuhk8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0baqufada/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdhvyzsbucnvzdcbdby4xfzavbgnvbamt
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzmdixmtixovoxdtixmdkzmde0mdexnvow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduyxr1cmugvhj1c3qgq28umrcwfqydvqqd
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJkozihvcnaqebbqadggepadccaqocggeb
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7Nndfcdawrgui+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67xmuegwgmooifooumm0rooeq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOednojjj4xlh7din9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xpi71xaicpnad
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsar7lhh62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7ukgy3or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbaux+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancwyalbumr9ybk+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1d9szimljnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvijjeubsfzgl+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2cntuq
-----END CERTIFICATE-----



Also make sure to define default_server, for example in the file /etc/nginx/conf.d/fallback.conf you can write:
server {
 listen XX.XX.XX.XX:80 default_server;
 server_name _;
 return 444;
}


default_server be useful for the treatment of incorrect queries, such as queries without the field "Host"
In my example, just above, nginx will simply close the connection for such requests, for this is special. code 444.
June 14th 19 at 20:41
Solution
Understood. Actually, it was rather trite and simple: it was necessary to add another a-record with www.example.com in the DNS, as suggested :) And just like that, the WWW in front, like @.example.com didn't work.

Find more questions by tags Digital certificatesNginx