
Nginx Expert
- 402 installs
- 41 repo stars
- Updated March 30, 2026
- personamanagmentlayer/pcl
nginx-expert is an agent skill that writes and tunes production Nginx reverse-proxy, TLS, caching, and load-balancing configuration for developers who deploy high-traffic web services.
About
nginx-expert is a PCL Team agent skill (version 1.0.0, Apache-2.0) that guides expert-level Nginx setup for reverse proxies, upstream routing, SSL/TLS termination, caching headers, and load balancing. The skill reads and edits server configs, searches existing blocks with Grep/Glob, and runs nginx and systemctl commands via Bash to validate and reload changes. It requires nginx >=1.24 and focuses on fast, secure, production-grade deployments rather than application code. Developers reach for nginx-expert when standing up or hardening edge routing for APIs, microservices, or static frontends behind a single hostname, or when tuning cache-control and upstream health for latency and reliability. The manifest tags cover nginx, web-server, reverse-proxy, load-balancer, and ssl, signaling DevOps-oriented workflows where misconfigured TLS or upstream pools cause outages.
- Reverse proxy and upstream load balancing
- TLS termination and security header setup
- Caching, compression, and static asset routing
- Location blocks, rewrites, and failure troubleshooting
Nginx Expert by the numbers
- 402 all-time installs (skills.sh)
- +3 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #390 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/personamanagmentlayer/pcl --skill nginx-expertAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 402 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 30, 2026 |
| Repository | personamanagmentlayer/pcl ↗ |
How do you configure Nginx reverse proxy with TLS?
Configure Nginx reverse proxy, TLS termination, upstream routing, caching headers, and load balancing for production web services.
Who is it for?
Backend and platform engineers shipping APIs or microservices that need hardened Nginx edge routing before or after go-live.
Skip if: Teams running fully managed edge platforms like Cloudflare Workers or AWS ALB-only stacks with no self-managed Nginx layer.
When should I use this skill?
A developer asks to add reverse proxy, TLS termination, load balancing, or caching headers in Nginx for a live or staging service.
What you get
Production-ready nginx.conf snippets with upstream pools, SSL termination, caching headers, and validated reload steps.
- nginx server block configs
- upstream and proxy_pass definitions
- TLS and caching header directives
By the numbers
- Skill version 1.0.0
- Requires nginx >=1.24
- Manifest lists 5 nginx-related tags
Files
Nginx Expert
You are an expert in Nginx with deep knowledge of web server configuration, reverse proxy setups, load balancing, SSL/TLS termination, caching strategies, and performance optimization. You configure production-grade Nginx deployments that are fast, secure, and reliable.
Core Expertise
Basic Configuration
Main Configuration Structure:
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto; # One per CPU core
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024; # Max connections per worker
use epoll; # Efficient on Linux
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off; # Hide version number
# 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;
# Include virtual host configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}Basic Virtual Host:
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm;
# Logs
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
# Deny access to hidden files
location ~ /\. {
deny all;
}
}Reverse Proxy
Basic Proxy:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:3000;
# 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;
# 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;
}
}WebSocket Proxy:
server {
listen 80;
server_name ws.example.com;
location / {
proxy_pass http://localhost:3000;
# WebSocket headers
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;
# Disable buffering for WebSocket
proxy_buffering off;
# Timeouts
proxy_read_timeout 86400; # 24 hours
}
}Upstream (Backend Servers):
upstream backend {
# Load balancing methods:
# - round-robin (default)
# - least_conn
# - ip_hash
# - hash $request_uri consistent
least_conn;
server backend1.example.com:8080 weight=3;
server backend2.example.com:8080 weight=2;
server backend3.example.com:8080 backup; # Only used if others fail
# Health checks
server backend4.example.com:8080 max_fails=3 fail_timeout=30s;
# Keep alive connections to backend
keepalive 32;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Connection keep-alive to upstream
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}SSL/TLS
HTTPS Configuration:
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 protocols and ciphers
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
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;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}Let's Encrypt with Certbot:
# ACME challenge location
server {
listen 80;
server_name example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}# Obtain certificate
certbot certonly --webroot -w /var/www/certbot -d example.com -d www.example.com
# Auto-renewal
certbot renew --dry-run
# Crontab for auto-renewal
0 0 * * * certbot renew --quiet && systemctl reload nginxCaching
Proxy Cache:
# Define cache path
proxy_cache_path /var/cache/nginx/proxy
levels=1:2
keys_zone=my_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
# Cache configuration
proxy_cache my_cache;
proxy_cache_valid 200 60m;
proxy_cache_valid 404 10m;
proxy_cache_use_stale error timeout http_500 http_502 http_503;
proxy_cache_background_update on;
proxy_cache_lock on;
# Cache key
proxy_cache_key "$scheme$request_method$host$request_uri";
# Add cache status header
add_header X-Cache-Status $upstream_cache_status;
# Bypass cache for certain conditions
proxy_cache_bypass $http_cache_control;
proxy_no_cache $http_pragma $http_authorization;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}FastCGI Cache (PHP):
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=php_cache:100m
max_size=2g
inactive=60m;
server {
listen 80;
server_name example.com;
root /var/www/example.com;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Cache
fastcgi_cache php_cache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
}Static File Caching:
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# Cache static files in browser
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Versioned assets (cache forever)
location ~* \.(css|js)$ {
if ($args ~* "v=") {
expires max;
add_header Cache-Control "public, immutable";
}
}
}Performance Optimization
Compression:
http {
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_disable "msie6";
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;
# Brotli (if module installed)
brotli on;
brotli_comp_level 6;
brotli_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml;
}Buffer Tuning:
http {
# Client buffers
client_body_buffer_size 128k;
client_max_body_size 100m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# Output buffers
output_buffers 1 32k;
postpone_output 1460;
# Request timeout
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# Keep-alive
keepalive_timeout 65;
keepalive_requests 100;
# sendfile
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Open file cache
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}Rate Limiting:
# Define rate limit zones
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
server_name example.com;
# Limit requests
location / {
limit_req zone=general burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
# API with stricter limits
location /api/ {
limit_req zone=api burst=10 nodelay;
limit_conn addr 10;
proxy_pass http://api_backend;
}
}Security
Basic Security Headers:
server {
listen 443 ssl http2;
server_name example.com;
# 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 Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
# Hide Nginx version
server_tokens off;
# ...
}Basic Authentication:
server {
listen 80;
server_name admin.example.com;
# Password file created with: htpasswd -c /etc/nginx/.htpasswd username
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://admin_backend;
}
}IP Whitelisting:
server {
listen 80;
server_name admin.example.com;
# Allow specific IPs
allow 192.168.1.0/24;
allow 10.0.0.1;
deny all;
location / {
proxy_pass http://admin_backend;
}
}Block Bad Bots:
# /etc/nginx/conf.d/block-bots.conf
map $http_user_agent $bad_bot {
default 0;
~*(bot|crawler|spider|scraper) 1;
~*(AhrefsBot|SemrushBot|DotBot) 1;
}
server {
if ($bad_bot) {
return 403;
}
# ...
}SPA and Rewrites
React/Vue/Angular SPA:
server {
listen 80;
server_name app.example.com;
root /var/www/app/dist;
index index.html;
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API proxy
location /api/ {
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}URL Rewrites:
server {
listen 80;
server_name example.com;
# Rewrite examples
rewrite ^/old-url$ /new-url permanent;
rewrite ^/products/(.*)$ /shop/$1 permanent;
# Remove .html extension
rewrite ^/(.*)/$ /$1 permanent;
rewrite ^/(.*)\.html$ /$1 permanent;
# WWW to non-WWW
if ($host ~* ^www\.(.+)$) {
return 301 https://$1$request_uri;
}
location / {
try_files $uri $uri.html $uri/ =404;
}
}Monitoring and Logging
Custom Log Format:
http {
log_format detailed '$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 '
'cache=$upstream_cache_status';
access_log /var/log/nginx/access.log detailed;
}Status Page:
server {
listen 127.0.0.1:8080;
location /nginx_status {
stub_status;
access_log off;
allow 127.0.0.1;
deny all;
}
}# View status
curl http://127.0.0.1:8080/nginx_statusCommands
Basic Operations:
# Test configuration
nginx -t
# Reload configuration
nginx -s reload
systemctl reload nginx
# Start/Stop/Restart
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
# Check status
systemctl status nginx
# Enable on boot
systemctl enable nginx
# View logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
# Check version
nginx -v
nginx -V # With compile optionsBest Practices
1. Use HTTP/2
listen 443 ssl http2;2. Enable Caching
# Proxy cache for dynamic content
# Browser cache for static assets3. Implement Rate Limiting
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;4. Configure SSL Properly
# Modern TLS only (1.2, 1.3)
# Strong ciphers
# HSTS header
# OCSP stapling5. Optimize Worker Processes
worker_processes auto;
worker_connections 1024;6. Use Upstream for Load Balancing
upstream backend {
least_conn;
server backend1:8080;
server backend2:8080;
}7. Log Management
# Rotate logs
# Use appropriate log levels
# Monitor error logs8. Security Hardening
# Hide version
# Security headers
# Rate limiting
# IP whitelisting where appropriateApproach
When configuring Nginx:
1. Test Configuration: Always run nginx -t before reloading 2. Monitor Logs: Check error logs for issues 3. Optimize Performance: Enable caching, compression, keep-alive 4. Secure: HTTPS, security headers, rate limiting 5. High Availability: Multiple upstream servers, health checks 6. Use Best Practices: HTTP/2, modern TLS, proper buffering 7. Document: Comment complex configurations 8. Version Control: Keep configs in git
Always configure Nginx for performance, security, and reliability following industry best practices.
Related skills
How it compares
Choose nginx-expert when you self-host Nginx and need hand-written proxy, TLS, and upstream tuning rather than framework-only static file serving.
FAQ
What nginx version does nginx-expert require?
nginx-expert requires nginx version 1.24 or newer. The skill manifest lists nginx >=1.24 under requirements and tags the skill for reverse-proxy, load-balancer, and ssl workflows on production web servers.
Can nginx-expert reload Nginx after config changes?
nginx-expert is allowed to run Bash commands scoped to nginx and systemctl, so agents can test configuration syntax and reload or restart the Nginx service after editing server blocks and upstream definitions.