How to Handle Multiple Domains in Nginx Config: Line Continuation and Best Practices


2 views

When configuring nginx for multiple domains in a single server block, we often face readability issues with long server_name declarations. The default approach quickly becomes unwieldy:

server {
    listen *:80;
    server_name example.com example.net example.org example.co example.io example.tech;
    return 301 https://canonical-domain.com$request_uri;
}

While nginx doesn't support traditional line continuation with backslashes like shell scripts, we have several practical alternatives:

# Option 1: Multiple server_name directives
server {
    listen *:80;
    server_name example.com example.net example.org;
    server_name example.co example.io example.tech;
    return 301 https://canonical-domain.com$request_uri;
}

# Option 2: Using include files
server {
    listen *:80;
    include /etc/nginx/conf.d/domains.conf;
    return 301 https://canonical-domain.com$request_uri;
}

For extremely large domain lists (50+), consider using the map directive for better maintainability:

map $host $canonical_host {
    default "canonical-domain.com";
    include /etc/nginx/conf.d/domain-mappings.conf;
}

server {
    listen *:80;
    server_name _;
    if ($canonical_host) {
        return 301 https://$canonical_host$request_uri;
    }
    # Handle non-mapped domains here
}

While all these methods work, be aware that:

  • Multiple server_name directives have minimal performance impact
  • include files are parsed at configuration load time
  • map directives are evaluated per request

For environments with wildcard domains, combine patterns with specific exceptions:

server {
    listen *:80;
    server_name "~^(www\.)?example\.(com|net|org)$";
    server_name sub.example.io special.example.co;
    return 301 https://main-site.com$request_uri;
}

When managing nginx configurations with numerous domains in the server_name directive, you often encounter messy, hard-to-maintain configurations like this:

server {
    listen *:80;
    server_name example.com test.com demo.com staging.com production.com 
                beta.com alpha.com dev.com www.example.com blog.example.com
                shop.example.com api.example.com;
    rewrite ^(.*) http://canonical.com permanent;
}

Unlike some other configuration formats, nginx doesn't support traditional line continuation characters like backslashes. However, you can simply split the domains across multiple lines naturally:

server {
    listen *:80;
    server_name 
        example.com 
        test.com 
        demo.com 
        staging.com 
        production.com
        beta.com 
        alpha.com 
        dev.com 
        www.example.com 
        blog.example.com
        shop.example.com 
        api.example.com;
    rewrite ^(.*) http://canonical.com permanent;
}

For extremely large domain lists, consider these additional methods:

# Method 1: Include external file
server {
    listen *:80;
    include /etc/nginx/domains.conf;
    rewrite ^(.*) http://canonical.com permanent;
}

# domains.conf contents:
server_name
    domain1.com
    domain2.com
    ...;

Or using regex patterns if domains follow consistent naming:

server {
    listen *:80;
    server_name ~^(www\.)?(example|test|demo|staging)\.com$;
    rewrite ^(.*) http://canonical.com permanent;
}

The multi-line approach provides several advantages:

  • Better version control diffs
  • Easier domain management
  • Improved readability
  • Simpler commenting for individual domains

Here's how you might implement it with comments:

server {
    listen *:80;
    server_name 
        # Production domains
        example.com 
        www.example.com
        
        # Development domains
        test.com
        dev.example.com
        
        # Regional domains
        us.example.com
        eu.example.com;
    rewrite ^(.*) http://canonical.com permanent;
}