Front-nginx HTTP/2 and brotli
This runbook captures the infra-level changes needed so the landing page
(/{owner}/{repo}) serves compressed HTML over HTTP/2. These settings
are tuned on the ingress controller (or standalone nginx) that terminates
TLS in front of the Vetrix services — not on the Go backend, the Next.js
web server, or any in-repo nginx.
What changes
| Knob | Before | After |
|---|---|---|
| TLS listener proto | HTTP/1.1 | http2 on; |
| HTML/CSS/JS/JSON | gzip only |
brotli preferred, gzip fallback |
alt-svc header |
absent | h2=":443"; ma=86400 (advisory; monitoring-friendly) |
ingress-nginx (Kubernetes)
The in-repo deployments/kubernetes/ingress.yaml sets the per-ingress
annotation nginx.ingress.kubernetes.io/use-http2: "true" as a belt-and-
braces assertion — the controller defaults to use-http2: "true" since
v0.32, so a regression is visible in the manifest diff.
Brotli and gzip tuning lives on the controller-level ConfigMap. Patch:
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
# Enable brotli for text types. The ingress-nginx image ships
# with the brotli module baked in since v1.9.0. Compression level 5 is
# the documented break-even between CPU and ratio for dynamic pages.
enable-brotli: "true"
brotli-level: "5"
brotli-types: "text/html text/css application/javascript application/json application/xml image/svg+xml"
# Keep gzip on as the fallback for clients that advertise `Accept-Encoding:
# gzip` but not `br` (e.g. old curl, monitoring probes).
use-gzip: "true"
gzip-types: "text/html text/css application/javascript application/json application/xml image/svg+xml"
# Optional: emit Alt-Svc so HTTP/1.1 clients learn about h2.
add-headers: "ingress-nginx/alt-svc"
Then, if you use the add-headers snippet above, create the headers
ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: alt-svc
namespace: ingress-nginx
data:
Alt-Svc: 'h2=":443"; ma=86400'
Apply in order: ConfigMap → rolling restart of the ingress-nginx Deployment → verify per the "Verification" section below.
Standalone nginx
If you terminate TLS on a plain nginx box instead of ingress-nginx, the
equivalent server block looks like:
server {
listen 443 ssl;
http2 on;
brotli on;
brotli_comp_level 5;
brotli_types text/html text/css application/javascript application/json application/xml image/svg+xml;
gzip on;
gzip_types text/html text/css application/javascript application/json application/xml image/svg+xml;
add_header Alt-Svc 'h2=":443"; ma=86400' always;
# ... existing TLS / cert / upstream config unchanged ...
}
The ngx_brotli module must be installed. On Debian/Ubuntu it ships as
libnginx-mod-http-brotli-filter / libnginx-mod-http-brotli-static
from the upstream nginx repo. On RHEL/Amazon Linux it ships as
nginx-module-brotli from EPEL-compatible repos. Do not pull the
module from untrusted third-party repos — the module must come from a
trusted distro or official build.
If brotli cannot be installed on a given deploy, leave the brotli *;
directives commented out — the gzip fallback still gives >60 % of the
compression win.
Verification
Run on each node after rollout:
# HTTP/2 confirmation
curl -I --http2 https://www.gitvetrix.com/ | head -3
# → HTTP/2 200
# → server: nginx
# → alt-svc: h2=":443"; ma=86400
# Brotli confirmation (client advertises br)
curl -sI -H 'Accept-Encoding: br,gzip' https://www.gitvetrix.com/ \
| grep -i content-encoding
# → content-encoding: br
# Fallback confirmation (client advertises only gzip)
curl -sI -H 'Accept-Encoding: gzip' https://www.gitvetrix.com/ \
| grep -i content-encoding
# → content-encoding: gzip
# Non-HTTP/2 client still works
curl -I --http1.1 https://www.gitvetrix.com/ | head -1
# → HTTP/1.1 200 OK
Canary rollout
Follow the normal infra change process: roll one node for ≥ 30 minutes before fleet-wide rollout. Watch the monitoring dashboards for regressions in:
- Request rate on
www.gitvetrix.comandapi.gitvetrix.com. - p95 landing-page response time (should improve, never worsen).
- Error rate — any 5xx uptick is a rollback signal.
nginx_ingress_controller_connectionsandnginx_ingress_controller_requests_totalto confirm HTTP/2 connection multiplexing is actually happening.
Rollback
Drop enable-brotli, brotli-*, and the alt-svc headers from the
ConfigMap and restart the ingress pods. Keep use-http2 enabled —
rolling it back would also undo controller defaults that predate this
change.