0% found this document useful (0 votes)
4 views29 pages

Nginx Complete Guide

This document provides a comprehensive guide on setting up and configuring Nginx as a reverse proxy and load balancer, including installation instructions for various operating systems. It covers core configuration, static file serving, SSL/TLS setup, and security best practices. Additionally, it discusses advanced topics such as port forwarding, virtual hosts, and performance tuning.

Uploaded by

hdrak85
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views29 pages

Nginx Complete Guide

This document provides a comprehensive guide on setting up and configuring Nginx as a reverse proxy and load balancer, including installation instructions for various operating systems. It covers core configuration, static file serving, SSL/TLS setup, and security best practices. Additionally, it discusses advanced topics such as port forwarding, virtual hosts, and performance tuning.

Uploaded by

hdrak85
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Reverse Proxy • Port Forwarding • Doc

■ Production Ready
■ SSL/TLS Ready
■ Docker Friendly
Table of Contents
1. Nginx ■■? – ■■■■■■ ■ Architecture
2. Installation – Ubuntu / Debian / CentOS / Docker
3. Core Configuration – [Link] ■■■■■■■■
4. Static File Serving
5. Reverse Proxy – ■■■■■■■■ ■■■■
6. Port Forwarding
7. Virtual Hosts / Server Blocks
8. SSL/TLS – Let's Encrypt ■■■■■ HTTPS
9. Load Balancing
10. Docker ■■■■ Nginx
11. Docker Compose – Full Stack Example
12. Security Best Practices
13. Performance Tuning
14. Common Directives Cheat Sheet
15. Troubleshooting
1. Nginx ■■? – ■■■■■■ ■ Architecture

Nginx (Engine-X ■■■■ ■■■■■■■■) ■■■■ high-performance, open-source web server, reverse
proxy, load balancer ■■■ HTTP cache■ 2004 ■■■■ Igor Sysoev ■■■■ ■■■■■ C10K problem
(■■■■■■ ■■,■■■ connection) solve ■■■■ ■■■■ event-driven, non-blocking architecture ■■■■■■■
■■■■

Nginx ■■ ■■ ■■■■ ■■■■?


Feature Description

Web Server Static files serve ■■■ (HTML, CSS, JS, images)

Reverse Proxy Client request ■■■■ server-■ forward ■■■

Load Balancer Multiple backend servers-■ traffic distribute ■■■

SSL Termination HTTPS handle ■■■ backend-■ plain HTTP ■■■■■■

HTTP Cache Response cache ■■■ performance ■■■■■■■

Port Forwarding ■■■■ port-■■ traffic ■■■■ port/server-■ ■■■■■■

API Gateway Microservice architecture-■ central entry point

Apache vs Nginx
Apache thread-based model ■■■■■■■ ■■■ – ■■■■■ connection-■ ■■■■ thread ■■■■ ■■■■
Nginx event-driven model ■■■■■■■ ■■■ – ■■■■ process ■■■■■ ■■■■■ connection ■■■■■■
handle ■■■■ ■■■■■

Apache Nginx

Architecture Thread/Process per conn Event-driven, async

Memory Usage ■■■■ ■■

Static Files ■■■■ ■■■■ ■■■■ (faster)

Dynamic Content mod_php ■■■■■ ■■■■■ FastCGI/proxy ■■■■■

Config .htaccess support Centralized config

Concurrency ■■ (C10K problem) ■■■■ ■■■■


2. Installation

Ubuntu / Debian
# System update ■■■
sudo apt update && sudo apt upgrade -y

# Nginx install ■■■


sudo apt install nginx -y

# Service start ■■■


sudo systemctl start nginx
sudo systemctl enable nginx # boot-■ auto-start

# Status check ■■■


sudo systemctl status nginx

# Firewall allow ■■■


sudo ufw allow 'Nginx Full' # HTTP + HTTPS
sudo ufw allow 'Nginx HTTP' # ■■■■ HTTP
sudo ufw allow 'Nginx HTTPS' # ■■■■ HTTPS

