Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for NGINX By James Joyner IV · · 8 min read Last reviewed Jul 2026

NGINX Warning Guide: 'conflicting server name ignored' — Fix Duplicate Vhosts

Quick answer

Fix NGINX 'conflicting server name ignored': find duplicate server_name entries across vhosts and includes, and stop requests hitting the wrong site.

  • #nginx
  • #web-server
  • #troubleshooting
  • #errors
Free toolkit

Stuck on this NGINX error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

NGINX emits this warning during nginx -t or startup when two server blocks listening on the same address:port declare the same server_name. NGINX keeps the first and discards the duplicate:

nginx: [warn] conflicting server name "app.example.com" on 0.0.0.0:443, ignored

It is a warning, not an [emerg], so NGINX still starts — which is exactly why it’s dangerous. Configuration loads “successfully,” but one of your two vhosts for that hostname is silently dropped. Whichever server block NGINX parsed first wins, and that ordering depends on filename sort order across conf.d/sites-enabled, so the “winner” can change unexpectedly.

Symptoms

  • nginx -t reports [warn] conflicting server name "..." ... ignored but still says the test is successful.
  • Requests to a hostname hit the wrong site — old content, wrong TLS certificate, or a 404 for routes that exist in the ignored block.
  • After adding a new vhost file, an existing site’s behavior changes even though its own config wasn’t edited.
  • The wrong server block “wins” and flips after a file is renamed or a new conf.d entry sorts ahead of the old one.

Common Root Causes

  • The same server_name in two files — often a leftover default or example vhost in conf.d colliding with the real one.
  • A copy-pasted vhost — a template duplicated for a new site but the server_name never changed.
  • Overlapping wildcard and exact names on the same listen — e.g. *.example.com in one block and app.example.com in another handled inconsistently.
  • HTTP and HTTPS mixed up — two blocks both on :443 for the same name because a redirect block was miswritten.
  • included snippets that each define a server for the same host.

Diagnostic Workflow

List every server_name across all config and find the duplicates:

grep -rhoE 'server_name\s+[^;]+;' /etc/nginx/ | \
  sed 's/;//' | awk '{$1=""; print}' | tr ' ' '\n' | \
  grep -v '^$' | sort | uniq -d

Then locate which files declare the conflicting name so you can decide which block should win:

grep -rn 'server_name .*app.example.com' /etc/nginx/
nginx -t   # re-read the exact warning, noting the address:port it conflicts on

Use nginx -T to see the assembled config and confirm which server block for that name/port appears first (that’s the one NGINX keeps):

nginx -T | grep -n -A3 'server_name .*app.example.com'

Resolve it by consolidating into a single authoritative server block per name+listen, and giving any intentional catch-all the default_server flag instead of a real hostname:

# The one real vhost for this name on :443
server {
    listen 443 ssl;
    server_name app.example.com;
    # ... TLS + locations ...
}

# A catch-all for unmatched hosts — NOT a duplicate name
server {
    listen 443 ssl default_server;
    server_name _;
    return 444;   # close connection on unknown hosts
}

Validate and reload:

nginx -t && nginx -s reload

Example Root Cause Analysis

After deploying a new marketing site, the team noticed app.example.com was suddenly serving a stale page with the wrong TLS certificate. nginx -t “passed” but printed conflicting server name "app.example.com" on 0.0.0.0:443, ignored. The grep sweep found the name in two files: the real sites-enabled/app.conf and a forgotten conf.d/00-legacy.conf created months earlier from a template whose server_name had never been updated.

Because conf.d files are included before sites-enabled in this setup and 00-legacy.conf sorted first, NGINX kept the legacy block and ignored the real one — hence the stale content and old certificate. Deleting the legacy block (its purpose had long since moved) left a single authoritative vhost for the name, and the warning disappeared. The lasting fix was replacing the leftover catch-all logic with a proper default_server block using server_name _;, so an unmatched host never collides with a real one again.

Prevention Best Practices

  • Treat this warning as an error in review — it means a vhost is being silently dropped, even though NGINX starts.
  • Keep exactly one server block per server_name + listen combination; if you need a default, use default_server with server_name _;, never a real hostname twice.
  • Periodically run the duplicate-name grep in CI so a copy-pasted server_name is caught before deploy.
  • Remove template and example vhosts (conf.d/default.conf) rather than leaving them to collide with real sites.
  • Be deliberate about file ordering: don’t rely on sort order to pick a winner — eliminate the duplicate instead.
  • Use nginx -T in code review to see the assembled config and confirm each hostname resolves to the intended block.

Quick Command Reference

# List duplicate server_name values across all configs
grep -rhoE 'server_name\s+[^;]+;' /etc/nginx/ | sed 's/;//' | \
  awk '{$1=""; print}' | tr ' ' '\n' | grep -v '^$' | sort | uniq -d

# Find which files declare a given name
grep -rn 'server_name .*HOSTNAME' /etc/nginx/

# See which block wins in the assembled config
nginx -T | grep -n -A3 'server_name .*HOSTNAME'

# Validate and reload after consolidating
nginx -t && nginx -s reload

Conclusion

conflicting server name ... ignored is a warning with real consequences: two server blocks claim the same hostname on the same listen, and NGINX silently keeps only the first. Because the winner depends on file sort order, behavior can flip unexpectedly. Find every duplicate server_name, consolidate to one authoritative block per name+listen, and use default_server with server_name _; for catch-alls. Then a passing nginx -t actually means every hostname routes where you intend.

Free download · 368-page PDF

Fixed it? Get 500 NGINX & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.