Nginx Server Configuration for Static Sites

I use nginx as my webserver. It’s fast and has a tone of features. However, for me it’s been a process to learn how to set up properly redirecting, caching, secure, and compressed static webpages with it. I’m not web developer. It’s been slow for me to discover all the useful things it can do for me.

Anyhow, over the past few years I’ve started to get a grasp on what features are useful to implement for the server blocks in nginx. I thought I would share them on my newsletter for anyone else looking on what features to include for hosting a static site. This newsletter article is also for myself for future reference.

HTTP2:

listen 443 ssl http2;  

Adding http2 after the listen 443 ssl in the https code block will enable http2 for your site. This can make your site load a lost faster.

Security Headers:


add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; img-src *; media-src *; https://example.com/css/ "
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
server_tokens off;

Strict-Transport-Security (HSTS):

Content-Security-Policy (CSP):

X-Frame-Options:

X-Content-Type-Options:

Referrer-Policy:

server_tokens off:

GZIP:

gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;

URL Redirection Logic:

location / {
    try_files $uri $uri.html $uri/ =404;
    error_page 404 = /error404;

    if ($request_uri ~ ^/(.*)\.html(\?|$)) {
        return 302 /$1;
    }
}
if ($request_uri ~ ^/(.*)\.html(\?|$)) {
    return 302 /$1;
}

HTTP traffic Redirect to HTTPS:

if ($host = example.com) {
    return 301 https://$host$request_uri;
} 

More Behavior For Linked Content:

location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp|otf)$ {
    expires 6M;
    access_log off;
    add_header Cache-Control "public, immutable";
    try_files $uri $uri/ =404;

    # Persistent connections
    keepalive_timeout 65;
    keepalive_requests 100;
}

Caching Behavior

Static File Handling

Persistent Connections

Disable nginx_status

    location = /nginx_status {
        if ($http_user_agent ~* "Netdata") {
            return 403;
        }
    }

Complete Server Block(s) Example:

server {
    server_name example.com;
    root /var/website;
    index index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri.html $uri/ =404;
        error_page 404 = /error404;

        if ($request_uri ~ ^/(.*)\.html(\?|$)) {
            return 302 /$1;
        }
    }

    location = /nginx_status {
        if ($http_user_agent ~* "Netdata") {
            return 403;
        }
    }

    location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|webp|otf)$ {
        expires 6M;
        access_log off;
        add_header Cache-Control "public, immutable";
        try_files $uri $uri/ =404;

        # Persistent connections
        keepalive_timeout 65;
        keepalive_requests 100;
    }

        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header Content-Security-Policy "default-src 'self'; img-src *; media-src *; https://example.com/css/"
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        server_tokens off;

    listen [::]:443 ssl;  # managed by Certbot
    listen 443 ssl http2;       # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;  # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;  # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf;  # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;      # managed by Certbot
}

server {
    gzip on;
    gzip_min_length 1100;
    gzip_buffers 4 32k;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary on;

    if ($host = example.com) {
        return 301 https://$host$request_uri;
    }  # managed by Certbot

    listen 80;
    listen [::]:80;
    server_name example.com;
    return 404;  # managed by Certbot
}

Securty headers and gzip should be added into a separate http server block in the nginx configuration if nginx is managing multiple sites on the same VPS. Certbot is being used to implement https for the website in this example.



Tags: