Nginx excels as a high-performance web server, reverse proxy, and load balancer, handling thousands of concurrent connections with minimal resource usage. On CentOS Stream 9 or 10 (the active CentOS variant in 2026), you can achieve excellent throughput by combining the official repository installation, conservative but effective tuning, and production hardening.
This guide assumes a fresh minimal CentOS Stream install, root or sudo access, and a public-facing server. Focus is on static content, PHP-FPM backend (common for WordPress/Laravel), and high-traffic readiness.
1. Installation Choices (2026 Recommendation)
Two reliable paths exist:
- AppStream module (Red Hat / CentOS default) → Nginx 1.20–1.22 series (stable, integrated, receives backported fixes via RHEL alignment). Best for long-term production stability.
- Official nginx.org repository → Mainline (1.29.x) or Stable (1.28.x) branch (latest features like improved HTTP/3, better QUIC tuning, native Brotli, etc.). Preferred for maximum performance and modern protocol support.
Recommended in 2026: Use the official Stable repo for most high-performance needs — it offers newer optimizations without the bleeding-edge risks of mainline.
Quick install (official Stable repo):
sudo dnf install -y dnf-plugins-core
sudo tee /etc/yum.repos.d/nginx.repo <<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=1
EOF
sudo dnf update -y
sudo dnf install -y nginx(If you prefer module stream: sudo dnf module enable nginx:1.22 then sudo dnf install nginx.)
Enable and start:
sudo systemctl enable --now nginx
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reloadVerify: curl -I http://localhost should return 200 OK or welcome page.
2. Basic Production Structure
Organize configs for scalability:
- /etc/nginx/nginx.conf → global settings (events, http block)
- /etc/nginx/conf.d/*.conf → site-specific server blocks (avoid editing default.conf)
- /etc/nginx/sites-available/ & sites-enabled/ → optional symlink pattern for easier management
- /var/www/html/ or per-site roots → content
Remove default welcome page:
sudo rm /usr/share/nginx/html/index.html3. Core Performance Tuning (High-Traffic Focus)
Edit /etc/nginx/nginx.conf (global http block unless noted).
Worker & Connection Tuning (scale to CPU cores)
worker_processes auto; # or exact core count +1
worker_rlimit_nofile 100000; # raise open files limit
events {
worker_connections 4096; # per worker; total = workers × this
multi_accept on;
use epoll; # or kqueue on BSD
}HTTP Optimizations
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000; # allow many requests per connection
# Gzip / Brotli (Brotli needs dynamic module or official build)
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;
gzip_vary on;
# Modern TLS & HTTP/2 (enable HTTP/3 if using mainline + QUIC)
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Buffers & timeouts for high concurrency
client_body_buffer_size 16k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 64m; # adjust for uploads
}FastCGI / Proxy Buffering (for PHP/Node.js backends)
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;4. Example High-Performance Virtual Host
Create /etc/nginx/conf.d/yourdomain.conf:
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
# Redirect HTTP → HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
root /var/www/yourdomain.com/html;
index index.php index.html;
# Static assets – aggressive caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2?|ttf|eot)$ {
expires 365d;
access_log off;
add_header Cache-Control "public";
}
# PHP backend (PHP-FPM)
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock; # or 127.0.0.1:9000
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 300;
}
# Deny access to hidden files & backups
location ~ /\. {
deny all;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
}5. Security & Reliability Essentials
- Certbot for Let’s Encrypt (HTTPS mandatory in 2026) sudo dnf install certbot python3-certbot-nginxsudo certbot –nginx -d yourdomain.com
- Rate limiting (protect login/API endpoints) limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;limit_req zone=one burst=20 nodelay;
- SELinux compatibility Keep enforcing; relabel web root: sudo restorecon -Rv /var/www
- Monitoring & Logging Enable stub_status or use NGINX Amplify/Prometheus exporter for metrics. Rotate logs with logrotate (default is fine).
6. Validation & Benchmarking
- Syntax check: sudo nginx -t
- Reload gracefully: sudo nginx -s reload
- Test concurrency: ab -n 10000 -c 200 https://yourdomain.com/ or wrk -t12 -c400 -d30s
- Monitor: ss -ltn (connections), top/htop (workers), journalctl -u nginx
Summary: Expected Gains
With these settings on modern hardware (e.g., 4–8 cores, 16+ GB RAM), Nginx routinely handles 20,000–80,000+ req/s for static content or 5,000–15,000 req/s with dynamic PHP backends — far beyond Apache defaults. The key is event-driven architecture, efficient keepalives, caching headers, and minimal per-request overhead.
For extreme scale, add upstream load balancing, Redis micro-caching, or move to Nginx Plus / open-source with Lua/njs modules.