nginx Configuration File Structure & Contexts Explained
This article explains the structure of the nginx configuration file and the contexts that define where directives are valid. You will learn how the main, events, http, server, and location blocks work together, how inheritance affects settings, and how to avoid common configuration mistakes.
Background: Why nginx Uses a Hierarchical Config
nginx is a high-performance web server and reverse proxy first released in 2004. Its configuration system is deliberately different from Apache’s .htaccess approach. Instead of allowing per-directory configuration files, nginx uses a single central file (usually /etc/nginx/nginx.conf) with a hierarchical block structure. This design improves performance because the server reads and parses the entire configuration once at startup, then keeps it in memory. It also makes the configuration more predictable: you always know exactly which directives apply to a request, without having to scan multiple directories for override files.
How the Configuration File Is Organized
The main configuration file is a plain text file containing directives and blocks. Directives are simple key-value pairs ending with a semicolon, such as worker_processes 4;. Blocks group related directives inside curly braces. The top-level block is the main context, which contains global settings. Inside it, you typically find the events block and one or more http blocks. The http block contains server blocks, and each server block can contain location blocks. This nesting is what gives nginx its flexibility.
Here is a minimal example showing the hierarchy:
# main context
events { ... }
http {
server {
location / { ... }
}
}
The events block sets connection-processing directives (like worker_connections). The http block holds directives that apply to all HTTP traffic, such as sendfile, keepalive_timeout, and gzip. server blocks define virtual hosts (similar to Apache’s VirtualHost), and location blocks match specific URI patterns to apply different rules.
Contexts and Directive Inheritance
Each directive has a defined set of contexts where it is valid. For example, worker_processes is only valid in the main context, while index is valid in http, server, and location. If you place a directive in the wrong context, nginx will fail to start and print an error like "worker_processes" directive is not allowed here.
nginx uses a simple inheritance model: a directive in an outer block applies to all inner blocks unless the inner block overrides it. For instance, if you set gzip on; in the http block, it applies to all servers and locations. If you set gzip off; in a specific location, that location overrides the inherited value. This is similar to CSS cascade but with fewer rules – there is no specificity or !important; the innermost block wins.
However, not all directives are inherited. Some are only meaningful in a single context. For example, listen is only valid in a server block, and alias is only valid in a location. Always check the official documentation for the directive’s context before using it.
Common Directives and Their Contexts
Here is a list of frequently used directives and where they are allowed:
worker_processes– main context only. Sets the number of worker processes.worker_connections– events context. Sets the maximum number of simultaneous connections per worker.include– any context. Includes another file, often used to split config into manageable parts.server_name– server context. Defines the domain name(s) for a virtual host.root– http, server, location. Sets the document root for requests.proxy_pass– location, if in location. Forwards requests to a proxied server.return– server, location. Sends an HTTP status code or redirect.
Remember that if is a directive that creates a new context, but it is often discouraged for rewriting rules due to its unpredictable behavior. Use try_files or dedicated modules instead.
How to Choose the Right Context for Your Settings
When adding a directive, ask yourself: “Should this apply to every request, to a specific domain, or only to a certain path?�
- Global settings (like
user,pid,worker_processes) go in the main context. - Connection tuning (like
worker_connections,multi_accept) goes in the events block. - HTTP-wide defaults (like
gzip,keepalive_timeout,sendfile) go in the http block. - Per-domain settings (like
server_name,listen, SSL certificates) go in the server block. - Per-URI settings (like
proxy_pass,alias,try_files) go in the location block.
If you are unsure, start with the broadest context and test. You can always narrow it down later. But remember that putting a directive in a broader context than necessary can cause unintended side effects. For example, setting root in http will apply to all servers that don’t override it, which might not be what you want.
Common Problems and How to Avoid Them
One of the most frequent mistakes is placing a directive in the wrong context. The error message usually tells you exactly which directive and which context is invalid, so read it carefully. Another common issue is forgetting the semicolon at the end of a directive – nginx will parse the next line as part of the same directive and fail.
A classic example of context confusion is trying to use server_name inside a location block. That is not allowed; server_name is only valid in server. Similarly, listen cannot be inside a location. If you need to handle different domains with different document roots, you need separate server blocks, not locations.
Another frequent problem is misunderstanding inheritance. For example, setting client_max_body_size in http will apply to all servers, but if you set it in a server block, it only applies to that server. If you have a location that needs a larger upload size, you must set it inside that location, otherwise the server-level value will be used.
Finally, always test your configuration before reloading nginx. Use nginx -t to check for syntax errors. This command will tell you if a directive is misplaced or if a file is missing. It is a good habit to run it after every change.
Frequently Asked Questions
What is the difference between server and location contexts?
A server block defines a virtual host – it listens on a specific IP/port and matches a server name. A location block is nested inside a server and matches a URI path. For example, you might have a server for example.com and a location /api that proxies to a backend, while other paths serve static files.
Can I use multiple http blocks?
Yes, technically you can have more than one http block, but they are merged into a single configuration. It is more common to use include to split files, but you can also have multiple http blocks. However, it’s cleaner to keep all http-level settings in one block.
Why does my if directive not work as expected?
The if directive in nginx is known to have pitfalls, especially when used with rewrite or proxy_pass. It is not a general-purpose conditional; it only works reliably for certain checks like if ($request_method = POST). For most routing logic, prefer try_files, map, or separate server blocks.
How do I include a file in nginx configuration?
Use the include directive with a path or a glob pattern. For example, include /etc/nginx/sites-enabled/*; is common on Debian/Ubuntu. The included file must contain valid nginx syntax and can have any extension, but .conf is conventional.
What does nginx -t do?
It tests the configuration file for syntax errors and validity. It will output syntax is ok and test is successful if everything is fine, or show the exact error line if not. It does not reload the server; you still need to run nginx -s reload to apply changes.
Can I set environment variables in nginx config?
nginx does not natively support environment variables in its configuration. You can use a template tool like envsubst or a configuration management system to substitute values at deploy time. Some third-party modules allow it, but they are not part of the standard distribution.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.