Gönderi

Nginx ile Web Server Konfigürasyonu: Profesyonel Rehber

Production Nginx konfigürasyonu rehberi. Reverse proxy, load balancing, SSL/TLS, caching stratejileri ve performance tuning best practices.

Nginx ile Web Server Konfigürasyonu: Profesyonel Rehber

Giriş

Nginx, yüksek performanslı, hafif ve ölçeklenebilir bir web server ve reverse proxy sunucusudur. Apache’ye göre daha az bellek kullanan ve daha yüksek eşzamanlı bağlantı kapasitesine sahip olan Nginx, modern web altyapılarının vazgeçilmez bir parçası haline gelmiştir.

Bu rehberde, Nginx’i sıfırdan kurarak production-ready bir web server konfigürasyonu oluşturmayı, güvenlik ayarlarını, performans optimizasyonlarını ve best practice’leri kapsamlı bir şekilde öğreneceksiniz.

Nginx Nedir ve Neden Kullanılır?

Nginx’in Özellikleri

Temel Özellikler:

  • Event-Driven Architecture: Asenkron, non-blocking I/O modeli
  • Düşük Bellek Tüketimi: Yüksek eşzamanlılıkta bile düşük resource kullanımı
  • Yüksek Performans: Static content serving’de üstün performans
  • Reverse Proxy: Backend servislere yönlendirme
  • Load Balancing: Trafiği birden fazla servere dağıtma
  • SSL/TLS Termination: HTTPS desteği
  • HTTP/2 ve HTTP/3: Modern protokol desteği
  • Caching: İçerik cache’leme
  • Rate Limiting: Trafik kontrolü

Nginx vs Apache

1
2
3
4
5
6
7
8
9
# Apache (Process-Based)
# Her istemci için yeni process/thread
# Bellek kullanımı: Yüksek
# C10K problemi: 10,000 eşzamanlı bağlantıda zorluk

# Nginx (Event-Driven)
# Asenkron event loop
# Bellek kullanımı: Düşük
# C10K çözümü: 10,000+ eşzamanlı bağlantı

Nginx Kurulumu

Ubuntu/Debian’da Kurulum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Repository güncelleme
sudo apt update

# Nginx kurulumu
sudo apt install nginx -y

# Firewall ayarları
sudo ufw allow 'Nginx Full'  # HTTP + HTTPS
sudo ufw allow 'Nginx HTTP'  # Sadece HTTP
sudo ufw allow 'Nginx HTTPS' # Sadece HTTPS

# Nginx servis kontrolü
sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl enable nginx  # Başlangıçta otomatik başlat
sudo systemctl reload nginx  # Konfigürasyon yenileme
sudo systemctl restart nginx # Tam yeniden başlatma

CentOS/RHEL’de Kurulum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# EPEL repository ekle
sudo yum install epel-release -y

# Nginx kurulumu
sudo yum install nginx -y

# SELinux ayarları
sudo setsebool -P httpd_can_network_connect 1

# Firewall ayarları
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

# Nginx başlat
sudo systemctl start nginx
sudo systemctl enable nginx

Source’tan Kurulum (Custom Modules)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Bağımlılıklar
sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
    libssl-dev libgd-dev libgeoip-dev -y

# Nginx source indir
cd /tmp
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# Configure (custom modules ile)
./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/nginx/modules \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_gzip_static_module \
    --with-http_stub_status_module \
    --with-threads \
    --with-stream \
    --with-stream_ssl_module

# Compile ve install
make
sudo make install

# Nginx user oluştur
sudo useradd -r -M -s /sbin/nologin nginx

# Systemd service dosyası oluştur
sudo tee /etc/systemd/system/nginx.service > /dev/null <<'EOF'
[Unit]
Description=Nginx HTTP Server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start nginx
sudo systemctl enable nginx

Nginx Konfigürasyon Yapısı

Ana Konfigürasyon Dosyası

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# /etc/nginx/nginx.conf

# Ana context - Global ayarlar
user nginx;
worker_processes auto;  # CPU core sayısı kadar worker
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

# Events context - Connection handling
events {
    worker_connections 1024;  # Worker başına max connection
    use epoll;                # Linux için optimal
    multi_accept on;          # Bir seferde birden fazla connection
}

