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.
- List every server block for the name:
sudo nginx -T 2>/dev/null | grep -n "server_name". - Find the files they come from:
grep -R "example.com" /etc/nginx/. - Remove duplicates: an old copy in
sites-enabled, a backup likedjango.bak, or a file in bothconf.dandsites-enabled. - Keep exactly one block per name per port (one for 80, one for 443).
- Run
sudo nginx -tuntil the warning is gone, thensudo 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/*includesdjango,django.bak, anddjango.save(nano's emergency save) alike. - Both include styles. Debian-family servers include
/etc/nginx/conf.d/*.confand/etc/nginx/sites-enabled/*; the same site placed in both loads twice. - A copy instead of a symlink.
sites-enabled/exampleshould be a symlink tosites-available/example; an old copy stays behind when you edit the original. - Certbot. The Nginx plugin adds
listen 443 ssland 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/
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
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_namematches, Nginx uses thedefault_serverfor 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 [::]:80is 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.confitself as well as include directories. - Wildcards.
*.example.comandexample.comdo not conflict; exact names take precedence over wildcards.
Next steps
- Review a full production config in Configure Nginx for Django in Production.
- Running several sites? See Host Multiple Django Sites on One Server.
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.