Powerful ways to Supercharge your NGINX server and improve its performance
Introduction
You don’t need to be a DevOps expert to make the optimizations explained in this post. Anyone who is new to web applications and is using NGINX can use these steps. All you have to do is edit your NGINX config file.
Let's begin
1. Improve Performance with HTTP/2
Support
HTTP/2
has a lot of benefits over HTTP
, like allowing the browser to download files in parallel, and allowing the server to push resources, among others. All you have to do is to replace http
with http2
in your server block.
2. Reduce Scrapping/Attacks
Limiting the requests to the server is critical, as this can easily deplete the resources and can result in huge billings. It's also important to fend off those who want to scrape and attack the servers.
3. Client-side Caching
Caching static files on the browser is easy, and it saves a lot of requests to the server. All you have to do is add these two code blocks and specify the expiration as you please. You can include any other static file extension you deem worthy of caching.
4. Microcaching
Microcaching is a caching technique in which content is cached for a very short period of time, perhaps as little as 1 second. This effectively means that updates to the site are delayed by no more than a second, which in many cases is perfectly acceptable.
5. Redirect WWW
Google prefers that you choose a domain without www
instead. It’s better to choose the naked domain as its smaller and removes the redundant www
. You can now redirect all www
users to your naked domain by adding these below directives.
6. Content Compression
Here comes Brotli
, which is the latest encoding algorithm by Google. Brotli is ~20%
more efficient than Gzip
. Just keep in mind you should send content in Gzip
where Brotli is not supported. Brotli works best with static files rather than dynamic content.
7. Improve Security
NGINX doesn't have all the important security headers required which are pretty straightforward actually. These prevent clickjacking attacks, cross-site scripting attacks, and other code injection attacks. HSTS also protects from protocol downgrade attacks.
8. Optimize SSL and Sessions
Use on TLS and disable SSL. SSL is pretty old and outdated and has a lot of vulnerabilities. Optimize cipher suites, as they are the core of TLS. This is where encryption happens.
Final NGINX config and domain config files
1. /etc/nginx/sites-available/example.com
proxy_cache_path /tmp/cacheapi levels=1:2 keys_zone=microcacheapi:100m max_size=1g inactive=1d use_temp_path=off;
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name example.com;
location /api/ {
# Rate Limiting
limit_req zone=reqlimit burst=20; # Max burst of request
limit_req_status 460; # Status to send
# Connections Limiting
limit_conn connlimit 20; # Number ofdownloads per IP
# Bandwidth Limiting
limit_rate 4096k; # Speed limit (here is on kb/s)
# Micro caching
proxy_cache microcacheapi;
proxy_cache_valid 200 1s;
proxy_cache_use_stale updating;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 30d;
}
location ~* \.(css|js)$ {
expires 7d;
}
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
# Pagespeed Module
pagespeed on;
pagespeed FileCachePath /var/cache/ngx_pagespeed_cache;
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
add_header "" "";
}
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
pagespeed RewriteLevel PassThrough;
pagespeed EnableCachePurge on;
pagespeed PurgeMethod PURGE;
pagespeed EnableFilters prioritize_critical_css;
}
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
return 301 https://example.com$request_uri;
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
}
2. /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# SSL Settings
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GC$
# Optimize session cache
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
# Enable session tickets
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
# security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "script-src 'strict-dynamic' 'nonce-rAnd0m123' 'unsafe-inline' http: https:; object-src 'none'; base-uri 'none';" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Cache-Status $upstream_cache_status;
# Logging Settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# limits
limit_req_log_level warn;
limit_req_zone $binary_remote_addr zone=reqlimit:10m rate=10r/m;
limit_conn_zone $binary_remote_addr zone=connlimit:100m;
limit_conn servers 1000; # Simultaneous Connections
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Bonus (Nginx config file generator tool)
If you find this beyond your reach, then there is this simple website that can get the final config file for you.