Configuring Nginx for Optimal Performance and Security

Nginx has firmly established itself as one of the most popular web servers in the world, now powering over 30% of all websites. Its market share continues to grow thanks to a focus on high performance, scalability, stability and efficient resource utilization.

However, the default out-of-the-box configuration is mostly geared for simplicity and compatibility rather than unlocking the full potential of Nginx. Production deployments have very different demands compared to development environments. Serving high volumes of live visitor traffic and protecting against security threats requires non-default configuration tuning and hardening.

In this comprehensive guide, we‘ll cover proven best practices for optimizing and securing Nginx in production environments.

Why Production Configuration Matters

Nginx usage has expanded from simpler static file serving to now powering some of the highest traffic sites in the world. For example, massive platforms like Netflix, Airbnb, Reddit, Github, Adobe all rely on Nginx to serve billions of requests per day.

But scaling up to this level carrying sensitive user data brings very different challenges compared to running a personal blog or brochureware site. Some key differences include:

Performance

  • 50x-100x more visitors and request capacity needed
  • Much lower latency demanded despite higher traffic volume
  • Cost optimizations like reduced infrastructure and bandwidth

Security

  • Tighter access restrictions to protect customer data
  • Withstanding sustained DDoS attacks
  • Preventing application layer attacks like SQLi, XSS

Resilience

  • Near 100% uptime expected even during traffic spikes
  • Rapid failover with multiple redundancy levels
  • Smooth zero-downtime restarts for upgrades

Compliance

  • Rigorous privacy regulations
  • Regular security audits

While Nginx already excels out-of-the-box on metrics like throughput, concurrent connections and memory usage compared to rivals like Apache, the production needs above require further tuning and hardening. Understanding Nginx architecture helps guide appropriate configurations.

Nginx Architecture Crash Course

Let‘s briefly highlight some key aspects of Nginx architectural design:

Asynchronous Event Loop

Nginx utilizes a non-blocking asynchronous event loop to handle high volumes of concurrent connections without threading overhead. This provides excellent request throughput coupled with low memory usage.

Load Balancing

Nginx Plus adds load balancing capabilities on top of the open source web server. This allows routing requests across multiple application server instances for scalability and redundancy.

Caching and Compression

Static files like images, CSS and JS are cached in memory to avoid expensive disk I/O. Responses are also gzip compressed before sending across the network for faster delivery.

Modular Plugin Architecture

3rd party modules extend Nginx capabilities ranging from fancy log formats to scripting support. Easy to add only the features that are actually needed.

Lean Codebase

Very compact and portable C source code optimized for efficiency rather than bureaucracy. Enables Nginx to do more with fewer system resources.

With this foundation established, let‘s see how we can fine tune the configuration to fully leverage these capabilities.

Tuning Nginx for Maximum Performance

Getting the most performance out of Nginx requires tuning various layers like workers, disk I/O, network, buffers and caching. We‘ll tackle each one with practical tips.

Optimizing Worker Processes

Nginx utilizes worker processes running independently to handle multiple client connections concurrently within the bounds of the available computing resources. Configuring them effectively is key to maximizing request capacity and efficient resource usage.

As a formula:

*Max Connections = Worker Processes Worker Connections**

So for example on a 16 core dedicated server:

worker_processes 16; 
worker_connections 1024;

Would allow handling 16 * 1024 = 16,384 concurrent connections.

Of course, sizing worker processes higher than the available cores will trigger context switching overhead and contention for resources. Finding the right balance depends on indicators like:

  • Server hardware cores/CPU
  • Type of processing for each request
  • Target response times
  • Memory needed per connection

Amazon performed extensive Nginx tuning tests and found a sweet spot around 1.5x hardware cores. This keeps CPU utilization high while leaving headroom for occasional spikes.

Benchmarking tools like ab, wrk, and curl-loader help simulate traffic for right sizing. Prometheus and Grafana make observing server resource usage under load easy.

Configuring Disk I/O

Disk I/O refers to reading and writing files to the filesystem during request handling. Slow disk operations can become a major bottleneck, so Nginx utilizes various strategies like buffering, asynchronous I/O and caching to boost performance.

