Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
NGINX config for SSL with Let's Encrypt certs
# UPDATED 17 February 2019
# Redirect all HTTP traffic to HTTPS
server {
listen 80;
listen [::]:80;
server_name www.domain.com domain.com;
return 301 https://$host$request_uri;
}
# SSL configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.domain.com domain.com;
ssl_certificate /etc/letsencrypt/live/www.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.domain.com/privkey.pem;
# Improve HTTPS performance with session resumption
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Enable server-side protection against BEAST attacks
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";
# RFC-7919 recommended: https://wiki.mozilla.org/Security/Server_Side_TLS#ffdhe4096
ssl_dhparam /etc/ssl/ffdhe4096.pem;
ssl_ecdh_curve secp521r1:secp384r1;
# Aditional Security Headers
# ref: https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
add_header X-Frame-Options DENY always;
# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
add_header X-Content-Type-Options nosniff always;
# ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
add_header X-Xss-Protection "1; mode=block" always;
# Enable OCSP stapling
# ref. http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/www.domain.com/fullchain.pem;
resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] valid=300s; # Cloudflare
resolver_timeout 5s;
# Required for LE certificate enrollment using certbot
location '/.well-known/acme-challenge' {
default_type "text/plain";
root /var/www/html;
}
location / {
root /var/www/html;
}
}
@shunia

This comment has been minimized.

Copy link

@shunia shunia commented Dec 6, 2017

Thanks for the infomation about ssl_dhparam part, though 4096 takes too long to generate, and as https://mozilla.github.io/server-side-tls/ssl-config-generator/ suggested, I use 2048 instead.
Thank you after all, helped a lot.

@shunia

This comment has been minimized.

Copy link

@shunia shunia commented Dec 6, 2017

And one more thing, https://certbot.eff.org/docs/using.html#where-are-my-certificates shows that cert.pem or chain.pem are used for the ssl_trusted_certificate part, don't know the difference between these two and fullchain.pem.

@jimblue

This comment has been minimized.

Copy link

@jimblue jimblue commented Mar 20, 2018

Apparently ssl_trusted_certificate must be made up of your intermediate certificate followed by root certificate:

ssl_trusted_certificate /etc/ssl/certs/example.com.chain+root.crt;

https://sslmate.com/blog/post/ocsp_stapling_in_apache_and_nginx

@Andrei-Paul

This comment has been minimized.

Copy link

@Andrei-Paul Andrei-Paul commented Mar 23, 2018

For ssl_protocols and ssl_ciphers, I would recommend Mozilla SSL Configuration Generator.

@s4ros

This comment has been minimized.

Copy link

@s4ros s4ros commented Apr 18, 2018

Did I say, that I love you for this snippet? ;)

@Keksinautin

This comment has been minimized.

Copy link

@Keksinautin Keksinautin commented Aug 28, 2018

Great thanks!

@zoran

This comment has been minimized.

Copy link

@zoran zoran commented Sep 8, 2018

you don't need a redirect anymore, a single server can handle both:
listen 80; listen 443 ssl;

@tzkmx

This comment has been minimized.

Copy link

@tzkmx tzkmx commented Oct 11, 2018

@zoran, your urls would be accesible through unprotected http protocol,
if the goal is to protect your users privacy, the redirect is recommended

@acrogenesis

This comment has been minimized.

Copy link

@acrogenesis acrogenesis commented Nov 6, 2018

Perhaps you should also add:

worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
  worker_connections  1024;
}

http {

.... gist here ....

}
@andreasvirkus

This comment has been minimized.

Copy link

@andreasvirkus andreasvirkus commented Jan 23, 2019

You'd most likely want to keep only TLS 1.2 and 1.3

ssl_protocols TLSv1.2 TLSv1.3;
@rmoretto

This comment has been minimized.

Copy link

@rmoretto rmoretto commented Jan 30, 2019

Out of curiosity, why should SSLv3 be disabled?

@nrollr

This comment has been minimized.

Copy link
Owner Author

@nrollr nrollr commented Jan 30, 2019

@rmoretto

Out of curiosity, why should SSLv3 be disabled?

See https://www.nginx.com/blog/nginx-poodle-ssl/

@nrollr

This comment has been minimized.

Copy link
Owner Author

@nrollr nrollr commented Feb 17, 2019

Latest version obtains an A+ and 100% SSL report from Qualys SSL Labs

@nrollr

This comment has been minimized.

Copy link
Owner Author

@nrollr nrollr commented Feb 17, 2019

Latest version obtains an A+ and 100% SSL report from Qualys SSL Labs

Note : If you want to obtain the A+ and 100% SSL report, make sure to use a 4096-bit private key. Add --rsa-key-size 4096 when generating keys with Certbot.

@brunocastilhoregio

This comment has been minimized.

Copy link

@brunocastilhoregio brunocastilhoregio commented May 28, 2019

HI guys,

I followed the nginx config and i recive a error where restart the nginx.service.