# HTTP context - HTTP server ayarları
http {
    # MIME types
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging format
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;

    # Performance optimizations
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;  # Hide Nginx version

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript 
               application/json application/javascript application/xml+rss 
               application/rss+xml font/truetype font/opentype 
               application/vnd.ms-fontobject image/svg+xml;

    # Virtual host config dosyaları
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Nginx Virtual Host Structure

Konfigürasyon Testi ve Reload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Syntax check
sudo nginx -t

# Detaylı syntax check
sudo nginx -T

# Konfigürasyonu reload et (zero downtime)
sudo nginx -s reload

# Nginx'i graceful stop
sudo nginx -s quit

# Hemen durdur
sudo nginx -s stop

# Log dosyalarını yeniden aç (log rotation sonrası)
sudo nginx -s reopen

Virtual Host (Server Blocks) Konfigürasyonu

Basit Static Website

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# /etc/nginx/sites-available/example.com

server {
    listen 80;
    listen [::]:80;  # IPv6
    
    server_name example.com www.example.com;
    
    root /var/www/example.com/html;
    index index.html index.htm;
    
    # Access ve error logları
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
    
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Favicon ve robots.txt için özel handling
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }
    
    location = /robots.txt {
        log_not_found off;
        access_log off;
    }
    
    # Static asset caching
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
# Virtual host'u aktifleştir
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# Web root oluştur
sudo mkdir -p /var/www/example.com/html
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com

# Test sayfası
echo "<h1>Welcome to example.com</h1>" | sudo tee /var/www/example.com/html/index.html

# Nginx reload
sudo nginx -t && sudo nginx -s reload

Reverse Proxy Konfigürasyonu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# /etc/nginx/sites-available/api.example.com

upstream backend_api {
    # Load balancing methods:
    # - round-robin (default)
    # - least_conn
    # - ip_hash
    # - hash $request_uri consistent
    
    least_conn;  # En az bağlantılı servera gönder
    
    server 127.0.0.1:8000 weight=3 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8001 weight=2 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8002 backup;  # Sadece diğerleri down olursa
    
    # Health checks (Nginx Plus)
    # health_check interval=10s fails=3 passes=2;
    
    keepalive 32;  # Backend connection pooling
}

server {
    listen 80;
    server_name api.example.com;
    
    # Client request limits
    client_max_body_size 10M;
    client_body_timeout 30s;
    client_header_timeout 30s;
    
    location / {
        proxy_pass http://backend_api;
        
        # Proxy headers
        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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # Buffering
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_busy_buffers_size 8k;
        
        # HTTP version
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
    
    # WebSocket support
    location /ws/ {
        proxy_pass http://backend_api;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;  # 24 hours
    }
    
    # Health check endpoint
    location /health {
        access_log off;
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
}

PHP-FPM ile Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# /etc/nginx/sites-available/wordpress.com

upstream php_fpm {
    server unix:/var/run/php/php8.2-fpm.sock;
    # Veya TCP socket:
    # server 127.0.0.1:9000;
}

server {
    listen 80;
    server_name wordpress.com www.wordpress.com;
    
    root /var/www/wordpress;
    index index.php index.html;
    
    # WordPress permalink support
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # PHP processing
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php_fpm;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        
        # FastCGI cache
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
    }
    
    # Static files caching
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # Deny access to sensitive files
    location ~ /\.ht {
        deny all;
    }
    
    location ~ /\.git {
        deny all;
    }
    
    location = /wp-config.php {
        deny all;
    }
}

SSL/TLS ve HTTPS Konfigürasyonu

Let’s Encrypt ile SSL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Certbot kurulumu
sudo apt install certbot python3-certbot-nginx -y

# SSL sertifikası al (otomatik Nginx konfigürasyonu)
sudo certbot --nginx -d example.com -d www.example.com

# SSL sertifikası al (manuel konfigürasyon)
sudo certbot certonly --webroot -w /var/www/example.com/html \
    -d example.com -d www.example.com

# Otomatik yenileme testi
sudo certbot renew --dry-run

# Otomatik yenileme cron job (zaten kurulu)
sudo systemctl status certbot.timer

Nginx SSL TLS Certificate Flow

Modern SSL Konfigürasyonu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# /etc/nginx/snippets/ssl-params.conf

# SSL protokolleri
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

# Cipher suites (Mozilla Modern configuration)
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
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 "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# /etc/nginx/sites-available/example.com

# HTTP -> HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    return 301 https://$server_name$request_uri;
}

# HTTPS server
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    # SSL certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    
    # SSL parameters
    include /etc/nginx/snippets/ssl-params.conf;
    
    root /var/www/example.com/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

Self-Signed SSL Certificate (Development)

1
2
3
4
5
6
7
8
9
# Self-signed certificate oluştur
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/nginx-selfsigned.key \
    -out /etc/nginx/ssl/nginx-selfsigned.crt \
    -subj "/C=TR/ST=Istanbul/L=Istanbul/O=MyCompany/CN=localhost"

# Diffie-Hellman parametreleri
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Self-signed SSL configuration
server {
    listen 443 ssl http2;
    server_name localhost;
    
    ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    
    include /etc/nginx/snippets/ssl-params.conf;
    
    root /var/www/html;
    index index.html;
}

Load Balancing Stratejileri

Round Robin (Default)

1
2
3
4
5
upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
}

