Nginx Installation and Reverse Proxy Configuration Guide
Install Nginx from scratch, configure virtual hosts, and set up reverse proxy for Node.js / PHP-FPM. Performance and security tips.
Using Nginx instead of Apache, or want to put a reverse proxy in front of your Node.js/Python/Docker app? You’re in the right place. Nginx is in roughly 35% of modern web servers — its async architecture uses far less resources than Apache. This guide covers install, vhost, and reverse proxy step by step.
Prerequisites
- Ubuntu 22.04 / Debian 12 (use
dnffor AlmaLinux) - Root access
- Ports 80, 443 open (UFW post)
1. Install Nginx
sudo apt update
sudo apt install nginx -y
sudo systemctl enable --now nginx
sudo systemctl status nginx
Open http://vds-ip in browser → you should see the Nginx default page.
2. Check for Apache conflict
If Apache is already installed, Nginx won’t start (port 80 conflict):
sudo systemctl stop apache2
sudo systemctl disable apache2
Or move Apache to 8080 (advanced).
3. First virtual host (your site)
sudo nano /etc/nginx/sites-available/yoursite.com
server {
listen 80;
listen [::]:80;
server_name yoursite.com www.yoursite.com;
root /var/www/yoursite.com;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
# PHP-FPM (for WordPress)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}
# Long cache for static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
access_log /var/log/nginx/yoursite.com_access.log;
error_log /var/log/nginx/yoursite.com_error.log;
}
Activate:
sudo ln -s /etc/nginx/sites-available/yoursite.com /etc/nginx/sites-enabled/
sudo nginx -t # syntax test
sudo systemctl reload nginx
4. Reverse proxy: in front of Node.js / Docker
Say your Node.js app runs on port 3000. Put Nginx on 80/443 and proxy to it:
server {
listen 80;
server_name app.yoursite.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
}
Wins:
- WebSocket support (
proxy_http_version 1.1+ Upgrade header) - SSL termination (Let’s Encrypt at Nginx, app stays plain HTTP)
- Serve static content (don’t tax Node.js)
5. Add SSL (Let’s Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yoursite.com -d www.yoursite.com
Details: Let’s Encrypt post.
Certbot adds the HTTPS block to your vhost and sets up HTTP→HTTPS redirect.
6. Performance tuning
/etc/nginx/nginx.conf:
worker_processes auto;
worker_connections 4096;
# Buffer settings
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 50m;
large_client_header_buffers 4 8k;
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss image/svg+xml;
# Brotli (if module installed)
# brotli on;
# brotli_comp_level 6;
# HTTP/2
listen 443 ssl http2;
sudo nginx -t && sudo systemctl reload nginx
7. 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Test: https://securityheaders.com/
8. Rate limiting (DDoS protection)
# In nginx.conf, http block
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
# In server block
location /api/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://localhost:3000;
}
Our DDoS post details this: DDoS Protection.
9. Log management
# Live tail
sudo tail -f /var/log/nginx/yoursite.com_access.log
# Top hitting IPs
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 404s
sudo grep " 404 " /var/log/nginx/access.log | tail -20
logrotate is pre-configured for Nginx (/etc/logrotate.d/nginx).
Common errors
- “nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)”: Apache is running → stop it
- “502 Bad Gateway”: reverse proxy backend down →
systemctl status node-app - “413 Request Entity Too Large”: bump
client_max_body_size - “504 Gateway Timeout”: add
proxy_read_timeout 300s; - PHP not running: PHP-FPM installed and running?
sudo systemctl status php8.3-fpm
Nginx vs Apache comparison
| Nginx | Apache | |
|---|---|---|
| Architecture | Async, event-driven | Process-based |
| Resources | Less RAM/CPU | More |
| Static files | Very fast | Fast |
| .htaccess | ❌ Not supported | ✓ |
| Reverse proxy | Native | Via mod_proxy |
| Config | sites-available syntax | .conf files |
Both work for WordPress; Nginx is more efficient under high traffic.
Conclusion
Nginx is a cornerstone of the modern web stack. From one VDS, you can run multiple sites + reverse proxy + SSL termination. KavesNET VDS is optimized for Nginx.
Related: WordPress Manual Install · Cloudflare CDN
İlgili Yazılar
Bunlar da ilgini çekebilir.
3-2-1 Yedekleme Kuralı: Sunucu Verilerini Asla Kaybetmemenin Yolu
3-2-1 yedekleme kuralı, kurumsal sunucu yedekleme stratejisinin altın standardıdır. Bu yazıda kuralı, otomasyon yöntemlerini ve KavesNET yedek altyapısını anlatıyoruz.
Devamını Oku
Plesk'ten Plesk'e Site Nasıl Taşınır? Migrator Aracı Rehberi
Plesk Migrator ile site, mail, DB ve DNS'i tek seferde yeni sunucuya taşı. Adım adım kurulum, migration test ve cutover.
Devamını Oku
FileZilla ile VDS'ten VDS'e Dosya Taşıma Rehberi
Eski sunucudan yeni VDS'e siteni taşı: FileZilla ile FTP/SFTP, hız ipuçları, izin ayarları ve hata kontrolü.
Devamını Oku