+44 7575 472931[email protected]
HostAccentKnowledge BaseHosting, websites, SEO, and growth

Port 80 Already in Use? Fix Apache/Nginx Bind Fast

Seeing 'port 80 already in use' when starting Apache or Nginx? Here's how to find the process holding port 80 and get your web server back online quickly.

VPS HostingWeb Hosting
Terminal showing the port 80 already in use error with lsof output identifying the process to stop on a Linux VPS

Port 80 already in use. That's the message stopping your web server cold — usually shown as bind() to 0.0.0.0:80 failed (98: Address already in use) on Nginx, or (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80 on Apache. You run the start command, and instead of a clean launch you get a flat refusal.

Take a breath. This is one of the most common — and fastest to fix — errors in server administration. Something else is already holding the port your web server wants. The whole job comes down to three moves: find what's on the port, stop it, restart. Most people clear it in under a minute once they know exactly where to look, and this guide walks you through every cause and the precise command for each.

Quick Answer: The "port 80 already in use" error means another process has already bound to TCP port 80, so Apache or Nginx can't start. Find it with sudo lsof -i :80 or sudo ss -ltnp | grep ':80', then stop that process — most often a second web server or a leftover instance. Restart your web server and the bind succeeds.

What "Port 80 Already in Use" Actually Means

Every network service listens on a port. Port 80 is the default for HTTP traffic, just as port 443 is the default for HTTPS. The rule that trips people up: only one process can bind to a given TCP port at a time. That's not a bug — it's how the kernel keeps two programs from quietly stealing each other's traffic.

When Nginx or Apache asks the kernel for port 80 and another program is already sitting there, the kernel refuses — error code 98, "Address already in use." Nothing is corrupted. There's a traffic jam, and the queue is one car long.

The reason it feels alarming is timing. You usually meet this error mid-incident: a deploy that won't come up, a server that won't restart after a config change, a fresh install that refuses to launch. The fix is almost always small. The hard part is resisting the urge to start randomly killing things before you know what you're killing.

On a managed host like Hostaccent this rarely surfaces, because the stack is pre-configured so two web servers never fight over the same port. On a self-managed VPS it's an everyday event — and once you've cleared it once, you'll recognise it instantly.

What's Causing the Port 80 Conflict

Almost every case traces back to one of four culprits. Here they are in the order you'll actually hit them in the real world, not in textbook order.

1. Two web servers fighting for the port (most common). Someone installs Nginx on a box that already runs Apache — or the reverse — and both grab port 80 on boot. In the support tickets our team handles at Hostaccent, this is the number-one cause by a wide margin. It's especially common right after someone follows two different tutorials back to back: one installs Apache, the next installs Nginx, and neither mentions the other exists.

2. A leftover instance of the same server. You restarted, systemd reported "stopped," but an old master or worker process never actually died and still holds the port. This happens after a crash, a kill that didn't propagate to child processes, or a hung graceful-reload.

3. Another service grabbed it first. A Docker container started with -p 80:80, a stray python -m http.server 80, a Jenkins or a control-panel web server can all claim port 80 before your main server gets there. Docker is the sneakiest of these because the listener shows up as docker-proxy, not as anything you'd recognise.

4. A duplicate Listen 80 in Apache's config. Two Listen 80 lines — typically one in ports.conf and one in a vhost you added by hand — make Apache try to bind the same port twice in a single start.

Step 1: Find the Process Holding Port 80

Before you kill anything, identify what's on the port. This single step prevents 90% of the damage people do to themselves while panicking. Any one of these commands works:

bash
sudo lsof -i :80
sudo ss -ltnp | grep ':80'
sudo fuser 80/tcp

Each returns the PID (process ID) and the program name — nginx, apache2, docker-proxy, whatever it is. That name is your diagnosis. See apache2 while you're trying to start Nginx? That's cause #1, a second web server. See the exact same server you're launching? That's a leftover, cause #2. See docker-proxy? A container has the port, cause #3.

Write the PID down before you do anything with it. On a busy box the listener can change between commands, and acting on a stale PID is how people end up killing the wrong process.

Pro Tip: ss -ltnp is faster than the older netstat and ships by default on current Ubuntu and Debian releases as of 2026. The -p flag is what reveals the owning process — drop it and you only learn the port is busy, not who's holding it. -l means listening, -t means TCP, -n keeps it numeric so it returns instantly instead of pausing on DNS lookups.

Step 2: Stop the Right Process and Restart

Now act on what you found. Match your fix to the cause — don't apply the same hammer to all four.

If it's a second web server (cause #1): decide which one you actually want, then stop and disable the other so it doesn't return on the next reboot. Stopping alone isn't enough; a stopped-but-enabled service comes straight back at boot.

bash
sudo systemctl stop apache2      ## stop the Apache conflict, keep Nginx
sudo systemctl disable apache2
sudo systemctl start nginx