Least Connections

1
2
3
4
5
6
upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
}

IP Hash (Session Persistence)

1
2
3
4
5
6
upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
}

Generic Hash

1
2
3
4
5
6
upstream backend {
    hash $request_uri consistent;  # URL-based routing
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
}

Weighted Load Balancing

1
2
3
4
5
upstream backend {
    server backend1.example.com weight=5;  # %50
    server backend2.example.com weight=3;  # %30
    server backend3.example.com weight=2;  # %20
}

Advanced Load Balancing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
upstream backend {
    least_conn;
    
    # Server tanımları
    server backend1.example.com:8080 weight=3 max_fails=3 fail_timeout=30s;
    server backend2.example.com:8080 weight=2 max_fails=3 fail_timeout=30s;
    server backend3.example.com:8080 backup;  # Backup server
    server backend4.example.com:8080 down;    # Maintenance mode
    
    # Connection pooling
    keepalive 32;
    keepalive_requests 100;
    keepalive_timeout 60s;
}

server {
    listen 80;
    server_name app.example.com;
    
    location / {
        proxy_pass http://backend;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        proxy_next_upstream_tries 3;
        proxy_next_upstream_timeout 30s;
        
        include /etc/nginx/snippets/proxy-params.conf;
    }
}

Caching Stratejileri

Nginx Caching Performance

FastCGI Cache (PHP)

1
2
3
4
5
6
7
8
9
10
11
# /etc/nginx/nginx.conf (http context)

fastcgi_cache_path /var/cache/nginx/fastcgi 
    levels=1:2 
    keys_zone=WORDPRESS:100m 
    inactive=60m 
    max_size=1g;

fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# /etc/nginx/sites-available/wordpress.com

set $skip_cache 0;

# POST requests ve query string olan istekleri cache'leme
if ($request_method = POST) {
    set $skip_cache 1;
}

if ($query_string != "") {
    set $skip_cache 1;
}

# WordPress admin ve login sayfalarını cache'leme
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
    set $skip_cache 1;
}

# Logged in users için cache'leme
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
    set $skip_cache 1;
}

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass php_fpm;
    
    # FastCGI cache
    fastcgi_cache WORDPRESS;
    fastcgi_cache_valid 200 60m;
    fastcgi_cache_valid 404 10m;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    
    # Cache headers
    add_header X-Cache-Status $upstream_cache_status;
}

Proxy Cache (Reverse Proxy)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /etc/nginx/nginx.conf (http context)

proxy_cache_path /var/cache/nginx/proxy 
    levels=1:2 
    keys_zone=PROXYCACHE:100m 
    inactive=60m 
    max_size=1g;

proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# /etc/nginx/sites-available/api.example.com

server {
    listen 80;
    server_name api.example.com;
    
    location /api/ {
        proxy_pass http://backend;
        
        # Proxy cache
        proxy_cache PROXYCACHE;
        proxy_cache_valid 200 10m;
        proxy_cache_bypass $http_pragma $http_authorization;
        proxy_no_cache $http_pragma $http_authorization;
        
        # Cache headers
        add_header X-Cache-Status $upstream_cache_status;
        add_header X-Proxy-Cache $upstream_cache_status;
        
        # Vary header
        proxy_cache_vary on;
        
        include /etc/nginx/snippets/proxy-params.conf;
    }
    
    # Cache purge endpoint (production'da authorization gerekli!)
    location ~ /purge(/.*) {
        allow 127.0.0.1;
        deny all;
        proxy_cache_purge PROXYCACHE "$scheme$request_method$host$1$is_args$args";
    }
}

