Bun.serve default bind address: restricting a dev server to localhost only
0 reputation · 20 May 2026, 12:20 UTC
0 reputation · 20 May 2026, 12:20 UTC
I'm configuring a development server with Bun.serve() and want to make sure it is never reachable from other machines on the network. My understanding is that when no hostname is given, Bun binds to all interfaces (0.0.0.0 / ::), which would expose the port beyond localhost if the host firewall permits it.
My constraints: I want the restriction expressed in the server configuration itself rather than relying on a firewall rule or a reverse proxy, and the same code should behave identically for every developer on the team regardless of their machine's network setup. I'm also unsure whether the default binding behavior is stable across Bun versions, or whether it has changed between releases.
Assuming a current Bun v1.x release:
hostname: "127.0.0.1" to Bun.serve() the supported way to guarantee loopback-only binding, and does it cover IPv6 loopback as well?33275 reputation · 20 May 2026, 22:57 UTC
To guarantee that a development server started with Bun.serve() is reachable only from the loopback interface, explicitly set the hostname option. For IPv4 loopback use hostname: "127.0.0.1"; for IPv6 loopback use hostname: "::1". The default behavior of binding to all interfaces (0.0.0.0 / ::) is documented as stable across Bun v1.x releases, so you can rely on it unless you override it.
hostname: "127.0.0.1" to Bun.serve() binds the server to the IPv4 loopback address only."127.0.0.1" does not automatically include the IPv6 loopback (::1); a separate hostname value is required for IPv6.hostname is provided, the server binds to 0.0.0.0 (IPv4) and :: (IPv6), i.e., all network interfaces, and this behavior has remained unchanged in the v1.x series.Bun.serve() (e.g., server.address()) or with OS tools such as ss -tulpn or netstat -an.The hostname option is forwarded directly to the underlying TCP listener. Supplying a literal loopback address tells the OS to accept connections only on that interface, preventing external LAN hosts from reaching the port even if the firewall allows it. Because the option is explicit, the behavior is identical for every developer regardless of their machine’s network configuration.
hostname value, e.g.: const server = Bun.serve({ hostname: '127.0.0.1', port: 3000, fetch(req) { return new Response('hello'); } });console.log('Listening on', server.address()); This will show an object containing address: '127.0.0.1' (or '::1' for IPv6).ss -tulpn | grep 3000 or netstat -an | grep 3000 and verify that the local address column shows 127.0.0.1:3000 (or [::1]:3000).Do you need the server to be reachable via IPv6 loopback (::1) as well as IPv4? If yes, you must either set hostname: '::1' (IPv6 only) or run two separate instances, one for each loopback address, because a single hostname value does not bind to both stacks simultaneously.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.