There's a smarter option than picking a winner, though. You can run both servers together — Nginx on ports 80 and 443 at the edge, forwarding to Apache on an internal port like 8080. Only one process ever touches port 80, so the bind conflict disappears for good. That reverse-proxy layout is exactly how we run things at Hostaccent. The minimal version, dropped into a file such as /etc/nginx/sites-available/your-site, looks like this:

nginx
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Then point Apache at the internal port by changing Listen 80 to Listen 8080 in /etc/apache2/ports.conf. Apache's binding documentation and Nginx's listen directive docs both cover the directives in full.

If it's a leftover instance (cause #2): stop the service the clean way first, confirm the port is clear, and only force-kill if a stray PID genuinely refuses to die.

bash
sudo systemctl stop nginx
sudo lsof -i :80          ## should now be empty
sudo kill PID             ## replace PID; if one stubborn process remains
sudo kill -9 PID          ## last resort only
sudo systemctl start nginx

A word on kill -9: it sends SIGKILL, giving the process no chance to flush buffers or release sockets cleanly. Use plain kill (SIGTERM) first, and reserve -9 for something genuinely wedged.

If it's another service (cause #3): stop that container or remap its port instead of killing your way out. A Docker container can publish to -p 8080:80 rather than -p 80:80, which frees port 80 for your web server while keeping the container running:

bash
docker ps                       ## find the container ID
docker stop CONTAINER_ID        ## or rerun it on a different host port

Pro Tip: If docker-proxy keeps reclaiming port 80 after every reboot, the mapping is baked into a docker-compose.yml or a container set to restart: always. Editing the live container won't stick — fix the compose file or the run command, or the conflict returns the moment Docker starts.

If it's a duplicate Listen (cause #4): open /etc/apache2/ports.conf and your enabled vhost, delete the second Listen 80, then test the config before restarting so a typo doesn't take the server down twice:

bash
sudo apache2ctl configtest
sudo systemctl restart apache2

The Same Error on Port 443 (HTTPS)

Once you've fixed port 80, don't be surprised if 443 throws the identical message. HTTPS uses port 443, and the same one-process-per-port rule applies. The cause is nearly always the same pairing — two servers, or one leftover instance — just on the secure port instead.

The diagnosis is identical; only the number changes:

bash
sudo ss -ltnp | grep ':443'

If you've set up the reverse-proxy layout above, terminate SSL at Nginx on port 443 and forward plain HTTP internally to Apache. That keeps your certificate handling in one place and means Apache never competes for 443 either. For a refresher on how HTTP, HTTPS and ports fit together, MDN's HTTP reference and Cloudflare's learning center are solid, vendor-neutral starting points.

How to Confirm the Fix — and Stop It Coming Back

Restart succeeded? Don't assume — confirm the right server owns the port and nothing else is lurking behind it:

bash
sudo ss -ltnp | grep ':80'   ## one line, your intended server
curl -I http://localhost     ## expect a 200 or a redirect, not "connection refused"
sudo systemctl status nginx  ## or apache2 — active (running)

If curl returns a real HTTP status and ss shows a single owner on the port, you're done. If you still see two listeners, you stopped one service but a second is still bound — go back to Step 1 and read the program name again.

Prevention is mostly about not letting two servers auto-start. Run sudo systemctl disable on whichever web server you're not using, so a reboot never resurrects the conflict. If you rely on Docker, keep a short note of every -p 80:80 and -p 443:443 mapping — an undocumented container is the single most frustrating version of this error, because nothing in your Apache or Nginx config explains where the conflict is coming from.

Insider Insight: When the error appears only after a reboot (never on a manual restart), the cause is almost always a stopped-but-still-enabled service. systemctl is-enabled apache2 tells you in one line whether it's set to launch at boot. Stop is temporary; disable is permanent. This one check resolves the "it keeps coming back" tickets faster than anything else.

Port 80 problems often travel with other server-side errors. If your web server won't bind at all even after clearing the conflict, the Nginx Won't Start guide covers the [emerg] config errors that follow a bad reload. If the port clash left you locked out of the box entirely, SSH Connection Refused? Causes & How to Fix It (2026) walks the console-in route step by step. And if you're also chasing a 403 Forbidden Error: How to Fix It (Step-by-Step 2026) or a 500 Internal Server Error WordPress: Fix It Fast (2026), the same discipline — find the exact cause before changing anything — saves you from turning a five-minute fix into an afternoon.

Skip the Conflict Entirely with a Managed VPS

Here's the bottom line: port 80 already in use is almost always a quick fix once you know the four causes and the three diagnostic commands. But if hunting down port conflicts at 2 a.m. isn't how you want to spend your night, a managed setup hands that work to someone else. Hostaccent Limited has run Linux servers for customers worldwide since 2018 — UK-registered, with a Bangladesh branch — on a Cloudflare → Nginx → Apache stack with NVMe SSD storage, where the reverse-proxy layout above is configured for you out of the box. The Managed Linux VPS starts at $7.99/mo on the Basic plan, with UK-based human support and your pick of location, including Amsterdam and Atlanta. Honest caveat: if you specifically want unrestricted root freedom to install whatever stack you like, a managed plan deliberately limits that — the trade-off for never seeing this error.

