How to access localhost of linux subsystem from windows

The answer to this is surprisingly simple which is why searching isn't giving you the right results.

All that WSL does is provide a translation layer between the Linux apps and the windows kernel, very much like how Wine works on Linux. Because of this some core parts of the Ubuntu system are just not there, networking being one of them. WSL translates the Linux system calls into windows ones so the Ubuntu network data flows through the exact same TCP/IP stack as the windows data.

In short this means to access the Linux localhost you just access the windows one, they are the same. localhost:4567 or 127.0.0.1:4567 will do what you want.

As an aside I've been using rails on WSL, it seems to work perfectly except the swing and listen gems don't play well, I had to disable them.


I needed to access my WSL-hosted port from another device in my LAN
(e.g. for mobile development), and I found @Owen Tourlamain's answer of didn't help for that.

I needed to set up portproxy, and I found that using connectaddress=localhost or connectaddress=127.0.0.1 did not work for me (WSL2, Windows 10 20H2).

So I still needed the answer the the OP's question, and it turns out it's surprisingly simple:

  1. Startup WSL
  2. wsl hostname -I
    
    Output like: 172.10.200.10

Note:
You have to trim whitespace if you're using it inline in a powershell command, e.g.:

netsh interface portproxy add v4tov4 listenport=19000 listenaddress=0.0.0.0 `
    connectport=19000 connectaddress=$($(wsl hostname -I).Trim());

Accessing WSL from your network

The OP asked about accessing WSL "from windows". If you want to also access it "from your private network", you'll also need to, one time, make a firewall rule allowing a specific port (or range of ports).

⚠️ Warning: Do not turn Windows firewall "off". Make a rule to open only specific ports that you need.

(powershell as Admin)

New-NetFireWallRule -Profile Private -DisplayName 'MyRule ports for LAN development' `
    -Direction Inbound -LocalPort 19000-19006 -Action Allow -Protocol TCP

Note:

  • -LocalPort 19000-19006 ← Replace the 19000-19006 with the port(s) you need.
  • -Profile Private so that the ports are only open a network that you've marked as being "Private"
  • -Direction Inbound means inbound (ingress) only
  • -DisplayName 'MyRuleName blah blah...' is for you, human-readable name. But pick something you'll remember, because you can use this name to find the rule in the future, to view its status or to delete it. e.g. Get-NetFirewallRule | Where-Object {$_.DisplayName -Match "MyRuleName.*"}

As a temporary solution, if it stops working on WSL2, you can just shutdown WSL and run it again from PowerShell or CMD. I don't know why, but it somehow fixes this problem temporarily:

wsl --shutdown
wsl

Old question that was bumped today via another answer, so I'll chime in. This question was originally asked for WSL1. While the "answer" is the same for WSL2, there are some slight differences that need to be addressed.

First, on WSL1, as the original accepted answer from 2016 mentions, the network is really running on the Windows host interface. That's why localhost/127.0.0.1 (or the address of the Windows NIC) works there.

WSL2, on the other hand, runs virtualized, so the network interface is a vNIC with a different address than that of the Windows host. That network is actually NAT'd behind the Windows host. This is also why you can access a WSL1 instance using the Windows IP address from another machine on the network, but no so with WSL2.

But WSL2 does have a feature known as "localhost forwarding", which makes it work like WSL1 for localhost/127.0.0.1. This feature is turned on by default, but can be disabled (although I don't know of any reason for ever doing so, honestly).

This feature allows you to access a service (like a Rails app, in this question). If the port isn't in use on the Windows NIC, then WSL2 will auto-forward the localhost request to the same port on the WSL2 vNIC.

So all is well and good, and you can access both WSL1 and WSL2 services via localhost, right?

Not so fast, unfortunately. Sometimes, as two other answers have mentioned, localhostForwarding "breaks". We've identified two very common (and related) use-cases where this will happen:

  • When the host Windows is hibernated.
  • When the host Windows is powered on using Windows "Fast Startup" feature, which turns out to be enabled by default. This feature uses a form of hibernation.

The solution is:

  • Don't hibernate if possible
  • Turn off Fast Startup. You'll find it in the Control Panel. Navigate to Hardware and Sound -> Power Options -> Change what the Power Buttons do
  • If you do find yourself in a situation where the feature is not working, as @AhmetK's answer mentioned, you can typically recover localhost forwarding by:
    • Exiting all running WSL instances
    • Issuing wsl --shutdown (from PowerShell, CMD, or even the Start Menu). While a full Windows restart will have the same effect, a wsl --shutdown is much faster.
    • Restart your WSL instance and running services/apps.

Reference the comments on this SO answer which have confirmed the issue and solution.