CentOS / RHEL / Rocky Linux


sudo yum install epel-release -y
sudo yum install nginx -y

# ■■■■ Rocky/AlmaLinux-■:
sudo dnf install nginx -y

sudo systemctl start nginx


sudo systemctl enable nginx

Version Check ■ Important Paths


nginx -v # version check
nginx -V # ■■ compile options ■■■■

# Important file paths (Ubuntu/Debian):


/etc/nginx/[Link] # main config
/etc/nginx/sites-available/ # ■■ site configs
/etc/nginx/sites-enabled/ # active site configs (symlinks)
/etc/nginx/conf.d/ # extra configs
/var/www/html/ # default web root
/var/log/nginx/[Link] # access logs
/var/log/nginx/[Link] # error logs
/run/[Link] # PID file

Nginx Commands
Command ■■■

sudo nginx -t Config syntax check (deploy ■■■■ ■■■ ■■■■■■!)

sudo systemctl reload nginx Config reload (downtime ■■■)

sudo systemctl restart nginx Full restart

sudo systemctl stop nginx Stop ■■■

sudo nginx -s reload Signal ■■■■■ reload

sudo nginx -s quit Graceful shutdown

sudo nginx -s stop Fast shutdown


3. Core Configuration – [Link] ■■■■■■■■

[Link] ■■ structure ■■■■■ main block-■ ■■■■■■: main, events, http■


# /etc/nginx/[Link]

# ■■ MAIN CONTEXT ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


user www-data; # ■■■ user-■ run ■■■■
worker_processes auto; # CPU core ■■■■■■■■ worker
error_log /var/log/nginx/[Link] warn;
pid /run/[Link];

# ■■ EVENTS CONTEXT ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


events {
worker_connections 1024; # ■■■■■ worker ■■■■■■■■ connections
use epoll; # Linux-■ best event model
multi_accept on; # ■■■■■■ ■■■■ connection accept
}

# ■■ HTTP CONTEXT ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


http {
include /etc/nginx/[Link];
default_type application/octet-stream;

# Log format
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

access_log /var/log/nginx/[Link] main;

sendfile on; # kernel-level file transfer


tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;

# Include ■■ site configs


include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

# ■■ SERVER BLOCK (Virtual Host) ■■■■■■■■■■■■■■■■■■


server {
listen 80;
server_name [Link] [Link];
root /var/www/html;
index [Link] [Link];

location / {
try_files $uri $uri/ =404;
}
}
}
4. Static File Serving

server {
listen 80;
server_name [Link] [Link];
root /var/www/mysite;
index [Link];

# Static files serve ■■■


location / {
try_files $uri $uri/ =404;
}

# Image caching (1 ■■■)


location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}

# CSS/JS caching (30 ■■■)


location ~* \.(css|js)$ {
expires 30d;
add_header Cache-Control "public";
}

# Hidden files block ■■■


location ~ /\. {
deny all;
}

# Directory listing (■■■■■ on ■■■)