Frequently Asked Questions

How do I find what is using port 80 on Linux?

Run sudo lsof -i :80 or sudo ss -ltnp | grep ':80'. Both return the process ID and program name holding the port — usually nginx, apache2, or docker-proxy. Keep the -p flag in ss; it's what reveals the owning process. That name tells you exactly which fix you need.

What does "port 80 already in use" mean exactly?

The "port 80 already in use" message means another process has already bound to TCP port 80, the default HTTP port. Because only one process can hold a port at a time, your web server's bind request is refused with error 98. Identify and stop the other process to clear it.

How do I kill a process running on port 80?

First try a graceful stop: sudo systemctl stop nginx (or apache2). If a stray process lingers, find its PID with sudo lsof -i :80 and run sudo kill PID. Reserve sudo kill -9 PID for a process that genuinely won't terminate, since it skips cleanup and can leave sockets behind.

Can Apache and Nginx both run on the same server?

Yes — but not both directly on port 80. The standard setup puts Nginx on ports 80 and 443 as a reverse proxy, forwarding to Apache on an internal port like 8080. That layout is the default on a managed VPS like Hostaccent's, and it avoids the bind conflict entirely.

Why does the port 80 error come back after every reboot?

If the error only appears after a reboot, a service you stopped is still enabled to launch at boot. Stopping a service is temporary; you also need sudo systemctl disable apache2 (or the relevant service). Check with systemctl is-enabled to see what's set to auto-start, then disable the one you don't want.

Is it safe to use kill -9 to free port 80?

It works, but treat it as a last resort. kill -9 (SIGKILL) forces immediate termination with no cleanup, which can leave sockets or lock files behind. Always try a normal kill or systemctl stop first, and only escalate to -9 if the process ignores those.

How do I check if port 80 is open and listening?

Use sudo ss -ltnp | grep ':80' to see if anything is listening locally, and curl -I http://localhost to confirm the server actually responds. A returned HTTP status means the port is open and serving; "connection refused" means nothing is bound there yet.

Reviewed by

HostAccent Editorial Team · Editorial Team

Last updated

Jun 29, 2026

HostAccent Editorial Team publishes practical hosting guides, operations checklists, and SEO-focused tutorials for businesses building international web presence.

Discussion

Have a question or tip about this topic? Share it below — your comment will appear after review.

Your email stays private and is only used for moderation.

How do I find what is using port 80 on Linux?

Run sudo lsof -i :80 or sudo ss -ltnp | grep ':80'. Both return the process ID and program name holding the port — usually nginx, apache2, or docker-proxy. Keep the -p flag in ss; it's what reveals the owning process. That name tells you exactly which fix you need.

What does "port 80 already in use" mean exactly?

The "port 80 already in use" message means another process has already bound to TCP port 80, the default HTTP port. Because only one process can hold a port at a time, your web server's bind request is refused with error 98. Identify and stop the other process to clear it.

How do I kill a process running on port 80?

First try a graceful stop: sudo systemctl stop nginx (or apache2). If a stray process lingers, find its PID with sudo lsof -i :80 and run sudo kill PID. Reserve sudo kill -9 PID for a process that genuinely won't terminate, since it skips cleanup and can leave sockets behind.

Can Apache and Nginx both run on the same server?

Yes — but not both directly on port 80. The standard setup puts Nginx on ports 80 and 443 as a reverse proxy, forwarding to Apache on an internal port like 8080. That layout is the default on a managed VPS like Hostaccent's, and it avoids the bind conflict entirely.

Why does the port 80 error come back after every reboot?

If the error only appears after a reboot, a service you stopped is still enabled to launch at boot. Stopping a service is temporary; you also need sudo systemctl disable apache2 (or the relevant service). Check with systemctl is-enabled to see what's set to auto-start, then disable the one you don't want.

Is it safe to use kill -9 to free port 80?

It works, but treat it as a last resort. kill -9 (SIGKILL) forces immediate termination with no cleanup, which can leave sockets or lock files behind. Always try a normal kill or systemctl stop first, and only escalate to -9 if the process ignores those.

How do I check if port 80 is open and listening?

Use sudo ss -ltnp | grep ':80' to see if anything is listening locally, and curl -I http://localhost to confirm the server actually responds. A returned HTTP status means the port is open and serving; "connection refused" means nothing is bound there yet.

Write for the Community

Have a tutorial, tip, or insight to share? Get published on the HostAccent Blog with your name, bio, and website link.

Become a Contributor

Need a faster setup for this workflow?