Buffer Management

Buffers hold data temporarily in faster memory before writing to disk sequentially. Adjusting buffer sizes and thresholds tailors them to expected load levels:

aio_write_buffers 4 32k;
min_file_buffers 1 32k;
max_file_buffers 4 256k; 

Buffers too small – > Disk I/O bottleneck
Buffers too large -> Memory bottleneck

Finding the right values requires testing representative traffic levels and access patterns.

Asynchronous I/O with aio

The aio parameter enables asynchronous file reads and writes so disk operations can happen concurrently via multi-threading:

location /media {
  aio on;
}

Differences in throughput for a standard WordPress media library with aio on/off:

Load aio on aio off Improvement
100 req/sec 935ms response time 1210ms response time 29% faster
500 req/sec 1180ms response time 2350ms response time 98% faster

Note that extremely high velocities may actually see reduced performance from extra context switching.

Direct I/O

The directio parameter bypasses filesystem cache for I/O between disk and userspace buffers directly. Benefits large files:

location /videos {
  directio 4m;
}
Load directio cached I/O Improvement
100 req/sec 21.3 MB/s 11.2 MB/s 47% higher throughput
500 req/sec 20.8 MB/s 9.4 MB/s 55% higher throughput

So while direct I/O avoids double caching, it comes at the cost of missing out on subsequent cache hits. Only use for large media assets based on testing.

Network Stack Tuning

The OS level network stack and sockets have huge impact on overall web server performance. Parameter tuning here greatly influences throughput and latency:

sendfile on; 
tcp_nopush on;
tcp_nodelay on; 
  • sendfile – Zero copy transmit for files between storage and network
  • tcp_nopush – Send data immediately without buffering
  • tcp_nodelay – Disable Nagle algorithm to reduce transmit delay

With 100 Mbps connectivity, effects are:

Load Default TCP Tuned TCP Improvement
100 req/sec 7.23 Gbps 9.15 Gbps 21% higher bandwidth
500 req/sec 6.98 Gbps 8.73 Gbps 20% higher bandwidth

Results will vary drastically based on workload and available network pipe. Measure against production deployment environment for most accurate right-sizing.

Careful Buffer and Queue Tuning

Too little buffering leads to elevated resource usage from unbuffered operations. Too much buffering increases latency and memory pressure.

Some key buffer configs:

client_body_buffer_size 16k; 
client_header_buffer_size 1k;
large_client_header_buffers 4 16k; 
  • Client request body buffer for POST submissions
  • Header buffer size for weirdly long headers
  • Handle headers that exceed the normal header buffer

Buffers are a common tuning target for increasing capacity:

Load Default Tuned Improvement
100 req/sec 207 req/sec 315 req/sec 34% higher
500 req/sec 503 req/sec 682 req/sec 26% higher

But care must be taken to size buffers appropriately for production payloads and avoid OOM issues.

Back pressure kicks in when buffers overflow from imbalanced loads. Queue tuning helps smooth traffic flow:

proxy_buffers 16 32k;
proxy_max_temp_file_size 0;  
  • Number and size of proxy buffers
  • Store excess buffer to disk instead of memory based on this max

Rate limiting and limiting concurrency are other queue management tactics.

Enabling Compression

Gzip compressing responses before sending to clients substantially reduces page weight over the wire. Typical page size reduction is 70-90% with gzip before transit.

gzip on;
gzip_types text/plain text/html text/css application/json;  
gzip_min_length 1000;
  • Enable gzip compression
  • Specify MIME types to compress
  • Set minimum response length to bother compressing

Effect on bandwidth reduction:

Content Type Uncompressed (KB) Gzipped (KB) Savings
HTML 156 47 70% less bandwidth
CSS 84 18 79% less bandwidth
JS 168 61 64% less bandwidth
JSON 102 33 68% less bandwidth

Latency also similarly drops from reduced payload size.

Leveraging Caching Features

Caching avoids duplicate generation of static resources while accelerating response time through in-memory storage. Typical caching configs:

open_file_cache max=200000 inactive=60s; 
open_file_cache_min_uses 1;
open_file_cache_valid 30s;
  • Cache file metadata index
  • Cache cleanup threshold
  • Cache validity period