Restarting nginx (via systemctl): nginx.serviceJob for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.

systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Tue 2019-05-28 19:33:40 UTC; 24s ago
Docs: man:nginx(8)
Process: 1263 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 1247 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 2246 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
Main PID: 1249 (code=exited, status=0/SUCCESS)

May 28 19:33:40 snipeit systemd[1]: Starting A high performance web server and a reverse proxy server...
May 28 19:33:40 snipeit nginx[2246]: nginx: [emerg] "server" directive is not allowed here in /etc/nginx/sites-enabled/default:21
May 28 19:33:40 snipeit nginx[2246]: nginx: configuration file /etc/nginx/nginx.conf test failed
May 28 19:33:40 snipeit systemd[1]: nginx.service: Control process exited, code=exited status=1
May 28 19:33:40 snipeit systemd[1]: nginx.service: Failed with result 'exit-code'.
May 28 19:33:40 snipeit systemd[1]: Failed to start A high performance web server and a reverse proxy server.

Can anybody help me?

@RohitDhankar

This comment has been minimized.

Copy link

@RohitDhankar RohitDhankar commented Oct 1, 2019

HI guys,

I followed the nginx config and i recive a error where restart the nginx.service.

Restarting nginx (via systemctl): nginx.serviceJob for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.

systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Tue 2019-05-28 19:33:40 UTC; 24s ago
Docs: man:nginx(8)
Process: 1263 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 1247 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 2246 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
Main PID: 1249 (code=exited, status=0/SUCCESS)

May 28 19:33:40 snipeit systemd[1]: Starting A high performance web server and a reverse proxy server...
May 28 19:33:40 snipeit nginx[2246]: nginx: [emerg] "server" directive is not allowed here in /etc/nginx/sites-enabled/default:21
May 28 19:33:40 snipeit nginx[2246]: nginx: configuration file /etc/nginx/nginx.conf test failed
May 28 19:33:40 snipeit systemd[1]: nginx.service: Control process exited, code=exited status=1
May 28 19:33:40 snipeit systemd[1]: nginx.service: Failed with result 'exit-code'.
May 28 19:33:40 snipeit systemd[1]: Failed to start A high performance web server and a reverse proxy server.

Can anybody help me?

You probably fixed it by now - just for the record .
You probably have retained the "default" file at the path = /etc/nginx/sites-available/default.
You also have Sym Linked it to DIR = /etc/nginx/sites-enabled/

In your /etc/nginx/sites-enabled/default , file you made changes and restarted Nginx , the Config / Changes you made were not to the liking of Nginx thus the statement - "test failed". The test is actually run on the File /etc/nginx/nginx.conf , it cascades down to all the Linked files , in your case that would be the /etc/nginx/sites-enabled/default.

Further here - https://stackoverflow.com/a/58480166/4928635

@AKApumkin

This comment has been minimized.

Copy link

@AKApumkin AKApumkin commented Oct 9, 2019

Thanks for the infomation about ssl_dhparam part, though 4096 takes too long to generate, and as https://mozilla.github.io/server-side-tls/ssl-config-generator/ suggested, I use 2048 instead.
Thank you after all, helped a lot.

use this instead it will speed it up :D openssl dhparam -dsaparam -out dhparam.pem 4096

@nrollr

This comment has been minimized.

Copy link
Owner Author

@nrollr nrollr commented Oct 11, 2019

@nrollr

This comment has been minimized.

Copy link
Owner Author

@nrollr nrollr commented Oct 11, 2019

Thanks for the infomation about ssl_dhparam part, though 4096 takes too long to generate, and as https://mozilla.github.io/server-side-tls/ssl-config-generator/ suggested, I use 2048 instead.
Thank you after all, helped a lot.

use this instead it will speed it up :D openssl dhparam -dsaparam -out dhparam.pem 4096

@AKApumkin you probably meant openssl dhparam -dsaparam -out dhparam.pem 2048 ;-)

@AKApumkin

This comment has been minimized.

Copy link

@AKApumkin AKApumkin commented Oct 21, 2019

@nrollr Nope, defiantly 4096. That command will generate the 4096 much faster. There's a good explanation of why here

https://security.stackexchange.com/questions/95178/diffie-hellman-parameters-still-calculating-after-24-hours

@kmcminn

This comment has been minimized.

Copy link

@kmcminn kmcminn commented Apr 7, 2020

thanks for this snippet!

if I'm not mistaken the acme protocol requires port 80 for the http-01 challenge. something like below should do:

server {
   listen 80;
   listen [::]:80; 	
   server_name www.domain.com domain.com;

   location '/.well-known/acme-challenge' {
	default_type "text/plain";
	root /var/www/html;
   }
   location / {
        return 301 https://$host$request_uri;
    }
}
@jjromannet

This comment has been minimized.

Copy link

@jjromannet jjromannet commented May 13, 2020

@kmcminn actually it tries HTTPs first

@vald-phoenix

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.