Fix "bind: Address already in use" on Linux
Find what is listening on the port, then stop that service or move one of them to another port.
sudo ss -ltnp 'sport = :8080'
# stop it properly if it is a service:
sudo systemctl stop apache2.service
# or kill whatever holds the port:
sudo fuser -k 8080/tcp
Each language and server phrases it differently:
bind: Address already in use
OSError: [Errno 98] Address already in use
Error: listen EADDRINUSE: address already in use :::3000
listen tcp :8080: bind: address already in use
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
What the error means
A program asked the kernel to listen on an address and port (for example 0.0.0.0:80), and the kernel refused with EADDRINUSE because another socket already holds that combination. Only one listener can own a TCP port on a given address unless both explicitly opt into sharing. The fix is always to find the other socket. When this happens as a service starts, systemd reports it as Job for X.service failed.
Find who holds the port
sudo ss -ltnp 'sport = :80' # TCP listeners
sudo ss -lunp 'sport = :53' # UDP
Example output:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("apache2",pid=1043,fd=4),("apache2",pid=1041,fd=4))
LISTEN 0 511 [::]:80 [::]:* users:(("apache2",pid=1043,fd=6))
Run it with sudo, otherwise the Process column is empty for other users' processes. Alternatives: sudo lsof -iTCP:80 -sTCP:LISTEN or sudo fuser -v 80/tcp. Then map the PID to a systemd unit:
ps -o unit=,cmd= -p 1043
The Linux networking guide explains ss output in more detail.
Cause 1: another service already uses the port
The classic case: Apache and nginx both want port 80, a distro package started a default web server, a second database instance wants 5432, or systemd-resolved holds 53 when you try to run your own DNS server. Decide which one should own the port, then stop and disable the other so it does not come back at boot:
sudo systemctl disable --now apache2.service # httpd on Fedora/Arch
Or move one of them to another port in its config. For port 53, set DNSStubListener=no in /etc/systemd/resolved.conf and restart systemd-resolved before starting dnsmasq, Pi-hole or BIND. The systemctl cheat sheet covers enable/disable/mask.
Cause 2: an old copy of your own program is still running
A development server left running in another terminal, a background process from nohup, a crashed app that left a child process holding the socket, or a tmux session you forgot about. ss shows your own program name. Stop it:
kill 52811
# only if it ignores SIGTERM:
kill -9 52811
Node.js, Python and Go dev servers are frequent offenders after closing the terminal window with Ctrl+Z (suspends, does not stop) instead of Ctrl+C. Run jobs and fg to bring it back and stop it.
Cause 3: Docker or Podman published the port
A container with -p 80:80 holds the host port through docker-proxy or the container runtime. ss shows docker-proxy, rootlessport or conmon as the process:
docker ps --format '{{.Names}}\t{{.Ports}}'
docker stop <name>
podman ps
In Compose, change the host side of the mapping ("8081:80") to run two stacks side by side. More in the docker commands cheat sheet and the Docker on Linux guide.
Cause 4: systemd socket activation
Some ports are held by systemd itself through a .socket unit, which starts the service on the first connection. ss shows systemd (PID 1) as the owner. Examples: cups.socket (631), ssh.socket on Ubuntu (22), cockpit.socket (9090). Stopping only the service is not enough; stop the socket:
systemctl list-sockets
sudo systemctl disable --now cockpit.socket
On Ubuntu, changing the SSH port means editing ssh.socket (via systemctl edit ssh.socket) or switching back to the plain ssh.service, not just sshd_config.
Cause 5: TIME_WAIT after a restart
If the error appears only for a minute or so right after you restart your own server, the previous socket's connections are in TIME_WAIT:
ss -tan state time-wait '( sport = :8080 )'
The correct fix is in the program: set SO_REUSEADDR before bind(). In Python, sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) (or allow_reuse_address = True for socketserver). Nginx, Apache, Node and Go already do this. Do not tune tcp_tw_* sysctls for this; they do not address the problem.
Cause 6: binding twice in one program, or IPv4/IPv6 overlap
A config that lists the same port twice (listen 80; in two nginx server blocks with different options, or Listen 80 twice in Apache) makes the server collide with itself. Also, on Linux an IPv6 socket on [::]:80 accepts IPv4 by default (net.ipv6.bindv6only=0), so a program that then binds 0.0.0.0:80 separately fails. Bind only [::], or set the IPV6_V6ONLY option (nginx: listen [::]:80 ipv6only=on;).
Distro-specific notes
- Ubuntu / Debian: installing
apache2ornginxstarts it immediately on port 80, so installing the second one fails at its post-install start. - Fedora / openSUSE: services are not started on install, so collisions usually appear after you enable a second one. Ports below 1024 need root or
CAP_NET_BIND_SERVICE; that gives "Permission denied", not "Address already in use". - Arch: same as Fedora; nothing listens until you enable it.
- All: rootless Podman cannot bind ports below 1024 unless
net.ipv4.ip_unprivileged_port_startis lowered.
How to prevent it
- Keep a short list of which service owns which port on each server, and disable services you do not use.
- In development, read the port from an environment variable so you can run two copies (
PORT=3001). - Stop servers with Ctrl+C, not by closing the terminal or Ctrl+Z.
Frequently asked questions
How do I find which process is using a port on Linux?
Run sudo ss -ltnp 'sport = :8080' for TCP (use -lunp for UDP). sudo lsof -i :8080 and sudo fuser -v 8080/tcp give the same answer.
How do I kill the process on a port?
If it belongs to a service, stop the service with systemctl stop so it does not restart. Otherwise sudo fuser -k 8080/tcp kills whatever listens there.
Why do I get the error right after restarting my own server?
The old socket is in TIME_WAIT, or the old process has not exited yet. Set SO_REUSEADDR on the listening socket before bind(), which every major server does by default.
Why does ss show nothing but the bind still fails?
Run ss with sudo so it can see other users' processes, check both IPv4 and IPv6 ([::]:80 can cover IPv4 too), and check if the port is held by a container or a systemd socket unit.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.