Table of contents:
- β Step-by-step: Install Nginx on Ubuntu
- π Critical Nginx Configuration After Installation
- Performance Optimization
- Buffer Optimizations
- Rate Limiting & DDoS Protection
- How to Include Directives in Nginx
β Step-by-step: Install Nginx on Ubuntu
1. Update your package list
# This ensures you're getting the latest version from Ubuntu's repositories.
sudo apt update
2. Install Nginx
sudo apt install nginx -y
3. Start and Enable Nginx
# Check Nginx Version
nginx -v
# Start Nginx service
sudo systemctl start nginx
# Enable Nginx to start automatically on boot
sudo systemctl enable nginx
# Check Nginx status
sudo systemctl status nginx
4. Reload Nginx
sudo nginx -t # Always test your config first to avoid crashing Nginx. If ok then reload
sudo systemctl reload nginx
π Critical Nginx Configuration After Installation
A. Remove Server Tokens
# /etc/nginx/nginx.conf
http {
server_tokens off;
# ... other config
}
B. Security Headers
Add to server blocks or http context or create a separate headers.conf file and then include this file.
# /etc/nginx/conf.d/headers.conf
# π Prevents your site from being embedded in iframes on other domains.
# Helps defend against clickjacking attacks.
add_header X-Frame-Options "SAMEORIGIN" always;
# π‘οΈ Enables the browser's built-in XSS protection and blocks the page if an attack is detected.
# Note: Modern browsers have mostly deprecated this, but itβs still safe to include.
add_header X-XSS-Protection "1; mode=block" always;
# π§ͺ Stops browsers from MIME-sniffing the content type.
# Ensures content is interpreted only as the declared content type.
add_header X-Content-Type-Options "nosniff" always;
# π Controls how much referrer information is sent with requests.
# This setting protects user privacy while preserving functionality.
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# π‘οΈ Forces browsers to always use HTTPS for your site and all its subdomains.
# "max-age" is set to 1 year (in seconds).
# Only enable this if your entire site (and subdomains) support HTTPS.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# β
Make sure your site uses HTTPS if youβre using HSTS (Strict-Transport-Security)!
C. Block Common Exploits
# /etc/nginx/conf.d/security.conf
# Block SQL injection
# β οΈ Might trigger false positives if a URL contains words like script for legitimate reasons.
location ~* "(\<|%3C).*script.*(\>|%3E)" {
return 403;
}
# Block common exploits
# β οΈ Use this kind of rule on static sites or APIs where you don't expect to see script-related content in URLs.
location ~* "(eval\()" {
return 403;
}
location ~* "(base64_encode)(.*)(\()" {
return 403;
}
# Block file inclusion
location ~* "\.(env|log|sql|md|yml|yaml|ini|conf)$" {
deny all;
access_log off;
log_not_found off;
}
# Block hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
Performance Optimization
# /etc/nginx/nginx.conf
worker_processes auto; # Automatically set to CPU cores
# Adjust based on your expected load
# "ulimit -Hn" to see the hard limit (maximum allowed)
worker_rlimit_nofile 65535; # Increase file descriptor limit (It tells Nginx to allow each worker process to open up to 65,535 files or connections simultaneously).
events {
worker_connections 4096; # Connections per worker (OS limit / CPU cores)
multi_accept on; # Accept multiple connections
use epoll; # Use efficient event method
}
# nproc - Outputs the number of CPU cores available.
http {
sendfile on; # Enable zero-copy file transfer for faster file serving
tcp_nopush on; # Send headers in one packet to reduce network overhead
tcp_nodelay on; # Disable delay, send packets immediately to reduce latency
keepalive_timeout 65; # Keep connections open for 65 seconds to reuse them
types_hash_max_size 2048; # Set hash table size for MIME type lookups (improves speed)
client_max_body_size 64M; # Limit max request body size (e.g., file uploads)
}
Buffer Optimizations
A buffer is a small area in memory used to temporarily hold data while itβs being moved from one place to another.
Think of it like:
πͺ£ A bucket that holds water (data) before you pour it into a tank (server processing).
Nginx uses buffers:
- To hold client data before it sends it to the backend (like PHP)
- To hold responses from backend servers before sending them to the browser
http {
client_body_buffer_size 128K; # Max size for buffering client request body in memory
client_header_buffer_size 1k; # Buffer size for reading client headers
large_client_header_buffers 4 4k; # Up to 4 buffers of 4KB for very large headers (like cookies)
client_body_timeout 12; # Time (in seconds) to wait for the client body
client_header_timeout 12; # Time (in seconds) to wait for client headers
send_timeout 10; # Time to wait before closing connection if client is too slow
}
Rate Limiting & DDoS Protection
limit_req_zone:
- Purpose: Rate limit requests by IP (login attempts in this case)
$binary_remote_addr: Uses client IP in binary format for efficient storagezone=login:10m: Defines a shared memory zone called login, using 10MB to track IPsrate=10r/m: Allows up to 10 requests per minute per IP- π Used to slow down brute-force login attacks
limit_conn_zone - Purpose: Limit the number of concurrent connections per IP
# /etc/nginx/nginx.conf
http {
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=global:10m rate=200r/s;
# Connection limiting
limit_conn_zone $binary_remote_addr zone=addr:10m;
}
Apply Rate Limiting
# In server blocks
server {
# Global rate limit
# burst=300 Allows up to 300 extra requests above the set rate, but only temporarily
# nodelay Sends those extra requests immediately, without slowing them down
# If they go over the burst limit, extra requests are dropped (403)
limit_req zone=global burst=300 nodelay;
limit_conn addr 100;
# Stricter limits for sensitive areas
location /login {
limit_req zone=login burst=5 nodelay;
}
location /api/ {
limit_req zone=api burst=50 nodelay;
}
# Whitelist trusted IPs
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.1;
deny all;
# Your admin configuration
}
}
How to Include Directives in Nginx
In Nginx, you can include directives using the include keyword to organize your configuration by breaking it into smaller, reusable files. This is useful for:
- Keeping your nginx.conf clean
- Managing multiple site configs
- Reusing shared config blocks (like security headers)
include /path/to/file.conf;
# You can also include multiple files using a wildcard:
include /etc/nginx/conf.d/*.conf;
Include Virtual Hosts (per site)
# /etc/nginx/nginx.conf
http {
include /etc/nginx/sites-enabled/*;
}