I ran a test at https://www.htbridge.com/websec/ and it didn't go well. There were some headers related to security that I was not aware of, hence my website grade was not the best. Luckily, I found a web focused only on security headers as its own domain name suggests https://securityheaders.io/. It is not only a security testing but also a didactic website full of information about every checked header.

This is what I have edited in my nginx configuration file to get an A+ grade.

Note: Headers definition's were taken from Mozilla Developer Network at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers

1. STRICT-TRANSPORT-SECURITY

The HTTP Strict-Transport-Security response header is a security feature that lets a web site tell browsers that it should only be communicated using HTTPS instead of HTTP. Even if the user enters or follows a plain HTTP link, the browser strictly upgrades the connection to HTTPS.

#All present and future subdomains will be HTTPS
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

2. CONTENT-SECURITY-POLICY

The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. It is a barrier against cross-site scripting attacks (XSS).

#Browsers are only allowed to get scripts, images, and styles from my own domain. Everything else will be blocked.
add_header Content-Security-Policy "default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self'" always;

3. X-XSS-PROTECTION

The HTTP X-XSS-Protection response header is a feature of Internet Explorer, Chrome and Safari that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although these protections are largely unnecessary in modern browsers when sites implement a strong Content-Security-Policy that disables the use of inline JavaScript ('unsafe-inline'), they can still provide protections for users of older web browsers that don't yet support CSP.

#Enables the XSS Filter. When a XSS attack is detected, the browser will prevent rendering of the page
add_header X-XSS-Protection "1; mode=block" always;

4. X-CONTENT-TYPE-OPTIONS

The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed. This allows to opt-out of MIME type sniffing, or, in other words, it is a way to say that the webmasters knew what they were doing.

#The browser will refuse to load the styles and scripts in case they have an incorrect MIME-type
add_header X-Content-Type-Options "nosniff" always;

5. X-FRAME-OPTIONS

The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a frame, iframe or object . Sites can use this to avoid clickjacking attacks, by ensuring that their content is not embedded into other sites. The added security is only provided if the user accessing the document is using a browser supporting X-Frame-Options.

#Browsers refuses to display any requested document in a frame
add_header X-Frame-Options "DENY" always;

6. REFERRER-POLICY

The Referrer-Policy HTTP header governs which referrer information, sent in the Referer header, should be included with requests made.

#Referrer is sent to requests with better or same security, but not less
add_header Referrer-Policy "no-referrer-when-downgrade";

7. PUBLIC-KEY-PINS

The Public Key Pinning Extension for HTTP (HPKP) is a security feature that tells a web client to associate a specific cryptographic public key with a certain web server to decrease the risk of man-in-the-middle attacks with forged certificates.

There is a useful post to know how to set this header properly. It is available here.

First, you need to generate two backup private keys, one RSA and one Elliptic Curve. To do this, run:

#Replace <your.domain> before run
openssl req -nodes -sha256 -newkey rsa:4096 -keyout "<your.domain>.rsa.key" -out "<your.domain>.rsa.csr"
openssl req -nodes -newkey ec:<(openssl ecparam -name prime256v1) -keyout "<your.domain>.ec.key" -out "<your.domain>.ec.csr"

Then, it is necessary to hash each public key by running:

#Replace <your.domain> before run
#hash1
openssl req -pubkey < <your.domain>.rsa.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
#hash2
openssl req -pubkey < <your.domain>.ec.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Next, do it again but with Let's Encrypt public keys:

#hash3
curl https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
#hash4
curl https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
#hash5
curl https://letsencrypt.org/certs/isrgrootx1.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

Finally:

#Replace each hash# properly
#Prevent man-in-the-middle attacks with forged certificates
add_header Public-Key-Pins 'pin-sha256="hash1"; pin-sha256="hash2"; pin-sha256="hash3"; pin-sha256="hash4"; pin-sha256="hash5"; max-age=5184000; includeSubDomains';

8. ADDITIONAL TASKS

Do not over-expose your configuration
No one needs to know except yourself what is the nginx version your website is running on. To hide this information, you need to customize the Server header with any text you want by installing a package named nginx-extras from Ubuntu repository.

# install nginx-extras
apt-get install nginx-extras
# edit nginx main configuration file usually at /etc/nginx/nginx.conf
...
http {
    ....
    more_set_headers "Server: nginx";
    server_tokens off;
    ....
}
...

Setting server_tokens to off instructs nginx to hide its sensitive information from the outside, whereas more_set_headers will overwrite the Server response header as you need to.

Allowed HTTP methods
It is also important to allow just the HTTP methods your website needs. If it serves just static content, GET method is usually enough.

# Edit nginx configuration file
...
server {
    ...
    location / {
        if ($request_method != GET) {
            return 405;
        }
        try_files $uri $uri/ =404;
    }
}
...
}

After I've done all of the above, my website got an A+ grade on these tests: