Nginx Error: 'a duplicate default server for 0.0.0.0:80' — Cause, Fix, and Troubleshooting Guide
Fix nginx [emerg] a duplicate default server for 0.0.0.0:80: only one default_server is allowed per listen socket. Diagnose the clash and resolve it.
- #nginx
- #web-server
- #troubleshooting
- #config
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.
What this error means
a duplicate default server is a configuration-parse error NGINX raises at load time. Every listen socket (an ip:port pair such as 0.0.0.0:80) can have exactly one server block marked as the default for unmatched requests. When two or more server {} blocks each declare listen 80 default_server; — or two blocks implicitly claim the default because the first block to bind a socket becomes its default — NGINX cannot decide which one wins and refuses to start.
nginx: [emerg] a duplicate default server for 0.0.0.0:80 in /etc/nginx/conf.d/site-b.conf:2
nginx: configuration file /etc/nginx/nginx.conf test failed
The message cites the exact file and line of the second (conflicting) listen directive. A reload keeps the previous config running; a cold systemctl start nginx fails outright and the service stays dead, so no vhost on that socket serves traffic.
How the server responds
nginx -tfails with[emerg] a duplicate default server for 0.0.0.0:80.systemctl reload nginxreports failure and the running config is unchanged.- A cold
systemctl start nginxexits1/FAILUREand the service does not come up. - The error points at a
listenline in one included vhost file, not the whole config. - Appears right after adding or copying a new site into
conf.d/orsites-enabled/. - Can also fire for other sockets, e.g.
a duplicate default server for [::]:443.
Testing the server configuration
Start with the validator; it names the file and line of the conflict.
sudo nginx -t
Find every default_server flag across the whole config tree:
grep -RnE 'listen[^;]*default_server' /etc/nginx/
Two or more hits for the same ip:port is your conflict. Because include order matters, dump the fully-assembled config and see which server blocks target the socket:
sudo nginx -T | grep -nE 'server_name|listen'
Inspect the specific file the error cited to confirm the flag:
sed -n '1,10p' /etc/nginx/conf.d/site-b.conf | cat -n
On Debian/Ubuntu, check whether the packaged default site is still linked:
ls -l /etc/nginx/sites-enabled/
grep -n default_server /etc/nginx/sites-enabled/default
Server configuration causes
- Two
default_serverflags on the same socket — the most direct cause:listen 80 default_server;appears in two differentserver {}blocks, often across two files inconf.d/. - Copy-pasted vhost templates — a starter config carries
default_serverand gets duplicated for each new site, so every site claims the default. - Implicit default collision — before
default_serverexisted, the first server on a socket was the implicit default. Mixing one explicitdefault_serverwith the historical implicit rule on the same socket can still collide across NGINX versions if two are flagged. - IPv4 and IPv6 treated as one socket —
listen 80 default_server;andlisten [::]:80 default_server;are separate sockets and are fine, butlisten 80 default_server;plus a barelisten 0.0.0.0:80 default_server;are the same socket and clash. - The distro default site still enabled — Debian/Ubuntu ship
/etc/nginx/sites-enabled/defaultwithlisten 80 default_server;; adding your own default_server site collides with it. - Included twice — the same vhost file symlinked or
included from two paths, so itsdefault_serveris parsed twice.
The fix
Keep default_server on exactly one server block per socket and remove it from the rest. Suppose site-a.conf should be the default:
# /etc/nginx/conf.d/site-a.conf — the ONE default for 0.0.0.0:80
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444; # or your real catch-all site
}
# /etc/nginx/conf.d/site-b.conf — drop default_server here
server {
listen 80; # no default_server flag
server_name site-b.example.com;
root /var/www/site-b;
}
If the shipped default site is the unwanted one, disable it rather than editing packaged files:
sudo rm /etc/nginx/sites-enabled/default # symlink only; the file stays in sites-available
If you want an explicit catch-all that returns a clean status for unknown hosts, make that single block the default and let every named vhost listen without the flag. Only one block per ip:port (and separately per IPv6 socket) may carry default_server.
Because default_server selection is bound to how the listen socket is set up, apply the change and revalidate:
sudo nginx -t && sudo systemctl reload nginx
A reload is sufficient for removing a duplicate flag. If NGINX was down because a cold start failed, use sudo systemctl start nginx (or restart) once nginx -t passes.
Safe configuration practice
default_serveris per listen socket, not per server: IPv40.0.0.0:80and IPv6[::]:80are different sockets and each may have its own default.- The default server also decides which cert/vhost serves requests whose
Hostheader matches nothing — pick it deliberately, don’t let it fall to whichever file loads first. - Debian/Ubuntu’s
sites-enabled/defaultis a frequent silent culprit; audit it before adding your own default site. - Grep the entire tree (
grep -RnE 'default_server' /etc/nginx/) after any bulk vhost change; a single stray flag breaks the whole socket. - Avoid symlinking or
includeing the same vhost from two places — the second parse re-declares the default. - Wire
nginx -tinto your deploy pipeline and alert on failed reloads; surface the failure on your monitoring dashboard so a bad vhost never reaches a cold restart.
Related server errors
- Nginx Error Conflicting Server Name — the sibling warning when two server blocks claim the same
server_nameon a socket. - Nginx Error Bind Address Already In Use — a related
listen-socket failure, but at bind time rather than default selection. - Nginx Error Could Not Build Server Names Hash — another server-block parse error tied to how vhosts are declared.
See the NGINX category for more guides.
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?
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.