Fix Nginx "conflicting server name" Warnings

Fix the Nginx warning conflicting server name example.com on 0.0.0.0:80, ignored: find duplicate server blocks in sites-enabled and conf.d, remove leftover Certbot or default configs, and make the right Django site answer.

Problem statement

nginx -t or a reload prints:

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

The test still says the syntax is ok, so it is easy to ignore. But "ignored" matters: two server blocks claim the same name on the same address and port, and Nginx uses only the first one it loaded. Your carefully edited Django config may be the one being ignored, which explains changes that "do nothing", an old site still answering, or HTTPS settings that never take effect.

How Nginx picks between duplicatesTwo server blockssame name and portLoad orderalphabetical includesFirst one winsfor that nameSecond ignoredyour edits unusedNginx keeps the first server block it loads for a name and port, and warns about the rest.
  1. List every server block for the name: sudo nginx -T 2>/dev/null | grep -n "server_name".
  2. Find the files they come from: grep -R "example.com" /etc/nginx/.
  3. Remove duplicates: an old copy in sites-enabled, a backup like django.bak, or a file in both conf.d and sites-enabled.
  4. Keep exactly one block per name per port (one for 80, one for 443).
  5. Run sudo nginx -t until the warning is gone, then sudo systemctl reload nginx.

Step-by-step solution

1. Dump the effective configuration

sudo nginx -T 2>/dev/null | grep -nE "^# configuration file|server_name|listen"

nginx -T prints every included file with a # configuration file header, so you can see which file each server_name line comes from and in what order they load.

2. Look for the usual duplicates

Most conflicts come from one of these:

  • A backup file in an include directory. sites-enabled/* includes django, django.bak, and django.save (nano's emergency save) alike.
  • Both include styles. Debian-family servers include /etc/nginx/conf.d/*.conf and /etc/nginx/sites-enabled/*; the same site placed in both loads twice.
  • A copy instead of a symlink. sites-enabled/example should be a symlink to sites-available/example; an old copy stays behind when you edit the original.
  • Certbot. The Nginx plugin adds listen 443 ssl and a redirect block to the file it chose. Running it against a second file, or copying the result, leaves two 443 blocks.
ls -la /etc/nginx/sites-enabled/ /etc/nginx/conf.d/
where the second server block usually comes fromWhat you findFixdjango.bak or .save in sites-enabledmove backups out ofinclude directoriessame site in conf.d and sites-enabledkeep one include style for all sitesregular file instead of a symlinkdelete the copy, symlinkfrom sites-availabletwo 443 blocks after Certbotmerge into one blockwith the ssl directivesEvery file in an include directory is loaded, whatever its extensiondjango-deployment.com
Clean the include directories first; most conflicts disappear with the stray file.

3. Remove the stray block

Move backups out of the include path rather than deleting them blindly:

sudo mkdir -p /etc/nginx/backup
sudo mv /etc/nginx/sites-enabled/django.bak /etc/nginx/backup/

If a file is a copy rather than a symlink, replace it:

sudo rm /etc/nginx/sites-enabled/example
sudo ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example

4. Structure the site as one block per port

For a Django site with HTTPS, the clean layout is one redirect block on port 80 and one application block on port 443:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com www.example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://unix:/run/gunicorn.sock;
        include proxy_params;
    }
}

A name may appear in several blocks only if they listen on different ports, as here.

5. Test and reload

sudo nginx -t && sudo systemctl reload nginx
curl -sI https://example.com | head -3
a conflict-free layoutsites-available/examplethe only real filesites-enabled/examplesymlink to itserver :80redirect to https onlyserver :443TLS and proxy_pass to GunicornSame names on different ports are fine; same name and port is a conflictdjango-deployment.com
Keep one source file per site so there is only ever one place to edit.

Verification check: sudo nginx -t prints no [warn] lines, and a change you make to the remaining block (for example a test header add_header X-Config-Check 1;) shows up in curl -I after reload.

Explanation

Nginx selects a server block in two steps: first by the listen address and port the connection arrived on, then by matching the Host header against server_name within that group. If two blocks in the same group declare the same name, Nginx cannot use both, so it keeps the first one parsed and warns about the rest. Because includes are expanded alphabetically, which block wins depends on file names, which is why the problem can appear or vanish after an unrelated rename.

Edge cases / notes

  • Default server. If no server_name matches, Nginx uses the default_server for that port, or the first block. That produces the Nginx welcome page instead of Django; see Fix the Nginx Default Page Showing Instead of Django.
  • IPv6 listeners. listen [::]:80 is a separate address; a conflict can appear only on IPv6 if one block lacks the IPv6 listen.
  • Control panels and images such as some cloud marketplace images ship their own server blocks for the hostname. Check /etc/nginx/nginx.conf itself as well as include directories.
  • Wildcards. *.example.com and example.com do not conflict; exact names take precedence over wildcards.

Next steps

FAQ

Is the conflicting server name warning harmful?

It means one of your server blocks is ignored. If that is the block you are editing, your changes do nothing.

Which block does Nginx use?

The first one loaded for that name and port, which depends on include order.

Can I use the same server_name on ports 80 and 443?

Yes. The conflict only occurs for the same name on the same address and port.

Does nginx -t fail on this?

No. It is a warning, so the test passes, which is why it often goes unnoticed.

Keep going