Microcaching

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Very short-term caching (1 second)
# Traffic spike'larında çok etkili

proxy_cache_path /var/cache/nginx/micro 
    levels=1:2 
    keys_zone=MICROCACHE:10m 
    inactive=1m 
    max_size=100m;

server {
    location / {
        proxy_pass http://backend;
        proxy_cache MICROCACHE;
        proxy_cache_valid 200 1s;
        proxy_cache_use_stale updating;
        proxy_cache_background_update on;
        proxy_cache_lock on;
    }
}

Güvenlik Konfigürasyonu

Rate Limiting

1
2
3
4
5
6
7
8
9
10
11
# /etc/nginx/nginx.conf (http context)

# Request rate limit (IP başına)
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

# Connection limit (IP başına)
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# Bandwidth limit
limit_rate_after 10m;  # İlk 10MB hızlı
limit_rate 1m;          # Sonra 1MB/s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# /etc/nginx/sites-available/example.com

server {
    listen 80;
    server_name example.com;
    
    # Rate limiting
    limit_req zone=req_limit burst=20 nodelay;
    limit_conn conn_limit 10;
    
    location /api/ {
        # Daha strict limit
        limit_req zone=req_limit burst=5 nodelay;
        proxy_pass http://backend;
    }
    
    location /login {
        # Login endpoint için daha katı
        limit_req zone=req_limit burst=2 nodelay;
        proxy_pass http://backend;
    }
}

Access Control

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# IP-based access control
location /admin {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
    
    proxy_pass http://backend;
}

# HTTP Basic Authentication
location /private {
    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    proxy_pass http://backend;
}
1
2
3
4
# .htpasswd dosyası oluştur
sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.htpasswd username
sudo chmod 640 /etc/nginx/.htpasswd

Security Headers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# /etc/nginx/snippets/security-headers.conf

# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Clickjacking protection
add_header X-Frame-Options "SAMEORIGIN" always;

# MIME type sniffing protection
add_header X-Content-Type-Options "nosniff" always;

# XSS protection
add_header X-XSS-Protection "1; mode=block" always;

# Referrer policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Permissions policy
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

# Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.example.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'self';" always;

# Remove server version
server_tokens off;
more_clear_headers Server;  # Requires headers-more module

DDoS Protection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# /etc/nginx/nginx.conf

http {
    # Connection limits
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn addr 10;
    
    # Request rate limits
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    limit_req zone=one burst=5;
    
    # Slow request protection
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 5s 5s;
    send_timeout 10s;
    
    # Request size limits
    client_max_body_size 1m;
    client_body_buffer_size 128k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
}

Performance Optimization

Worker Process Optimization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# /etc/nginx/nginx.conf

# CPU core sayısı kadar worker
worker_processes auto;

# Worker priority (nice value: -20 to 19, düşük = yüksek priority)
worker_priority -5;

# Worker process file descriptor limit
worker_rlimit_nofile 65535;

events {
    # Worker başına max connection
    worker_connections 4096;
    
    # Optimal event method (Linux için epoll)
    use epoll;
    
    # Birden fazla connection'ı aynı anda kabul et
    multi_accept on;
}

Buffering ve Timeouts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
http {
    # Client settings
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;
    
    # Timeouts
    client_body_timeout 12s;
    client_header_timeout 12s;
    keepalive_timeout 15s;
    send_timeout 10s;
    
    # Proxy buffering
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;
    proxy_temp_file_write_size 8k;
    
    # FastCGI buffering
    fastcgi_buffering on;
    fastcgi_buffer_size 4k;
    fastcgi_buffers 8 4k;
    fastcgi_busy_buffers_size 8k;
}

