Nginx – SSL/TLS configuration

We have ready Nginx server, ready PHP deamons with tweaked configuration so… what next? It’s time to secure our websites. With Nginx it’s very simple to run SSL/TLS connections and also HTTP/2 – faster protocol, great for mobile devices and new web browsers. Like in previous chapters, we will make changes not only to enable secure connections, but also tweak default settings – be aware, these recommendations will not work with old browsers like Opera 12, Internet Explorer 7 or old Android (2.x) build-in browsers. I thinks is isn’t any drawback, these browsers are obsolote for a long time. Ok, let’s start with Nginx configuration.

Nginx installation and first configuration

Nginx virtual host configuration

Use PHP-FPM with Nginx

Describe and change php.ini settings

PHP-FPM – config improvements

Use strong Nginx encryption settings

Nginx optimizations, tips and tricks

First step is to change listening port for our website and add additional configuration file – I preferer this method, becuase we can separate global, SSL settings for all websites in one file. Edit /etc/nginx-sites-available/your-config:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /home/mywebsite/ssl/certificate.pem;
    ssl_certificate_key /home/mywebsite/ssl/priv.key;

    include config/ssl.conf;

It’s very simple simple example. First two lines – we change listening port to 443, enable SSL and HTTP/2. Next lines – set certificate and key files – you can generate these files using free Let’s Encrypt or receive from your service provider. We also include new file. Save vhost and add /etc/nginx/config/ssl.conf file with this content:

// Enable SSL
ssl on;

// Set protocols and ciphers - force browsers to use only server ciphers
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
ssl_ciphers '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES';
ssl_prefer_server_ciphers on;

// Enable HSTS - WARNING - after that, you MUST use SSL on your domain and all subdomains!
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";

// Disable tickets because it isn't secure
ssl_session_tickets off;

// Stampling and resolve by Google servers
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

// Additional headers for security
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

There are few settings, I think most are clear, I also add some comments to code. We will use only TLS 1.2 and 1.3 – without SSL and TLS 1.0 and 1.1 because it isn’t secure solution – you can enable these old protocols and change ciphers, but it isn’t good option if you website doesn’t have to be compatible with old devices, old browsers and operating systems. There is also enabled HSTS – it’s great, but you must remember, that all your subdomains must also use secure connections (with includeSubDomains parameter) – without that, browsers will display error and guests will not do anything with that. It’s because HSTS issues block access to website.

There is also enabled SSL stampling to check if certificates are revoked. I also added two important headers to secure websites. It’s should be enabled by default on web browsers, but it’s good idea to set these headers. Ok, we can now go to final step, redirect all non-secure connections to secure versions. Just creathe new vhost:

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

    return 301 https://$host$request_uri;
}

And it’s all. You should test Nginx configuration and restart server.