Nginx Config Validator
Statically review Nginx configuration structure, proxy settings, TLS, headers, includes, and deployment warnings.
server { ... } block can be a valid file included from http { ... }, while the same server block at the top level of the real nginx.conf is not the same context.Structural findings, context notes, proxy/TLS/header diagnostics, and parsed directive locations will appear here.
A Browser Can Parse the Shape of Nginx Config; Only Nginx Knows the Configuration You Actually Built
Nginx configuration is composed of simple directives ending in a semicolon and block directives containing nested directives between braces. That structure is visible in pasted text, so a browser tool can catch missing semicolons, unclosed quotes, unmatched braces, and several high-confidence directive mistakes.
But Nginx modules define their own directives, accepted arguments, allowed contexts, and runtime behavior. Dynamic modules can add vocabulary this page has never heard of. An includecan change the effective configuration completely. That is why unknown directives are not naively labelled invalid here.
nginx -t Does More Than Count Braces
Nginx documents -t as testing configuration syntax and trying to open files referenced by the configuration. A browser cannot perform the second half. It cannot confirm a certificate file exists, an included file parses, a log directory is writable, a dynamic module is installed, or a referenced path is correct on the target machine.
Use this page before or during editing. Use nginx -tagainst the real deployment before reload. When includes make the source hard to reason about, nginx -T additionally dumps the configuration Nginx sees.
“This server Block Is Invalid” Depends on Whether You Pasted nginx.conf or an Included File
A virtual-host file might contain only server { ... } because the main nginx.conf includes it from inside http { ... }. The snippet is valid in that parent context even though the same text would not be a complete top-level configuration.
The source-mode selector exists to avoid a common static-linter mistake: judging every snippet as though it starts at Nginx's main context.
A Trailing Slash on proxy_pass Can Change the Upstream URI
location /api/ {
proxy_pass http://backend/;
}
location /api/ {
proxy_pass http://backend;
}Those two configurations are not merely stylistic variations. When proxy_pass is specified with a URI, Nginx replaces the portion of the normalized request URI that matched the location with the URI from proxy_pass. Without that URI, the request URI is passed according to a different rule.
This is why the linter reports a proxy URI as an interpretation note instead of “fixing” slashes automatically. The correct form depends on the upstream path contract.
Regex and Named Locations Make proxy_pass URI Rewriting More Restricted
Nginx documents cases where the request-URI portion to replace cannot be determined, including regular-expression locations and named locations. In those cases, proxy_pass should be specified without a URI component.
The static checker can recognize the visible location form and flag this specific combination. It still cannot know what an included rewrite rule or variable will do to the final request.
Includes Turn Local Absence Into Weak Evidence
Suppose a pasted TLS server has listen 443 ssl; but no visible ssl_certificate. If that same server also includes a shared TLS file, the certificate may be configured perfectly outside the pasted text. A static tool should not call that a definite missing-certificate error.
Findings become deliberately more cautious when includes are present. The right debugging step is to inspect the expanded configuration with Nginx itself.
add_header Has Both Status-Code and Inheritance Behavior
Security headers added without the always parameter are not necessarily emitted on every response status. Separately, declaring add_header in a child context can change what is inherited from a parent. Newer Nginx releases also provide add_header_inherit controls.
A header line can therefore look correct in isolation while error pages or nested locations receive a different effective header set. Test representative response paths after configuration validation.
Variables Move Some Configuration Questions From Parse Time to Request Time
A static proxy_pass http://backend; can refer to a named upstream resolved from the configuration. A destination containing variables can require runtime DNS resolution depending on the final value, which introduces resolver behavior and different URI rules.
The linter reports variable-based proxying as something to inspect; it cannot expand Nginx variables in a browser without a request, runtime state, and the complete configuration.
Security Checks Need Context, Not a Collection of “Best Practice” Superstitions
autoindex on deserves attention because it can expose directory contents; it is still correct for a deliberate file browser. Running older TLS protocols deserves attention because compatibility may be trading against transport security; a legacy internal client might still explain the choice.
The page therefore avoids assigning a fake security score. Findings tell you what behavior to verify, not whether an arbitrary checklist has declared the server “secure.”
-t and -T, while module documentation such as proxy_pass remains the authority for directive-specific behavior.