About nginx configuration files
Nginx is configured with plain-text files made of two things: simple directives that end in a semicolon (listen 443 ssl;) and block directives whose body sits in braces (server { … }, location /api/ { … }, upstream, map, if). The main file is usually /etc/nginx/nginx.conf, with virtual hosts under sites-available or conf.d pulled in by include. The same syntax is used by OpenResty, by the configuration snippets of the Kubernetes ingress-nginx controller, and by the default.conf baked into countless Docker images. Configs collected from Stack Overflow answers, generated by Certbot or squeezed into a Helm value often arrive on one line or with indentation that no longer matches the nesting.
Formatting a config
Paste the config or drop the file; server, http or location blocks combined with semicolon-terminated lines are recognised as nginx. Output appears as soon as the input parses, Ctrl/Cmd+Enter formats again on demand, and Ctrl/Cmd+Shift+C copies it, ready to paste into your editor or a ConfigMap.
The Indent setting in the toolbar is the only layout choice: 2 spaces, 4 spaces or tabs per level. Everything else follows one fixed style, close to what the popular nginxbeautifier produces.
The printer is built into PasteKit and its tokenizer follows the same rules as nginx’s own config reader, so quoting and escaping are understood the way the server understands them. Upstream addresses, internal hostnames and certificate paths stay in your browser.
The output style
- One directive per line, each ending with its
;. - An opening
{goes on the same line as its directive and the closing}on its own line, indented to match the directive that opened it. - Directive arguments are separated by single spaces. Quoted strings, regular expressions in
location ~*andrewriterules, and$variablesare copied exactly, including a semicolon inside quotes such asset $x "a;b";. - A directive you deliberately split over several lines, typical for
log_format, keeps its line breaks; the continuation lines are indented one level deeper. - Comments stay where they were. A comment after a directive or after a closing brace stays on that line.
- Blank lines you used to separate groups are kept, but several in a row become one and none appear right after an opening brace.
- Bodies of OpenResty
*_by_lua_blockdirectives are re-indented as a whole without being parsed as nginx syntax, so Lua code is not broken up at its semicolons or braces.
Errors it catches, and what it does not
Formatting requires a structurally valid file, so the parser reports the problems that make nginx -t fail early: a missing semicolon (with the line where it belongs), an opening brace without a partner, an extra closing brace and an unterminated quoted string. It does not know nginx’s directive list, so a misspelt directive name, a directive used in the wrong context or a duplicate listen will format without complaint. Always run nginx -t before reloading. For a validation-focused view of the same checks, see the nginx validator.
Examples
Reverse proxy squeezed onto a few lines
The upstream, the HTTP redirect server and the HTTPS server each get their own indented block with one directive per line.
upstream api_backend{least_conn;server 10.0.0.11:8080 max_fails=3;server 10.0.0.12:8080 backup;}
server{listen 80;server_name shop.example.com;return 301 https://$host$request_uri;}
server{listen 443 ssl http2;server_name shop.example.com;
location /api/{proxy_pass http://api_backend;proxy_set_header X-Real-IP $remote_addr;proxy_read_timeout 60s;}
location /static/{alias /srv/shop/static/;expires 7d;}}upstream api_backend {
least_conn;
server 10.0.0.11:8080 max_fails=3;
server 10.0.0.12:8080 backup;
}
server {
listen 80;
server_name shop.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name shop.example.com;
location /api/ {
proxy_pass http://api_backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 60s;
}
location /static/ {
alias /srv/shop/static/;
expires 7d;
}
}
Multi-line log_format and a map block
The log_format keeps its two-line layout, the map is expanded, and the two gzip directives sharing a line are split.
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer"';
map $http_upgrade $connection_upgrade { default upgrade; '' close; }
gzip on; gzip_types text/css application/javascript;
}http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer"';
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
gzip on;
gzip_types text/css application/javascript;
}
OpenResty Lua block with tab indentation
The Lua body is shifted to the right depth as a unit rather than being split at its parentheses and quotes.
location /hello {
default_type text/plain;
content_by_lua_block {
local name = ngx.var.arg_name or "world"
ngx.say("hello, ", name)
}
}location /hello {
default_type text/plain;
content_by_lua_block {
local name = ngx.var.arg_name or "world"
ngx.say("hello, ", name)
}
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Missing ';' after directive 'listen' on line 1Explained | A simple directive is not terminated, so nginx would read the next word as one of its arguments. | Add ‘;’ at the end of the reported directive. |
Unclosed '{' opened by 'server' on line 1 | A block is opened but the file ends before its closing brace, common when copying only the top of a config. | Add the missing ‘}’ after the last directive that belongs to the block. |
Unexpected '}' with no matching '{' | There is one closing brace too many, usually left over after deleting a location block. | Remove the extra brace, or restore the block opening it was meant to close. |
Unterminated double-quoted string starting on line 1 | A quoted argument such as an add_header value or a return body has no closing quote, so the rest of the file is read as part of the string. | Close the quote, or escape any quote character that is part of the value with a backslash. |
Unexpected ';' with no directive before it | A semicolon stands on its own, typically a doubled ;; or one left after a closing brace. | Delete the stray semicolon. |
Frequently asked questions
Is the formatted config guaranteed to pass nginx -t?
No. The formatter checks structure (braces, semicolons, quotes) but not whether directives exist or are allowed in that block. Run nginx -t on the server before reloading.
Will it change my regular expressions or rewrite rules?
No. Arguments are copied exactly as written, including regex characters, captures like $1 and named groups such as (?<ver>…).
Can I format a single location or server block?
Yes. Any fragment with balanced braces works, so you can paste one block out of a larger file.
Does it expand include files?
No. include lines are kept as directives; the files they reference are not loaded.
Does it work for ingress-nginx snippets and OpenResty configs?
Yes. Snippets are ordinary nginx syntax, and *_by_lua_block bodies are recognised so Lua code is indented without being parsed as nginx.