What port 3000 is
TCP port 3000 has no official service. It is simply the port many frameworks pick by default for a local development server, so it is the one you most often find already taken. It carries plain HTTP unless you configure TLS yourself.
| Software | Default |
|---|---|
| Express examples and many Node.js apps | 3000 |
Next.js (next dev, next start) |
3000 |
| Create React App | 3000 |
Ruby on Rails (rails server) |
3000 |
| Grafana | 3000 |
| Gitea and Forgejo | 3000 |
"Port 3000 is already in use"
The error looks like Error: listen EADDRINUSE: address already in use :::3000 in Node.js, or Address already in use - bind(2) for "127.0.0.1" port 3000 in Rails. Another process is listening. Find it:
lsof -i :3000
sudo ss -tlnp 'sport = :3000'
On Windows:
netstat -ano | findstr :3000
taskkill /PID 12345 /F
Usually it is a dev server from an earlier terminal session, a crashed process, or a container. Stop it with kill <pid> (use kill -9 only if it ignores the first signal), or run on another port instead:
PORT=3001 npm start # Create React App, Express apps that read PORT
npx next dev -p 3001 # Next.js
bin/rails server -p 3001 # Rails
If a Docker container holds the port, docker ps shows a mapping such as 0.0.0.0:3000->3000/tcp; stop that container. For a stale Rails server, delete tmp/pids/server.pid after confirming the process is gone.
Should it be open to the internet?
No. Development servers are not built to face the internet: they may serve source maps, verbose error pages and debug endpoints. In production, run the app behind a reverse proxy on ports 80 and 443, and bind the app to loopback:
server {
listen 443 ssl;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Make sure the app itself listens on 127.0.0.1, not 0.0.0.0, or the firewall is the only thing keeping 3000 private. With Docker, publish it on loopback (-p 127.0.0.1:3000:3000), because Docker's published ports bypass ufw rules on most Linux setups.
If you run Grafana on 3000, the same advice applies: put it behind the proxy and change the default admin password on first login.
Firewall rules
To allow only your office network and block everyone else with ufw:
sudo ufw allow from 203.0.113.0/24 to any port 3000 proto tcp
sudo ufw deny 3000/tcp
ufw applies the first matching rule, so the allow must come before the deny. Leave out the allow line to block the port for everyone.
How to test it
From another machine:
nc -zv app.example.com 3000
curl -I http://app.example.com:3000/
Our Port Scanner does not probe port 3000, so use these commands to confirm it is closed from outside.
Related ports
- Port 5000: Flask and other dev servers.
- Port 8080: the classic alternative HTTP port.
- Port 80 and port 443: where the public site should be served.
After putting the app behind a proxy, confirm what the public URL answers with the HTTP Status Checker.