nginx Configuration

Posted on 18 2026

nginx configuration is hierarchical and modular. A single top-level file includes everything else. Global settings apply to all virtual servers. Per-server settings override globals where needed. Individual site configurations are activated and deactivated by creating and removing symlinks.

Understanding this structure before writing any configuration makes every subsequent page in this section easier to follow.

Configuration hierarchy

nginx processes configuration from the top down. The main configuration file nginx.conf sets global parameters and includes everything else. The included files add HTTP-level settings, TLS defaults, security headers, and finally the individual virtual server definitions.

nginx.conf
├── events { }                     # Worker connection settings
└── http { }                       # HTTP-level settings
    ├── include conf.d/*.conf       # Global HTTP includes
    │   ├── ssl.conf                # Shared TLS configuration
    │   ├── security.conf           # Security headers
    │   ├── gzip.conf               # Compression settings
    │   ├── logging.conf            # Log format definitions
    │   └── rate-limiting.conf      # Rate limit zones
    └── include sites-enabled/*.conf # Active virtual servers
        ├── default.conf            # Default catch-all server
        ├── nextcloud.conf          # Nextcloud reverse proxy
        ├── snappymail.conf         # Webmail
        ├── autoconfig.conf         # Mail client autoconfig
        └── ...

Settings defined at a higher level in this hierarchy apply everywhere below them unless overridden. A TLS cipher suite defined in conf.d/ssl.conf applies to every virtual server. A specific header override in nextcloud.conf applies only to the Nextcloud server block.

Directory structure

The packaged nginx on Ubuntu uses this layout under /etc/nginx/:

/etc/nginx/
├── nginx.conf              # Main configuration file
├── conf.d/                 # Global HTTP includes (all active)
│   └── default.conf        # Default virtual server (replaced)
├── sites-available/        # Site configurations (all files, not all active)
│   ├── default             # Ubuntu default site
│   ├── nextcloud
│   ├── snappymail
│   └── autoconfig
└── sites-enabled/          # Symlinks to active sites only
    └── nextcloud -> ../sites-available/nextcloud

This series adds additional global configuration files to conf.d/ rather than modifying the default conf.d/default.conf. The sites-available/sites-enabled pattern is kept as the Ubuntu package sets it up, since it is the standard expectation.

The modular approach

Rather than putting all configuration in nginx.conf or in individual site files, common settings are factored into shared include files. This avoids repetition and ensures consistency.

For example, TLS settings should be identical across every virtual server. Defining them in conf.d/ssl.conf and including them everywhere means a cipher suite change happens in one file and takes effect everywhere. Without this approach, a TLS update requires editing every virtual server file individually and risks inconsistency.

The same principle applies to security headers, logging formats, rate limiting zones, and proxy settings. Define once, include everywhere.

Activating and deactivating sites

Site configurations in sites-available/ are not loaded until they are symlinked into sites-enabled/. This allows configuration files to be prepared and tested without affecting the running server.

Activate a site:

sudo ln -s /etc/nginx/sites-available/nextcloud \
    /etc/nginx/sites-enabled/nextcloud
sudo nginx -t && sudo systemctl reload nginx

Deactivate a site:

sudo rm /etc/nginx/sites-enabled/nextcloud
sudo nginx -t && sudo systemctl reload nginx

The nginx -t step validates the configuration before reloading. Never reload without validating first.

Testing and reloading

The source material uses sudo service nginx configtest which is the SysV init syntax. On Ubuntu 24.04 with systemd:

# Test configuration syntax
sudo nginx -t

# Reload configuration without dropping connections
sudo systemctl reload nginx

# Full restart (drops all connections)
sudo systemctl restart nginx

# Check current status
sudo systemctl status nginx

Use reload rather than restart for configuration changes. A reload applies the new configuration to new connections while existing connections continue with the old configuration until they close naturally. A restart drops all active connections.

Useful nginx commands

# Show nginx version and compile options
nginx -V

# Test configuration
nginx -t

# Test and show the full configuration (including all includes)
nginx -T

# List all includes and their paths
nginx -T 2>/dev/null | grep "# configuration file"

# Show current number of worker processes and connections
ps aux | grep nginx
cat /var/run/nginx.pid

What the sub-pages cover

Main Configuration File: the top-level nginx.conf with worker process settings, error logging, and the include directives that pull in everything else.

Global HTTP Settings: the conf.d/ files covering TLS defaults, compression, logging format, rate limiting zones, and the HTTP-level settings that apply to every virtual server.

Security Headers: the headers added to every response: HSTS, Content Security Policy, X-Frame-Options, Referrer-Policy, and Permissions-Policy. These are complex enough to warrant their own page.

Virtual Servers: the structure of an individual site configuration. Covers the HTTP-to-HTTPS redirect, the main HTTPS server block, proxy settings for backend services, and the locations that serve static content.

TLS configuration: the cipher suite selection, certificate configuration, OCSP stapling, and session caching that make up a robust TLS implementation.

A note on CSP

The source material covers Content Security Policy (CSP) in its own page. CSP is the most complex of the security headers: a fine-grained policy that specifies which origins are permitted to load resources (scripts, styles, images, fonts, frames) for a given page. Getting it wrong breaks sites. Getting it right is meaningfully more secure.

Each virtual server in this series has its own CSP tailored to its backend. The Nextcloud CSP is different from the SnappyMail CSP, which is different from a simple static site CSP. The global security headers page sets permissive defaults; individual sites tighten them.

nginx configuration errors prevent the server from starting or reloading. Always run nginx -t after any change and before any reload. The error messages are specific about which file and which line the problem is on, making debugging straightforward.