Install
$ agentstack add skill-fellipeutaka-leon-nginx ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Nginx Expert
When to Use
- Creating or reviewing nginx configuration files
- Setting up reverse proxy or load balancer
- Configuring SSL/TLS and HTTPS
- Implementing rate limiting or access control
- Optimizing performance (caching, gzip, keepalive)
- WebSocket proxying
- Serving static content
- Debugging nginx issues (502, 504, connection errors)
Out of scope (recommend dedicated skills):
- Docker containerization -> docker expert
- Kubernetes ingress controllers -> kubernetes expert
- Application-level code -> relevant framework skill
Core Principles
- Security-first -- TLS 1.2+ only, strong ciphers, no server tokens, rate limiting
- Minimal exposure -- only expose what's needed, hide upstream details
- Performance -- leverage caching, gzip, keepalive connections, sendfile
- Clarity -- well-organized config with comments, logical server/location blocks
Configuration File Structure
main (global)
├── events { } -- connection processing
├── http { } -- HTTP server config
│ ├── upstream { } -- backend server groups
│ ├── server { } -- virtual hosts
│ │ ├── location { } -- request routing
│ │ └── location { }
│ └── server { }
└── stream { } -- TCP/UDP proxying
Key rules:
- Simple directives end with semicolon (
;) - Block directives use braces (
{}) - Directives inherit from parent contexts unless overridden
- Comments start with
# - Default config path:
/etc/nginx/nginx.conf
Process Management
nginx -t # test configuration syntax
nginx -s reload # graceful reload (re-read config)
nginx -s quit # graceful shutdown
nginx -s stop # fast shutdown
nginx -s reopen # reopen log files
Location Matching
Priority order (highest to lowest):
| Modifier | Type | Example | |---|---|---| | = | Exact match | location = / | | ^~ | Prefix (skip regex) | location ^~ /images/ | | ~ | Regex (case-sensitive) | location ~ \.php$ | | ~* | Regex (case-insensitive) | location ~* \.(jpg\|png)$ | | (none) | Prefix | location /docs/ |
Algorithm: Check all prefix locations (remember longest) -> if longest has ^~, use it -> check regex in config order (first match wins) -> fallback to longest prefix.
Serving Static Content
server {
listen 80;
server_name example.com;
root /var/www/html;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|png|jpg|gif|ico|svg|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
root vs alias
# root: appends URI to path
location /images/ {
root /data; # /images/photo.jpg -> /data/images/photo.jpg
}
# alias: replaces matched location
location /images/ {
alias /data/photos/; # /images/photo.jpg -> /data/photos/photo.jpg
}
Reverse Proxy
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
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_pass URI Behavior
# WITH trailing slash -- strips location prefix
location /api/ {
proxy_pass http://backend/; # /api/users -> /users
}
# WITHOUT trailing slash -- passes full URI
location /api/ {
proxy_pass http://backend; # /api/users -> /api/users
}
Full proxy and upstream reference: [references/proxy-upstream.md](references/proxy-upstream.md)
Load Balancing
# Round-robin (default)
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
# Weighted
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com weight=1;
}
# Least connections
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
}
# IP hash (session persistence)
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
}
Server Parameters
weight=N-- server weight (default 1)max_fails=N-- failures before marking unavailable (default 1)fail_timeout=T-- failure window AND unavailability duration (default 10s)max_conns=N-- max simultaneous connections (default 0 = unlimited)backup-- only used when primary servers are all downdown-- permanently marked as unavailable
Upstream Keepalive
upstream backend {
server backend1.example.com;
keepalive 32;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Full proxy and upstream reference: [references/proxy-upstream.md](references/proxy-upstream.md)
SSL/TLS
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
# HTTP to HTTPS redirect
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Full SSL/TLS reference (OCSP, SNI, cert chains, hardening): [references/ssl-tls.md](references/ssl-tls.md)
Rate Limiting
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
}
rate=Nr/sorrate=Nr/m-- requests per second/minute (leaky bucket)burst=N-- allow N excess requests to queuenodelay-- process burst immediately without delay$binary_remote_addr-- preferred over$remote_addr(4/16 bytes vs string)
Full security reference: [references/security.md](references/security.md)
Gzip Compression
http {
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_vary on;
gzip_proxied any;
gzip_types text/plain text/css text/javascript
application/javascript application/json
application/xml image/svg+xml;
}
text/html is always compressed -- don't list it in gzip_types.
WebSocket Proxying
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
}
Default proxy_read_timeout is 60s -- idle WebSocket connections will be closed. Increase the timeout or use backend ping frames.
Logging
http {
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
server {
location /health {
access_log off;
return 200 "OK";
}
}
}
Performance Tuning
worker_processes auto;
events {
worker_connections 1024;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65s;
keepalive_requests 1000;
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
Full caching and performance reference: [references/caching-performance.md](references/caching-performance.md)
Production Checklist
- [ ]
nginx -tpasses - [ ]
server_tokens off - [ ] SSL/TLS with TLSv1.2+ only
- [ ] HTTP to HTTPS redirect
- [ ] HSTS header enabled
- [ ] Security headers (X-Frame-Options, CSP, X-Content-Type-Options)
- [ ] Rate limiting on sensitive endpoints
- [ ]
client_max_body_sizeset appropriately - [ ] Gzip compression enabled
- [ ] Static asset caching with
expires - [ ] Logging configured with rotation
- [ ] Hidden files blocked (
location ~ /\. { deny all; }) - [ ] Upstream keepalive with
proxy_http_version 1.1 - [ ]
worker_processes auto,sendfile on,tcp_nopush on
Anti-Patterns
| Don't | Do Instead | |---|---| | Use if for complex routing | Use map + variables or multiple location blocks | | Leave server_tokens on | server_tokens off; | | Allow TLSv1.0/1.1 | ssl_protocols TLSv1.2 TLSv1.3; | | Use proxy_pass without Host header | Set proxy_set_header Host $host; | | Skip proxy_http_version with keepalive | proxy_http_version 1.1; and clear Connection header | | Hardcode IPs in config | Use upstream blocks with named servers | | Ignore proxy_read_timeout for long requests | Tune per-location based on expected response times | | Use root inside if blocks | Place root in server or location context |
Diagnostics
502 Bad Gateway
- Backend is down or not listening
- Check
proxy_passURL and backend connectivity
504 Gateway Timeout
- Backend is too slow -- increase
proxy_read_timeout
413 Request Entity Too Large
- Increase
client_max_body_size
Configuration Errors
- Always test before reload:
nginx -t - Check error log:
tail -f /var/log/nginx/error.log
Key Variables
| Variable | Description | |---|---| | $host | Host header or server name | | $remote_addr | Client IP address | | $binary_remote_addr | Client IP in binary (for limit zones) | | $proxy_add_x_forwarded_for | X-Forwarded-For + client IP | | $scheme | http or https | | $request_uri | Full original URI with query string | | $uri | Normalized URI (without query string) | | $args | Query string | | $upstream_response_time | Response time from upstream | | $upstream_cache_status | Cache hit/miss status |
Reference Index
| Topic | File | |-------|------| | Proxy module, upstream, load balancing, timeouts, buffering, keepalive | [references/proxy-upstream.md](references/proxy-upstream.md) | | SSL/TLS, HTTPS, certificates, OCSP, SNI, HTTP/2, HTTP/3 | [references/ssl-tls.md](references/ssl-tls.md) | | Security headers, rate limiting, access control, client limits | [references/security.md](references/security.md) | | Proxy caching, gzip, performance tuning, open file cache | [references/caching-performance.md](references/caching-performance.md) | | Full config patterns: API gateway, SPA, microservices, logging | [references/common-patterns.md](references/common-patterns.md) |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: fellipeutaka
- Source: fellipeutaka/leon
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.