# Nginx Kit ## Start ```bash git clone https://git.forge.st/ops/nginx-kit.git /opt/nginx-kit ln -s /opt/nginx-kit /etc/nginx/kit ``` ### Update ```bash cd /opt/nginx-kit git pull nginx -t systemctl reload nginx ``` ## Contexts This repository is organized by nginx context: - `http/`: snippets that must be included inside `http {}`. - `listen/`: listener snippets for `server {}` blocks. - `fastcgi/`: FastCGI-specific snippets for `location {}` or `server {}` blocks. - `ssl/`: HTTPS and TLS snippets for `server {}` blocks. - `proxy_pass/`: reverse proxy snippets for `location {}` blocks. - `redirect/`: host and canonical URL redirects for `server {}` blocks. - `templates/`: copy-and-edit starter snippets such as certificates. - `examples/`: working examples showing how to compose the snippets. ## Common combinations ### HTTPS site Include these inside a `server {}` block: ```nginx server { # ... include kit/listen/http.conf; include kit/listen/https-http2.conf; include snippets/cert/mydomain.com.conf; include kit/security.conf; include kit/ssl/security.conf; include kit/ssl/hsts.conf; include kit/ssl/force.conf; # ... } ``` See [examples/example.com.conf](examples/example.com.conf:1) for the full server-level example. For widest compatibility, the examples use `listen ... http2` instead of the standalone `http2 on;` directive. The standalone `http2` directive appeared in nginx `1.25.1` on `2023-06-13`, while Ubuntu-packaged nginx `1.24.x` rejects it. For nginx `1.25.1+`, you can use the modern split form instead: ```nginx server { include kit/listen/http.conf; include kit/listen/https.conf; include kit/listen/http2.conf; # ... } ``` ### Optional `http {}` features These snippets are independent `http {}`-level features: ```nginx http { include kit/http/gzip.conf; } ``` Use `kit/http/gzip.conf` when you want nginx to compress common text-based responses. It is not specific to proxying or websocket traffic. ```nginx http { include kit/http/websocket-map.conf; } ``` Use `kit/http/websocket-map.conf` only when a `location {}` will include `kit/proxy_pass/websocket.conf`. ```nginx http { include kit/http/log-format-upstream.conf; } ``` Use `kit/http/log-format-upstream.conf` when you want a reusable access log format with upstream timing fields. It only defines `upstream_timing`; each server still opts in with its own `access_log` directive. ### Reverse proxy Plain HTTP reverse proxying only needs the `location {}`-level proxy snippets: ```nginx server { # ... include kit/listen/http.conf; location / { include kit/proxy_pass/forwarded.conf; include kit/proxy_pass/timeout-300.conf; proxy_pass http://app_backend; } } ``` ### Streaming reverse proxy For SSE, token streaming, or other incremental responses, add the streaming and long-timeout snippets to the proxied location: ```nginx http { include kit/http/log-format-upstream.conf; server { include kit/listen/http.conf; access_log /var/log/nginx/app.access.log upstream_timing; location /events/ { include kit/proxy_pass/forwarded.conf; include kit/proxy_pass/streaming.conf; include kit/proxy_pass/timeout-300.conf; proxy_pass http://app_backend; } } } ``` Use `kit/proxy_pass/streaming.conf` only for locations that genuinely need incremental flushing. It intentionally changes buffering behavior and forces HTTP/1.1 for that location. ### Websocket reverse proxy Websocket proxying adds one `http {}`-level dependency plus the websocket location snippet: ```nginx http { include kit/http/websocket-map.conf; server { include kit/listen/http.conf; include kit/listen/https-http2.conf; location /ws/ { include kit/proxy_pass/forwarded.conf; include kit/proxy_pass/websocket.conf; include kit/proxy_pass/timeout-300.conf; proxy_pass http://app_backend; } } } ``` See [examples/reverse-proxy.nginx.conf](examples/reverse-proxy.nginx.conf:1) for a complete standalone config. ## Templates ### SSL certs ```bash cd /etc/nginx mkdir -p snippets/cert cp kit/templates/cert/example.com.conf snippets/cert/mydomain.com.conf vi snippets/cert/mydomain.com.conf ``` Replace the certificate paths with yours, then include the snippet in your `server {}` block: ```nginx server { # ... include snippets/cert/mydomain.com.conf; include kit/security.conf; include kit/ssl/security.conf; include kit/ssl/hsts.conf; # ... } ``` ## Snippet reference - `kit/http/gzip.conf`: gzip compression for common text-based responses. Must be included inside `http {}`. - `kit/http/log-format-upstream.conf`: defines the `upstream_timing` access log format with upstream timing fields. Must be included inside `http {}`. - `kit/http/websocket-map.conf`: defines `$connection_upgrade` for websocket proxying. Must be included inside `http {}`. - `kit/listen/http.conf`: IPv4 and IPv6 HTTP listeners for `server {}`. - `kit/listen/https.conf`: IPv4 and IPv6 HTTPS listeners for `server {}` without enabling HTTP/2. - `kit/listen/http2.conf`: standalone `http2 on;` snippet for nginx `1.25.1+`. - `kit/listen/https-http2.conf`: IPv4 and IPv6 HTTPS listeners with HTTP/2 for `server {}`. Uses `listen ... http2` for nginx `1.24.x` compatibility. - `kit/security.conf`: common low-risk security headers and host normalization. Intended for `server {}`. - `kit/security-legacy.conf`: optional legacy compatibility headers such as `X-Download-Options` and `X-Permitted-Cross-Domain-Policies`. - `kit/fastcgi/hide-powered-by.conf`: hides `X-Powered-By` from FastCGI upstream responses. - `kit/fastcgi/timeout-300.conf`: longer FastCGI timeouts. Intended for `location {}`. - `kit/ssl/security.conf`: TLS protocol and session resumption settings. Intended for `server {}`. - `kit/ssl/hsts.conf`: HSTS header for HTTPS responses. Intended for `server {}`. - `kit/ssl/hsts-preload.conf`: HSTS variant with `preload`. Use only if the whole domain tree is preload-safe. - `kit/ssl/force.conf`: redirects HTTP requests to HTTPS. Intended for `server {}`. - `kit/redirect/to-primary-domain.conf`: redirects aliases to the primary `server_name`. Intended for `server {}`. - `kit/proxy_pass/forwarded.conf`: standard reverse proxy headers. Intended for `location {}`. - `kit/proxy_pass/hide-powered-by.conf`: hides `X-Powered-By` from proxied upstream responses. - `kit/proxy_pass/https-upstream.conf`: enables SNI for HTTPS upstreams. Intended for `location {}`. - `kit/proxy_pass/streaming.conf`: disables proxy buffering for streaming responses and requests. Intended for `location {}`. - `kit/proxy_pass/websocket.conf`: websocket upgrade headers. Requires `kit/http/websocket-map.conf`. - `kit/proxy_pass/timeout-300.conf`: longer proxy timeouts. Intended for `location {}`. ## Validation Run the Docker-based syntax checks from the repo root: ```powershell ./scripts/validate-docker.ps1 ``` The script validates: - [examples/example.com.conf](examples/example.com.conf:1) as a server-level snippet. - [examples/reverse-proxy.nginx.conf](examples/reverse-proxy.nginx.conf:1) as a complete nginx config. - The optional logging, streaming, HTTPS-upstream, and timeout snippets via synthetic configs assembled in the validation script. ## Notes - `gzip_proxied` does not remove `ETag` or `Last-Modified` headers. It only controls when nginx may gzip requests that arrived through another proxy. - `text/html` does not need to appear in `gzip_types`; nginx compresses it automatically. - Gzip over HTTPS can contribute to BREACH-style risk for responses that reflect attacker-controlled input alongside secrets. Keep that in mind for highly sensitive dynamic pages. - `kit/security.conf` intentionally does not set `X-Robots-Tag: none` or `X-XSS-Protection: 1; mode=block`; those are too risky or too obsolete for a default site-wide baseline. - The standalone `http2 on;` directive appeared in nginx `1.25.1` on `2023-06-13`. For broader compatibility, this repository currently prefers `listen 443 ssl http2;` and `listen [::]:443 ssl http2;`. - If you are standardizing on nginx `1.25.1+`, prefer `kit/listen/https.conf` plus `kit/listen/http2.conf` to avoid the deprecation warnings on modern nginx. - Listener snippets are intentionally minimal. Variants such as `default_server`, `proxy_protocol`, or non-HTTP/2 HTTPS should live in separate project-specific snippets to avoid accidental conflicts.