Advanced Nginx Server Tuning and Security Best Practices
Information Disclosure and Header Obfuscation
Preventing version exposure reduces attack surface visibility. Disabling token broadcasting stops clients from identifying exact software builds.
http {
server_tokens off;
}
When branding customization is required at the binary level, modify core definition headers before compilation:
// src/core/nginx_custom.h
#define CUSTOM_PKG_NAME "webgateway"
#define CUSTOM_BUILD_VER "2.8"
#define CUSTOM_RELEASE_TAG "stable-core"
// src/http/ngx_http_header_filter.c
static char ngx_server_banner[] = "Server: " CUSTOM_PKG_NAME "/" CUSTOM_BUILD_VER "\r\n";
Recompile with explicit prefix and service account assignments to align with system policies:
./configure --prefix=/opt/gateway --user=websvc --group=websvc && make install
Process Isolation and Privilege Management
Running workers under restricted accounts limits potential damage from compromised services. Define the runtime identity within the configuration:
user websvc webservice;
Alternatively, enforce restrictions during initialization via build flags or post-installation ownership changes:
useradd -r -s /usr/sbin/nologin websvc
chown -R websvc:webservice /opt/gateway/*
Request Scaling and Concurrency Control
Align worker threads with available cores to maximize throughput without context-switch overhead. Modern deployments prefer automatic detection:
worker_processes auto;
Pin execution threads to specific processor sockets to minimize cache misses and NUMA interference:
# Map 4 workers to distinct cores using binary masks
worker_cpu_affinity 0001 0010 0100 1000;
# Distribute 8 workers across dual sockets
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
Select efficient I/O multiplexing based on the host kernel. Linux environments benefit significantly from epoll:
events {
use epoll;
worker_connections 65535;
multi_accept on;
}
ulimit -n 102400
Increase the per-process file descriptor ceiling to accommodate high-concurrency workloads:
worker_rlimit_nofile 8192;
Access Policies and Network Restrictions
Block unauthorized endpoints by matching URI patterns and rejecting traffic explicitly:
location ~* ^/(api/internal|backup/db)/ {
deny all;
return 403;
}
location ~ \.(env|bak|sql|git)$ {
deny all;
}
Restrict source addresses using allow/deny ordering rules:
location /secure-panel/ {
allow 10.10.0.0/24;
allow 172.16.5.10;
deny all;
}
Validate incoming host headers to prevent DNS rebinding or missing virtual host routing:
map $host $allowed_host {
default 0;
api.internal.net 1;
www.internal.net 1;
}
server {
listen 80 default_server;
server_name _;
if ($allowed_host = 0) {
return 444;
}
}
Media Protection and Hotlink Prevention
Verify the Origin header to ensure asset requests originate from permitted domains:
location ~* \.(png|jpeg|webp|svg|mp4)$ {
valid_referers none blocked server_names *.trustedcdn.com internal.net;
if ($invalid_referer) {
return 403;
}
root /srv/assets/media;
}
Error Response Customization
Redirect failure states to controlled interfaces while suppressing stack traces:
http {
fastcgi_intercept_errors on;
proxy_intercept_errors on;
error_page 403 /denied_access.html;
error_page 404 /page_missing.html;
error_page 500 502 503 504 /service_unavailable.html;
location = /denied_access.html {
root /srv/errors;
internal;
}
location = /page_missing.html {
root /srv/errors;
internal;
}
}
Directory Security Standards
| Service Tier | Permission Strategy | Risk Assessment |
|---|---|---|
| Dynamic Application Cluster | Directories: 755 Files: 644 Owner: root:root | High isolation. Static assets remain immutable, execute permissions revoked, secure deployment pipeline enforced. |
| Static Asset Repository | Directories: 755 Files: 644 Owner: root:root | Maximum safety. Zero write capabilities, read-only distribution layer. |
| User Upload Gateway | Upload Dir: 775 (owned by websvc) Other Files: 644/755 (root) | Moderate risk. Write capability required for ingestion, but read access disabled via internal routing or firewall rules. |
Bot Mitigation and Method Restrictions
Filter automated crawlers by inspecting the User-Agent string:
if ($http_user_agent ~* (Python-urllib|curl/|wget/|Go-http-client|Apache-HttpClient)) {
return 403;
}
Limit allowed HTTP verbs to reduce vector exposure:
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 501;
}
Network Boundaries and Flow Control
Cap upload payloads to prevent memory exhaustion attacks:
client_max_body_size 16m;
Tune connection lifecycles to balance resource retention and cleanup frequency:
keepalive_timeout 65;
client_header_timeout 30;
client_body_timeout 30;
send_timeout 45;
Bandwidth Comprestion Settings
Enable adaptive encoding to reduce payload weight while preserving bandwidth:
gzip on;
gzip_comp_level 6;
gzip_min_length 256;
gzip_buffers 16 32k;
gzip_proxied any;
gzip_vary on;
gzip_types application/javascript text/css application/json image/svg+xml text/plain;
gzip_disable "msie6";
Caching Strategies
Assign browser expiry headers to static resources to decrease repeat request volume:
location ~* \.(ico|pdf|flv|woff2)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
location ~* \.(js|css|map)$ {
expires 30d;
add_header Cache-Control "public";
}
location /dynamic/ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
FastCGI Pipeline Optimization
Configure backend communication buffers and cache lifecycles for PHP or Python gateways:
fastcgi_connect_timeout 30;
fastcgi_send_timeout 60;
fastcgi_read_timeout 60;
fastcgi_buffer_size 128k;
fastcgi_buffers 8 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_cache_path /var/cache/fcgi levels=1:2 keys_zone=app_cache:256m inactive=12h max_size=10g use_temp_path=off;
fastcgi_cache app_cache;
fastcgi_cache_valid 200 301 2h;
fastcgi_cache_valid 404 1m;
fastcgi_cache_min_uses 2;
fastcgi_cache_key $scheme$request_method$host$request_uri;
Automated Log Segmnetation
Implement daily archiving to maintain consistent storage consumption and streamline analysis pipelines:
#!/bin/bash
LOG_DIR="/var/log/webgw"
ARCHIVE_DIR="${LOG_DIR}/archive_$(date +%Y-%m)"
mkdir -p "$ARCHIVE_DIR"
for logfile in access.log error.log; do
if [ -f "${LOG_DIR}/${logfile}" ]; then
mv "${LOG_DIR}/${logfile}" "${ARCHIVE_DIR}/${logfile}_$(date +%F).gz"
gzip "${ARCHIVE_DIR}/${logfile}_$(date +%F)"
fi
done
/usr/local/nginx/sbin/nginx -s reopen
Schedule execution via system crontab:
0 0 * * * /opt/scripts/nginx_log_rotate.sh >/dev/null 2>&1
Authentication Layering
Protect sensitive administrative routes using digest credentials:
location /admin-console/ {
auth_basic "Restricted Zone";
auth_basic_user_file /etc/nginx/.htpasswd;
satisfy any;
}
htpasswd -cb /etc/nginx/.htpasswd operator Sec@rePass!2024
chmod 600 /etc/nginx/.htpasswd
chown www-data:www-data /etc/nginx/.htpasswd
Distributed Denial Service Countermeasures
Enforce rate thresholds per client identifier and virtual endpoint:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $server_name zone=vhost_limit:10m rate=100r/s;
server {
limit_conn conn_limit 20;
limit_conn vhost_limit 500;
limit_req zone=api_limit burst=15 nodelay;
limit_rate 512k;
}
Build Metadata Verification
Retrieve compilation flags to audit enabled modules and dependency configurations:
/usr/local/nginx/sbin/nginx -V 2>&1 | tee build_flags.txt