location /files/ {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
5. Reverse Proxy – ■■■■■■■■ ■■■■

Reverse proxy ■■■■ ■■■ Nginx client-■■ request ■■■■■ backend server-■ ■■■■■■, response
■■■■■ client-■■ ■■■■■ Client ■■■■■ ■■ ■■■■■ ■■■■ server ■■■■

Basic Reverse Proxy


server {
listen 80;
server_name [Link];

location / {
proxy_pass [Link] # backend port

# Headers ■■■■■ backend-■


proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Complete Reverse Proxy (Production)


# /etc/nginx/sites-available/[Link]

upstream backend {
server [Link]:3000;
}

server {
listen 80;
server_name [Link] [Link];

# ■■ HTTP → HTTPS redirect


return 301 [Link]
}

server {
listen 443 ssl http2;
server_name [Link] [Link];

ssl_certificate /etc/letsencrypt/live/[Link]/[Link];
ssl_certificate_key /etc/letsencrypt/live/[Link]/[Link];

# Security headers
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000" always;
# Buffer settings
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

# Timeout settings
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

location / {
proxy_pass [Link]
proxy_http_version 1.1;

# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

# Real IP forward
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# Cache bypass
proxy_cache_bypass $http_upgrade;
}

# Static files directly serve ■■■ (backend bypass)


location /static/ {
alias /var/www/myapp/static/;
expires 30d;
}

# Upload size limit


client_max_body_size 50M;
}

Multiple Apps – ■■■■ Server-■ ■■■■ App


# App 1: [Link] → port 3000
server {
listen 80;
server_name [Link];
location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
# App 2: [Link] → port 4000
server {
listen 80;
server_name [Link];
location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

# App 3: [Link] → port 5000


server {
listen 80;
server_name [Link];

# IP restriction (optional)
allow [Link]/24;
deny all;

location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Path-based Routing
# ■■■■ domain-■ path ■■■■■■■■ ■■■■■ backend
server {
listen 80;
server_name [Link];

# / → frontend (React/Vue)
location / {
proxy_pass [Link]
proxy_set_header Host $host;
}

# /api/ → backend API (Node/Django/Laravel)


location /api/ {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

# /ws/ → WebSocket server


location /ws/ {
proxy_pass [Link]
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}

# /media/ → media server


location /media/ {
proxy_pass [Link]
}
}
6. Port Forwarding

Port forwarding ■■■■ ■■■■ port-■ ■■■ traffic ■■■■ port ■■ server-■ ■■■■■■■ Nginx-■ ■■■
HTTP ■■■ TCP/UDP ■■■■■ ■■■ ■■■■■

HTTP Port Forwarding (Port 80 → ■■■■ Port)


# Port 80 → Port 8080
server {
listen 80;
server_name [Link];

location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

TCP/UDP Port Forwarding (stream module)


# /etc/nginx/[Link] ■ ■■■ ■■■ (http block ■■ ■■■■■)
stream {
# TCP: Port 3306 → MySQL (■■■■ server)
server {
listen 3306;
proxy_pass [Link]:3306;
proxy_timeout 300s;
proxy_connect_timeout 10s;
}

# TCP: Port 6379 → Redis


server {
listen 6379;
proxy_pass [Link]:6380;
}

# UDP: DNS forwarding


server {
listen 53 udp;
proxy_pass [Link]:53;
proxy_timeout 1s;
proxy_responses 1;
}

# Load balancing with TCP


upstream mysql_servers {
server [Link]:3306;
server [Link]:3306;
}
server {
listen 3307;
proxy_pass mysql_servers;
}
}

Port 443 ■■■■ Internal Port Forwarding


# HTTPS traffic forward ■■■ internal service-■
server {
listen 443 ssl;
server_name [Link];

ssl_certificate /etc/ssl/certs/[Link];
ssl_certificate_key /etc/ssl/private/[Link];

location / {
proxy_pass [Link]
proxy_ssl_verify off; # internal self-signed cert ■■■
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

External to Internal Network Forwarding


# Internet ■■■■ ■■■ traffic → Internal server
# (DMZ setup)
stream {
upstream internal_web {
server [Link]:80; # internal server 1
server [Link]:80; # internal server 2
}

server {
listen 80;
proxy_pass internal_web;
proxy_timeout 600s;
}
}
7. Virtual Hosts / Server Blocks

■■■■ server-■ ■■■ IP ■■■■■ ■■■■ domain host ■■■■ ■■■■■■■


# Step 1: Config file ■■■■ ■■■
sudo nano /etc/nginx/sites-available/[Link]

# ■■ Config content ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


server {
listen 80;
listen [::]:80; # IPv6 support

server_name [Link] [Link];


root /var/www/[Link]/html;
index [Link] [Link];

access_log /var/log/nginx/[Link];
error_log /var/log/nginx/[Link];

location / {
try_files $uri $uri/ =404;
}
}

# Step 2: Symlink ■■■■ ■■■ (enable ■■■)


sudo ln -s /etc/nginx/sites-available/[Link] /etc/nginx/sites-enabled/

# Step 3: Test ■ reload


sudo nginx -t
sudo systemctl reload nginx

# Step 4: Web root ■■■■ ■■■


sudo mkdir -p /var/www/[Link]/html
sudo chown -R $USER:$USER /var/www/[Link]/html
8. SSL/TLS – Let's Encrypt ■■■■■ HTTPS

# Certbot install ■■■


sudo apt install certbot python3-certbot-nginx -y

# SSL certificate ■■■ (auto nginx config)


sudo certbot --nginx -d [Link] -d [Link]

# Manual certificate (nginx config ■■■■ ■■■■)


sudo certbot certonly --nginx -d [Link]

# Certificate renew test


sudo certbot renew --dry-run

# Auto renew cron job (certbot automatically ■■■)


# /etc/cron.d/certbot ■ ■■■

Manual SSL Config


server {
listen 443 ssl http2;
server_name [Link] [Link];

ssl_certificate /etc/letsencrypt/live/[Link]/[Link];
ssl_certificate_key /etc/letsencrypt/live/[Link]/[Link];
ssl_trusted_certificate /etc/letsencrypt/live/[Link]/[Link];

# SSL settings (Mozilla Intermediate)


ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
resolver [Link] [Link] valid=300s;

root /var/www/mysite;
index [Link];

location / {
try_files $uri $uri/ =404;
}
}

# HTTP → HTTPS redirect


server {
listen 80;
server_name [Link] [Link];
return 301 [Link]
}
9. Load Balancing

http {
# ■■ Round Robin (default) ■■■■■■■■■■■■■■■■■■■■■■■■■
upstream myapp_rr {
server [Link]:8080;
server [Link]:8080;
server [Link]:8080;
}

# ■■ Weighted Round Robin ■■■■■■■■■■■■■■■■■■■■■■■■■■


upstream myapp_weighted {
server [Link]:8080 weight=5; # ■■■■ traffic ■■■■
server [Link]:8080 weight=2;
server [Link]:8080 weight=1;
}

# ■■ Least Connections ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


upstream myapp_lc {
least_conn;
server [Link]:8080;
server [Link]:8080;
}

# ■■ IP Hash (session persistence) ■■■■■■■■■■■■■■■■■


upstream myapp_iphash {
ip_hash;
server [Link]:8080;
server [Link]:8080;
server [Link]:8080 backup; # backup server
}

# ■■ Health Check ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


upstream myapp_health {
server [Link]:8080 max_fails=3 fail_timeout=30s;
server [Link]:8080 max_fails=3 fail_timeout=30s;
server [Link]:8080 backup;
}

server {
listen 80;
server_name [Link];

location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
10. Docker ■■■■ Nginx

Docker-■ Nginx ■■■■■■■ ■■■■■■■ ■■■ ■■■■: (■) Nginx ■■■■■ Docker container-■, (■) Nginx
host-■ ■■■■ Docker container-■■■■■ reverse proxy ■■■■■■ ■■■ ■■■■

Method 1: Nginx Docker Container


# Basic Nginx container ■■■■■
docker run -d \
--name nginx \
-p 80:80 \
-p 443:443 \
nginx:alpine

# Custom config ■■■■■ ■■■■■


docker run -d \
--name nginx \
-p 80:80 \
-v /path/to/[Link]:/etc/nginx/[Link]:ro \
-v /path/to/html:/usr/share/nginx/html:ro \
nginx:alpine

# Logs ■■■■
docker logs nginx
docker logs -f nginx # live logs

Nginx ■■■■■ Docker Apps Proxy ■■■ (Host Nginx)


# Docker app ■■■■■ (port expose ■■■)
docker run -d \
--name my-node-app \
-p 3000:3000 \
my-node-image

docker run -d \
--name my-python-app \
-p 5000:5000 \
my-python-image

# Host-■ nginx config:


# /etc/nginx/sites-available/[Link]
server {
listen 80;
server_name [Link];

location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 80;
server_name [Link];

location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Custom Nginx Dockerfile


# Dockerfile
FROM nginx:alpine

# Default config ■■■■


RUN rm /etc/nginx/conf.d/[Link]

# Custom config copy ■■■


COPY [Link] /etc/nginx/[Link]
COPY conf.d/ /etc/nginx/conf.d/

# Static files copy ■■■


COPY html/ /usr/share/nginx/html/

# Port expose ■■■


EXPOSE 80 443

# Health check
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider [Link] || exit 1

CMD ["nginx", "-g", "daemon off;"]


11. Docker Compose – Full Stack Example

Real-world ■■■■■■: React frontend + [Link] API + PostgreSQL + Nginx

[Link]
version: '3.8'

services:
# ■■ Nginx (Reverse Proxy) ■■■■■■■■■■■■■■■■■■■■■■■■■■
nginx:
image: nginx:alpine
container_name: nginx_proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/[Link]:/etc/nginx/[Link]:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
depends_on:
- frontend
- backend
restart: unless-stopped
networks:
- app-network

# ■■ React Frontend ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: react_app
expose:
- "3000" # ■■■■ internal network-■ expose
environment:
- NODE_ENV=production
- REACT_APP_API_URL=[Link]
restart: unless-stopped
networks:
- app-network

# ■■ [Link] Backend API ■■■■■■■■■■■■■■■■■■■■■■■■■■■■


backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: node_api
expose:
- "5000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@postgres:5432/mydb
- JWT_SECRET=your-secret-key
- REDIS_URL=redis://redis:6379
depends_on:
- postgres
- redis
restart: unless-stopped
networks:
- app-network

# ■■ PostgreSQL Database ■■■■■■■■■■■■■■■■■■■■■■■■■■■■


postgres:
image: postgres:15-alpine
container_name: postgres_db
volumes:
- postgres_data:/var/lib/postgresql/data
- ./[Link]:/docker-entrypoint-initdb.d/[Link]
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
expose:
- "5432" # external access ■■■■!
restart: unless-stopped
networks:
- app-network

# ■■ Redis Cache ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


redis:
image: redis:7-alpine
container_name: redis_cache
expose:
- "6379"
volumes:
- redis_data:/data
restart: unless-stopped
networks:
- app-network

# ■■ Volumes ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
volumes:
postgres_data:
redis_data:

# ■■ Networks ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
networks:
app-network:
driver: bridge
nginx/conf.d/[Link]
# Docker Compose-■■ service name ■■■■■■■ ■■■ hostname ■■■■■■
upstream frontend {
server frontend:3000; # service name = hostname in Docker network
}

upstream backend {
server backend:5000;
}

server {
listen 80;
server_name [Link] [Link];

# Let's Encrypt ACME challenge


location /.well-known/acme-challenge/ {
root /var/www/certbot;
}

# HTTP → HTTPS
location / {
return 301 [Link]
}
}

server {
listen 443 ssl http2;
server_name [Link] [Link];

ssl_certificate /etc/letsencrypt/live/[Link]/[Link];
ssl_certificate_key /etc/letsencrypt/live/[Link]/[Link];

client_max_body_size 20M;

# Frontend
location / {
proxy_pass [Link]
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

# Backend API
location /api/ {
proxy_pass [Link]
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
}
}

Deploy Commands
# Start ■■■
docker-compose up -d

# Logs ■■■■
docker-compose logs -f nginx

# Rebuild ■ restart
docker-compose up -d --build

# Stop ■■■
docker-compose down

# Volumes ■■ ■■ ■■■■ ■■■■


docker-compose down -v

# Nginx config reload (container restart ■■■■■)


docker-compose exec nginx nginx -s reload

# Nginx config test


docker-compose exec nginx nginx -t
12. Security Best Practices

server {
listen 443 ssl http2;
server_name [Link];

# ■■ Version Hide ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


server_tokens off; # Nginx version hide

# ■■ Security Headers ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-in
line';" always;

# ■■ Rate Limiting ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


# (http block-■ define ■■■)
# limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# limit_conn_zone $binary_remote_addr zone=addr:10m;

location /api/ {
limit_req zone=api burst=20 nodelay;
limit_conn addr 10;
proxy_pass [Link]
}

# ■■ DDoS Protection ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 5s 5s;
send_timeout 10s;

# ■■ Block Bad Bots ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


if ($http_user_agent ~* "sqlmap|nikto|masscan|nmap") {
return 403;
}

# ■■ Sensitive Files Block ■■■■■■■■■■■■■■■■■■■■■■■■■


location ~ /\.(git|env|htaccess|htpasswd) {
deny all;
return 404;
}

location ~ \.(sql|bak|old|backup)$ {
deny all;
}
# ■■ IP Whitelist (admin panel) ■■■■■■■■■■■■■■■■■■■■
location /admin {
allow [Link]/24;
allow [Link];
deny all;
proxy_pass [Link]
}

# ■■ Basic Auth ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


location /private {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass [Link]
}
}
13. Performance Tuning

# /etc/nginx/[Link]

worker_processes auto; # CPU cores = worker count


worker_rlimit_nofile 65535; # max open files

events {
worker_connections 65535;
use epoll;
multi_accept on;
}

http {
# ■■ Gzip Compression ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_min_length 1000;
gzip_types
text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
image/svg+xml;

# ■■ Caching ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;

# ■■ Keepalive ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
keepalive_timeout 65;
keepalive_requests 1000;

# ■■ Buffers ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;

# ■■ Sendfile (kernel-level, faster) ■■■■■■■■■■■■■■■


sendfile on;
tcp_nopush on;
tcp_nodelay on;

# ■■ Open File Cache ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
14. Common Directives Cheat Sheet

Directive Context ■■■

listen server Port ■ IP listen ■■■

server_name server Domain name match ■■■

root http/server/location Document root directory

alias location Path replace ■■■

index http/server/location Default file

try_files location File ■■■■■ ■■ ■■■■ fallback

proxy_pass location Upstream server-■ forward

proxy_set_header location Upstream-■ header ■■■■■■

return server/location Redirect ■■ response

rewrite server/location URL rewrite ■■■

location server URL pattern match

upstream http Backend server group

add_header http/server/location Response header ■■■ ■■■

deny/allow http/server/location IP access control

limit_req location Request rate limit

gzip http/server/location Compression ■■■■ ■■■

ssl_certificate server SSL cert path

expires http/server/location Cache expiry time

client_max_body_size http/server/location Max upload size

error_page http/server/location Custom error pages

include any ■■■■ config file include


15. Troubleshooting

Common Errors ■ Solutions


Error ■■■■ Solution

nginx: [emerg] bind() to [Link]:80


Port 80
failed
already in use sudo fuser -k 80/tcp ■■■■ ■■■■ service ■■■■ ■■■

502 Bad Gateway Backend ■■■■ ■■ Backend service ■■■■ ■■■ ■■■■ ■■■■

504 Gateway Timeout Backend respond ■■■■ ■■ proxy_read_timeout ■■■■■■

403 Forbidden Permission ■■■■■■ File/folder permission ■ nginx user ■■■ ■■■

404 Not Found File ■■■ ■■ root ■■■ root path ■ try_files ■■■ ■■■

Upload size ■■■■


413 Request Entity Too Large client_max_body_size ■■■■■■

Debug Commands
# Config test
sudo nginx -t

# Error log ■■■■ (live)


sudo tail -f /var/log/nginx/[Link]

# Access log ■■■■ (live)


sudo tail -f /var/log/nginx/[Link]

# ■■■ port ■■ use ■■■■


sudo ss -tlnp | grep :80
sudo lsof -i :80

# Nginx process ■■■■


ps aux | grep nginx

# Docker container-■■ log


docker logs -f nginx_container

# Nginx reload without restart


sudo nginx -s reload

# Permission fix
sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite

■ Nginx ■■■■■ ■■■■■■■ management ■■■■ ■■■ ■■■■ ■■ guide-■■ ■■ config


■■■■ try ■■■ – practice-■ best teacher!

You might also like