Localhost Development: ip, ports & co.
1. Context
This is a back to basics about developing local servers.
It’s mainly a reference for my future self.
2. Network Interfaces
Your computer has multiple network interfaces. Each interface is assigned with a specific IP address. One such virtual interface is called loopback.
On a Mac, you can run ifconfig to list your network interfaces.
Here is a summary of the kind of interface you might see:
| Name | Description |
|---|---|
lo0 |
Loopback |
gif0 |
Generic IP tunnel (VPN) |
stf0 |
IPv4 to IPv6 tunnel, obsolete |
anpiX |
Apple Network Processor Interface, virtual usb-c interfaces |
enX |
Ethernet interface (wifi, wired, dock, etc.) |
ap0 |
Access Point interface, for when laptop is a Wifi hotspot |
awdl0 |
Apple Wireless Direct Link for Airdrop and Airplay |
bridge0 |
Network bridge (usually for enX) to share traffic between interfaces |
llw0 |
Low Latency Wireless for Homekit/IoT |
utunX |
Tunnel interfaces (VPN) |
3. Loopback
4. Localhost
.localhost is one of the 4 reserved gTLD to help with development, along with .example, .invalid and .test.
x.localhost is guarranteed to resolve to the loopback address on the loopback interface.
5. 0.0.0.0?
:: or 0.0.0.0 are special: listening on those IPs means listening on all interface of this device.
This is only useful if you want to access your local server on the same network, like if you run your server on your laptop, but want to access it from your phone.
For this usecase, I’d recommend mDNS, though.
6. Ports
| Range | Description |
|---|---|
0-1023 |
System Ports/Well Known Ports, required escalated priviledges |
1024-49151 |
User Port/Registered Ports, usables |
49152-65535 |
Dynamic Ports, never assigned, for clients |
Port 0 is special: binding to it will result in the OS assigning a randomly available free port.
Realistically, only the User Ports should be used, and it’s common to bind to port 8080 for http traffic, or nearby.
7. Static Recommendations
For running a server locally, listen to localhost and a free port
like 8080. Ensure the port is changeable via a configuration to allow running more than 1 service at a time.
To avoid remembering the ports of each service, and to help with TLS, you may want to have a reverse proxy listening on localhost:80, and let it handle the conversion with sub dns, like api.localhost being routed to localhost:8080, and db.localhost is routed to localhost:8083, etc.
This is what Traeffic partially automates in with labels in docker-compose, but you can do this locally with Caddy:
api.localhost {
reverse_proxy localhost:8080
}
db.localhost {
reverse_proxy localhost:8083
}
8. Kubernetes Recommendations
If your container listens on localhost in kubernetes, only other containers in that pod will be able to access your server.
Kubernetes will make the traffic reach your container through a different network interface.
Since you usually do not know in advance which IP will be given to you, it is recommended to expose your container server on all network interfaces (aka :: or 0.0.0.0).
9. Dynamic Recommendations
If you have a registry, like in a service mesh, it makes sense to bind to localhost and port 0 and then publish this to your registry.