From agent-almanac
Configures reverse proxy patterns for Nginx, Traefik, and ShinyProxy including WebSocket proxying, path/host-based routing, SSL termination, and Docker label auto-discovery.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agent-almanac:configure-reverse-proxyThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Set up reverse proxy patterns for routing traffic to backend services using Nginx, Traefik, or ShinyProxy.
Set up reverse proxy patterns for routing traffic to backend services using Nginx, Traefik, or ShinyProxy.
| Feature | Nginx | Traefik |
|---|---|---|
| Configuration | Static files | Docker labels / dynamic |
| Auto-discovery | No (manual) | Yes (Docker provider) |
| Let's Encrypt | Via certbot | Built-in ACME |
| Dashboard | No (3rd party) | Built-in |
| WebSocket | Manual config | Automatic |
| Best for | Static config, high traffic | Dynamic Docker environments |
server {
listen 80;
location /api/ {
proxy_pass http://api:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /app/ {
proxy_pass http://webapp:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
}
Note: Trailing / on proxy_pass strips the location prefix. proxy_pass http://api:8000/; with location /api/ forwards /api/users as /users.
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://api:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://webapp:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
WebSockets require upgrade headers. Essential for Shiny, Socket.IO, and live reload:
location /ws/ {
proxy_pass http://app:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
For Shiny apps specifically:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location / {
proxy_pass http://shiny:3838;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400;
proxy_buffering off;
}
}
Expected: WebSocket connections establish and persist.
On failure: Check proxy_http_version 1.1 is set. Verify Upgrade and Connection headers.
docker-compose.yml:
services:
traefik:
image: traefik:v3.2
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
api:
image: myapi:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
webapp:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.webapp.entrypoints=websecure"
- "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
- "traefik.http.services.webapp.loadbalancer.server.port=3000"
volumes:
letsencrypt:
Expected: Traefik auto-discovers services via labels, provisions SSL certificates.
services:
api:
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.middlewares=strip-api"
- "traefik.http.middlewares.strip-api.stripprefix.prefixes=/api"
- "traefik.http.services.api.loadbalancer.server.port=8000"
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
- "traefik.http.middlewares.security.headers.stsSeconds=63072000"
- "traefik.http.middlewares.security.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security.headers.frameDeny=true"
- "traefik.http.routers.app.middlewares=ratelimit,security"
# Nginx: test config
docker compose exec nginx nginx -t
# Check routing
curl -H "Host: api.example.com" http://localhost/health
# Check WebSocket (needs wscat: npm install -g wscat)
wscat -c ws://localhost/ws/
# Traefik dashboard (if enabled)
# http://localhost:8080/dashboard/
Expected: Requests route to correct backends. WebSocket upgrades succeed.
Host, X-Real-IP, X-Forwarded-For headersdocker compose restartproxy_pass http://app/ vs http://app behaves differently with path stripping in Nginx.proxy_read_timeout is 60s. Long-lived WebSocket connections need 86400 (24h)./var/run/docker.sock in Traefik gives it full Docker access. Use ro mount and consider socket proxy.resolver 127.0.0.11 for Docker's internal DNS with dynamic services.proxy_buffering off: Shiny and SSE endpoints need proxy_buffering off for real-time streaming.configure-nginx - detailed Nginx configuration with SSL and security headersdeploy-shinyproxy - ShinyProxy for containerized Shiny app hostingsetup-compose-stack - compose stack that uses a reverse proxyconfigure-api-gateway - API gateway patterns with Kong and Traefiknpx claudepluginhub pjt222/agent-almanacSets up Nginx as a web server and reverse proxy with SSL/TLS termination, static file serving, rate limiting, load balancing, and security headers.
Guides Nginx configuration for reverse proxies, SSL/TLS hardening, load balancing strategies, and performance tuning. Useful for proxy_pass, upstream blocks, certbot, gzip, and rate limiting.
Turns application stacks into production deployments on Linux VPS with Docker Compose, Traefik, private registries, SSH tunnels, backups, and rollback planning.