NGINX mTLS Client Certificate Auth Prompt
Configure mutual TLS so NGINX requires and verifies client certificates — for service-to-service or partner APIs — with correct CA trust, verification depth, and the right variables passed to your backend.
- Target user
- Engineers locking down an endpoint to clients holding a valid certificate
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior infrastructure engineer who has rolled out mutual TLS without locking yourself out. You know the difference between `on` and `optional` verification, you set the trust chain correctly, and you pass verification results to the backend so the app can make authorization decisions.
I will provide:
- Which endpoint/server block needs mTLS: [DESCRIBE — whole server or a location]
- The CA that issues client certs: [DESCRIBE — internal CA, partner CA, file path]
- Whether ALL clients must present a cert or only some paths: [DESCRIBE]
- What the backend needs to know about the cert (subject, fingerprint): [DESCRIBE]
- Revocation needs (CRL/OCSP): [DESCRIBE OR "none yet"]
Build the config:
1. **Trust setup** — `ssl_client_certificate` (the CA bundle to verify against) and, if relevant, `ssl_verify_depth`. Explain that this CA file determines who is trusted, and the risk of pointing it at a public CA (anyone with a cert from it passes).
2. **Verification mode** — `ssl_verify_client on;` for hard enforcement, or `optional` when you want to verify-if-present and decide in config. Show how to reject with `if ($ssl_client_verify != SUCCESS) { return 403; }` only where `if` is safe, or prefer a `map`-driven gate.
3. **Per-path scoping** — if only some paths need mTLS, show the `optional` + per-location enforcement pattern rather than turning it on for the whole listener.
4. **Passing identity to the backend** — `proxy_set_header` lines exposing `$ssl_client_s_dn`, `$ssl_client_verify`, and `$ssl_client_fingerprint` so the app can authorize on identity.
5. **Revocation** — show `ssl_crl` if a CRL is provided, and note OCSP limitations for client certs.
Output: (a) the complete commented config, (b) a table of each `$ssl_client_*` variable and what the backend should do with it, (c) an `openssl s_client`/`curl --cert` test proving both a valid cert succeeds and no cert is rejected, plus `nginx -t`. Validate with `nginx -t` and reload — test from a second machine so you don't lock yourself out.
Why this prompt works
Mutual TLS fails in two opposite, equally bad ways: too loose (you trust a CA so broad that any cert it ever signed gets in) or too tight (you flip ssl_verify_client on on the whole listener and lock out your health checks, your CI, and yourself). This prompt forces both decisions into the open. Step one makes the model reason explicitly about which CA bundle ssl_client_certificate trusts, because that single file is the entire authorization boundary — point it at a public CA and you’ve built a door with no lock.
The per-path scoping step addresses the most common operational mistake. Most real systems want mTLS on a partner-facing API but not on /health or the human-facing pages, and the clean way to do that is optional verification plus a config-level gate, not a separate listener or a blanket on. Surfacing that pattern prevents the lockout that turns an mTLS rollout into an incident.
Finally, the identity hand-off is what makes mTLS useful rather than just restrictive. Verifying the cert is only half the job; the backend needs $ssl_client_s_dn or $ssl_client_fingerprint to map the connection to an actual identity and authorize it. The two-sided test — valid cert succeeds, no cert is rejected, run from a second machine — is the guardrail that keeps you from confidently shipping a config that either lets everyone in or locks everyone out.
Related prompts
-
NGINX Config Security Audit Prompt
Audit an NGINX config for the classic misconfigurations — version leakage, missing security headers, open proxy, path traversal, exposed dotfiles — and get a prioritized fix list with exact directives, not a generic checklist.
-
NGINX TLS/SSL Hardening Prompt
Harden your NGINX TLS config to a modern, A-grade baseline — protocols, cipher suites, HSTS, OCSP stapling, session settings — without breaking older clients you actually need to support.