Nginx include directive file loading order: Behavior analysis and workaround for shared configurations


3 views

During configuration management in Nginx deployments, many engineers report inconsistent behavior when including multiple configuration files. Unlike Apache's documented alphabetical order (see Apache include directive), Nginx's include processing appears non-deterministic.

The core issue manifests when trying to establish dependency chains between configuration files. For example:

# Problem scenario:
include /etc/nginx/conf.d/*.conf;
# Where:
# - 00_default.conf defines shared log formats
# - 20_example.com depends on those formats

Engineers expect lexicographical ordering (00_default loading first), but Nginx's filesystem read implementation may vary across:

  • Different OS filesystems (ext4 vs NTFS)
  • Kernel versions
  • Containerized environments

Option 1: Explicit Includes

# Replace wildcard includes with ordered explicit includes
include /etc/nginx/conf.d/00_default.conf;
include /etc/nginx/conf.d/20_example.com.conf;

Option 2: Single-file Inheritance

# master.conf
include base_configs/*.conf;  # Contains shared directives
include sites/*.conf;         # Site-specific configs

Option 3: Runtime Validation

# In 20_example.com.conf
if ($log_format = '') {
    return 500 "Missing base configuration";
}

For complex environments, consider:

  1. Using configuration management tools (Ansible/Puppet) to generate ordered includes
  2. Implementing pre-start validation scripts
  3. Adopting Nginx Plus with its configuration API

To inspect load order:

# Add to main nginx.conf
env NGINX_DEBUG_LOAD_ORDER;

Then check error logs with debug level enabled.


Unlike Apache which explicitly documents alphabetical ordering for wildcard includes, Nginx's include directive doesn't guarantee any specific file loading sequence. This becomes crucial when you need certain configurations to load before others.

Consider this common scenario:


# In /etc/nginx/conf.d/
00_default.conf   # Contains shared directives
20_example.com.conf # Depends on 00_default

You might expect 00_default.conf to load first due to its naming, but Nginx may process them in arbitrary order, potentially breaking your configuration.

Option 1: Explicit Includes


http {
    include /etc/nginx/conf.d/00_default.conf;
    include /etc/nginx/conf.d/20_example.com.conf;
}

Option 2: Single File with Proper Ordering


# main.conf
include shared/*.conf;
include sites/*.conf;
include locations/*.conf;

Option 3: Using Nginx's Stages

Leverage Nginx's configuration phases:


# In nginx.conf
events {}
http {
    # Early phase includes
    include conf.d/early/*.conf;
    
    # Main configuration
    # ...
    
    # Late phase includes
    include conf.d/late/*.conf;
}
  • Document your include hierarchy
  • Use clear naming conventions (e.g., 01_, 02_ prefixes)
  • Test configuration with nginx -T
  • Consider using a configuration management tool

To see actual include order:


grep -r "include" /etc/nginx/ | awk -F: '{print $1}' | sort | uniq

Or check the compiled configuration:


nginx -T