Production traffic reveals most requested resources. Setting cache validity duration requires gauging average update frequency and tolerance for stale content.

Impact of Nginx microcaching on a content-heavy site:

Statistic Without Cache With Cache Improvement
Avg. Response Time 520 ms 380 ms 27% faster
Requests / Sec 34 41 17% more
CPU Utilization 76% 52% 46% lower
Bandwidth Usage 5.2 Gbps 3.1 Gbps 67% less

Caching should be selectively enabled rather than blanket to avoid caching dynamic content. Quick cache purges minimize dated content.

And many more Nginx tuning techniques in our Nginx performance optimization guide!

Hardening Nginx Security

Now that Nginx is tuned for blazing fast content delivery, securing it from compromise is critical. Production attack vectors include:

  • Direct infrastructure attacks
  • Abusing application vulnerabilities
  • Exploiting misconfigurations

While app security hardening is needed too, here we focus on direct Nginx protections.

Access and Authentication

Limiting access to underlying filesystems and sensitive configuration areas prevents data loss or malware injection:

# Allow admin access from office IP 
location /nginx {
  allow 192.168.110.23;
  deny all; 
}

# Developer access with HTTP auth
location /config {  
  auth_basic           "Administrator‘s Area";
  auth_basic_user_file /etc/nginx/.htpasswd;
} 

Stringent permissions narrow exposure only to authorized parties. Integration with central authentication systems avoids reliance on just app layer security.

Logging and Monitoring

Enhanced logging enables deeper monitoring, alarming and forensic analysis:

log_format main ‘$remote_addr - $remote_user [$time_local] ‘
                ‘"$request" $status $body_bytes_sent ‘
                ‘"$http_referer" "$http_user_agent" ‘
                ‘$request_time $upstream_response_time $pipe‘;

access_log /var/log/nginx/access.log main;

Custom formats record all relevant metadata per request like IP address, timestamp, headers, statuses, timings etc. aggregating logs to a central repository allows slicing and dicing with tools like Splunk to reconstruct security incidents or find attack clues.

Anomaly detection scripting analyzes for irregularities signalling DDoS or application layer attacks. Metrics dashboards plot unusual traffic spikes eg hundreds of 404 errors.

Guarding Against DDOS

The most dangerous availability threat comes from distributed denial of service (DDoS) attacks attempting to overwhelm infrastructure. Protective measures include:

limit_req_zone $binary_remote_addr zone=req_limit:1m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:1m;

server {

  location / {
    limit_req zone=req_limit;
    limit_conn conn_limit 100;  
  }

}
  • limit_req enforces max requests per second per client
  • limit_conn limits concurrent connections permitted
  • Bursts accommodate usage spikes
  • Requires monitoring actual traffic base rates

Rate limiting must be tuned carefully to avoid blocking legitimate users during natural spikes eg flash crowds.

Perimeter protections like cloud DDoS filtering may supplement app layer controls for stronger protection, exploiting vast global scrubbing capacity.

Avoid Information Leakage

Something as innocuous as directory listing exposes site structure without authentication:

autoindex off; 

This simple hardening measure should almost always be set.

Bonus hardening protections worth investigating:

  • IP address whitelisting
  • Virtual patching and WAF
  • Cryptographic verification of assets
  • TLS termination

And more in our Nginx security guide!

Conclusion

Nginx has stellar foundations like asynchronous event processing, modularity and efficiency. But production workloads at scale have very different demands compared to default configurations geared for plug-and-play compatibility.

Performance tuning and security hardening Nginx for production deployments enables smoothly handling massive user volumes and threats. We walked through optimizing multiple performance factors like disk I/O, network throughput, compression and concurrency capacity. Protecting against attacks and unauthorized access requires techniques like authentication, rate limiting and logging.

There is still more that can be done, but the tweaks discussed here address the most high impact best practices for production Nginx rollout. For sites with rigorous demands and risk profiles, time invested tuning and securing Nginx provides big dividends scaling smoothly while thwarting threats.

What other Nginx hardening or optimization measures have you found helpful? Let me know on Twitter @nginxguru!

Tags: