Installing SSL certificates for Nginx on Ubuntu

Purchasing an SSL certificate requires creating a Certificate Signing Request (CSR) which you can do on your host using:

openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr

When you purchase your certificate from your vendor, you’ll provide the text content from your CSR file. Once you have the certificate files (normally a .crt and a .key file), transfer them to your server, and place them somewhere like /etc/ssl-certs/.

In your /etc/nginx/nginx.conf (or /etc/nginx/sites-enabled/default), add to the server {  } block:

server {
  listen 443 ssl;
  ssl on;
  ssl_certificate     /etc/ssl-certs/yourdomain_com.crt;
  ssl_certificate_key /etc/ssl-certs/yourdomain.com.key;
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;
        
  # rest of server config
}

Restart nginx with:

sudo service nginx restart

This is documented in the nginx docs here.

Returning custom HTTP headers from nginx

Using curl -v against your site you can easily check the headers being returned from your nginx server. To see only the HTTP exchange without the actual HTML content you can send the output to /dev/null:

curl -v https://yoursite.com -o /dev/null

By default my site is returning:

< Server: nginx
< Date: Sat, 29 Jul 2017 20:12:10 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Link: <https://www.kevinhooke.com/wp-json/>; rel="https://api.w.org/"
< Link: <https://wp.me/91fMZ>; rel=shortlink

To add additional headers, such as XSS prevention headers:

X-XSS-Protection: 1; mode=block

Edit your nginx.conf and add to your server { } block:

add_header X-XSS-Protection "1; mode=block";

To hide X-Powered-By headers if you are using fastcgi (see here), add:

fastcgi_hide_header X-Powered-By;

 

nginx redirecting http requests to https

If you have your nginx server setup with valid SSL certificates to support https, you can redirect all http incoming requests to https with a simple 301 ‘Permanently Moved’ response to the client.

Returning a 301 is considered best practice for enforcing an http to https upgrade.

This post covers this approach, which involves configuring a server block for port 80 to always respond with a 301 response including the https url:

server {
    listen 80;
    listen [::]:80;
    server_name www.example.com; 
    return 301 https://www.example.com$request_uri;
}

The example config in the above article also shows how to redirect first to your server defined with no subdomain, and then additionally redirect from the request with no subdomain to your www subdomain, e.g from http://www.example.com to https://example.com then to https://www.example.com. Apparently the way nginx caches server names there’s performance advantages to redirect to a no-name subdomain first. Redirecting directly to your www subdomain obviously still works too.