Static Content Optimization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
server {
    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript 
               application/json application/javascript application/xml+rss;
    gzip_disable "msie6";
    
    # Brotli compression (requires ngx_brotli module)
    # brotli on;
    # brotli_comp_level 6;
    # brotli_types text/plain text/css text/xml application/json;
    
    # Open file cache
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    
    # Static files
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    location ~* \.(css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    location ~* \.(woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Access-Control-Allow-Origin "*";
        access_log off;
    }
}

Monitoring ve Logging

Status Module

1
2
3
4
5
6
7
8
9
10
11
12
13
# /etc/nginx/sites-available/status

server {
    listen 127.0.0.1:8080;
    server_name localhost;
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}
1
2
3
4
5
6
7
8
# Status kontrolü
curl http://localhost:8080/nginx_status

# Çıktı:
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

Custom Log Format

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
http {
    # JSON log format
    log_format json_combined escape=json
    '{'
        '"time_local":"$time_local",'
        '"remote_addr":"$remote_addr",'
        '"remote_user":"$remote_user",'
        '"request":"$request",'
        '"status": "$status",'
        '"body_bytes_sent":"$body_bytes_sent",'
        '"request_time":"$request_time",'
        '"http_referrer":"$http_referer",'
        '"http_user_agent":"$http_user_agent"'
    '}';
    
    # Performance log
    log_format performance '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" '
                          'rt=$request_time uct="$upstream_connect_time" '
                          'uht="$upstream_header_time" urt="$upstream_response_time"';
    
    access_log /var/log/nginx/access.log json_combined;
    access_log /var/log/nginx/performance.log performance;
}

Log Rotation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# /etc/logrotate.d/nginx

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi \
    endscript
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

Debugging ve Troubleshooting

Error Log Analysis

1
2
3
4
5
# Error log levels: debug, info, notice, warn, error, crit, alert, emerg
error_log /var/log/nginx/error.log warn;

# Debug log (sadece development'ta!)
error_log /var/log/nginx/debug.log debug;
1
2
3
4
5
6
7
8
# Real-time error log monitoring
tail -f /var/log/nginx/error.log

# Error log istatistikleri
awk '{print $9}' /var/log/nginx/error.log | sort | uniq -c | sort -rn

# Yavaş istekler (>1 saniye)
awk '$NF > 1 {print $7, $NF}' /var/log/nginx/access.log

Common Issues

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. Permission denied
# Çözüm: SELinux veya dosya izinleri
sudo chown -R nginx:nginx /var/www
sudo chmod -R 755 /var/www

# SELinux context
sudo chcon -Rv --type=httpd_sys_content_t /var/www

# 2. Too many open files
# Çözüm: ulimit artır
sudo vim /etc/security/limits.conf
# nginx soft nofile 65535
# nginx hard nofile 65535

# 3. Connection refused to upstream
# Çözüm: Backend servis kontrolü
sudo systemctl status backend-service
sudo netstat -tulpn | grep 8000

# 4. SSL certificate issues
sudo nginx -t
sudo certbot certificates

# 5. Configuration syntax error
sudo nginx -T | less

Production Best Practices

Checklist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Production Nginx Checklist:

Security:
  - [ ] HTTPS enabled with valid SSL certificate
  - [ ] Security headers configured
  - [ ] Rate limiting enabled
  - [ ] server_tokens off
  - [ ] Access control configured
  - [ ] DDoS protection enabled

Performance:
  - [ ] Gzip/Brotli compression enabled
  - [ ] Static file caching configured
  - [ ] FastCGI/Proxy caching enabled
  - [ ] Worker processes optimized
  - [ ] Buffer sizes tuned
  - [ ] Connection pooling enabled

Monitoring:
  - [ ] Access logs configured
  - [ ] Error logs configured
  - [ ] Status module enabled
  - [ ] Log rotation configured
  - [ ] Monitoring/alerting setup

High Availability:
  - [ ] Load balancing configured
  - [ ] Health checks enabled
  - [ ] Failover configured
  - [ ] Backup servers defined
  - [ ] Session persistence configured

Maintenance:
  - [ ] Automated backup
  - [ ] Configuration versioning (Git)
  - [ ] Update strategy defined
  - [ ] Rollback plan documented
  - [ ] Regular security audits

Sonuç

Nginx, modern web altyapılarının vazgeçilmez bir bileşenidir. Bu rehberde öğrendiğiniz konfigürasyonları uygulayarak yüksek performanslı, güvenli ve ölçeklenebilir bir web server altyapısı oluşturabilirsiniz.

Kaynaklar

Production ortamında Nginx kullanırken sürekli izleme, güvenlik güncellemeleri ve performans optimizasyonlarını ihmal etmeyin! 🚀

Bu gönderi CC BY 4.0 lisansı altındadır.