Skip to content

VcXsrv WSL2 vsock User Guide

millin edited this page Jul 22, 2026 · 4 revisions

VcXsrv WSL2 vsock User Guide


English

This guide shows how to connect X clients in WSL2 to VcXsrv over Hyper-V vsock, replacing the default NAT / localhost-forwarded TCP path.

Why vsock

TCP path (default) vsock path
Latency Via the WSL2 localhost relay; noticeable stutter with mouse-heavy event streams Direct, significantly lower
Sleep/resume, VPN changes Connections may drop Unaffected
Firewall May trigger allow prompts No network stack involved, no prompts
Setup Look up host IP / enable localhostForwarding Just DISPLAY=:0

Quick start (3 steps)

Prerequisites: WSL2 (Store WSL 2.0+), socat >= 1.7.4 (sudo apt install socat).

  1. Start VcXsrv on Windows with -vsock:
vcxsrv.exe :0 -multiwindow -clipboard -vsock

The log (%TEMP%\VCXSrv.0.log) should show:

winVsock: WSL2 VM xxxxxxxx-xxxx-... detected, vsock listener enabled
  1. In WSL2, start the relay (one command):
socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork,mode=777 VSOCK-CONNECT:2:106000 &
  • 2 = VMADDR_CID_HOST, i.e. "the host" (the guest side never needs to know any VM GUID)
  • 106000 = the vsock port, by convention 106000 + display number (:0 → 106000, :1 → 106001)
  1. Run X programs:
export DISPLAY=:0
xeyes

To verify you are really on vsock: while the app is running, run ss --vsock | grep '2:106000' — you should see an ESTAB connection.

Making it persistent

socat should start with WSL. Pick one of:

Simple (~/.bashrc or /etc/profile.d/x11vsock.sh):

if ! pgrep -f "VSOCK-CONNECT:2:106000" >/dev/null; then
    rm -f /tmp/.X11-unix/X0
    socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork,mode=777,forever,retry=10,interval=2 \
          VSOCK-CONNECT:2:106000 &
fi
export DISPLAY=:0

forever,retry lets socat reconnect within seconds after a VcXsrv or WSL restart (together with the server-side automatic rebind, the whole path self-heals). socat does not remove the X0 socket file on exit, so rm -f before restarting it avoids "Address already in use".

systemd (for distros with systemd enabled):

# /etc/systemd/system/x11vsock.service
[Unit]
Description=VcXsrv vsock relay
After=multi-user.target

[Service]
ExecStartPre=/bin/rm -f /tmp/.X11-unix/X0
ExecStart=/usr/bin/socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork,mode=777,forever,retry=10000,interval=2 VSOCK-CONNECT:2:106000
Restart=always

[Install]
WantedBy=multi-user.target

sudo systemctl enable --now x11vsock, and export DISPLAY=:0 in /etc/profile.d.

For older socat (< 1.7.4, without VSOCK-CONNECT), use the raw form:

socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork,mode=777 \
      SOCKET-CONNECT:40:0:x0000x109e0100x02000000x00000000 &

(0x00019E10 = 106000, little-endian; display :1 is 106001 → x119e0100.)

WSLg conflicts

On machines with WSLg enabled, /tmp/.X11-unix/X0 is taken by WSLg. Either:

  • Start VcXsrv on a different display (e.g. :1) and use UNIX-LISTEN:.../X1 + VSOCK-CONNECT:2:106001 + export DISPLAY=:1, or
  • Disable WSLg (guiApplications=false in .wslconfig).

Manual mode (when not using -vsock)

Goal Option
Bind a specific VM (manual GUID) -vmid {GUID} (get it via wsl.exe -- wslinfo --vm-id; braces required)
Change the vsock base port -vsockport 6000 (then :0 → 6000, :1 → 6001)
Serve regular Hyper-V VMs -listen hyperv (wildcard bind; works for regular VMs, not for WSL2)
Disable vsock entirely -novsock (this is the default; no need to pass it)

For regular Hyper-V VMs: by Microsoft convention, a guest connecting to a host service GUID normally requires the service to be registered in the host registry under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\<GUID> (requires admin); the guest uses the same socat relay. Whether unregistered services are accepted depends on the host configuration — test it.

Limitations and notes

  • One listener, one VM: a VcXsrv instance binds its vsock listener to a single VM id; it cannot serve WSL2 plus another VM at the same time (workaround: two instances, see below).
  • Self-healing across WSL restarts: after wsl --shutdown, once a distro starts again the server rebinds to the new VM id within about 2–4 seconds (no need to restart VcXsrv); with forever,retry, socat reconnects automatically. Manual -vmid mode still requires restarting VcXsrv after a WSL VM restart.
  • No cookie: vsock connections are treated as local clients (same trust level as 127.0.0.1); MIT-MAGIC-COOKIE is not required by default. Only the single bound VM can reach the listener.
  • WSL1: has no VM layer and does not support vsock; -vsock simply falls back to TCP silently — no error.
  • Multiple instances: vcxsrv :0 -vsock and vcxsrv :1 -vsock bind 106000/106001 respectively; use X0/X1 socats on the WSL side. Give the second instance -noclipboard to avoid clipboard contention. Two instances can also serve WSL2 and a regular VM separately (one with -vsock, one with -listen hyperv).
  • Running vcxsrv as a different user: the VM id query sees that user's WSL instance, not yours.

Troubleshooting

Symptom What to check
Can't open display: :0 Is socat running (pgrep -a socat)? Does DISPLAY match the socket socat created (X0 ↔ :0)? Remove the stale socket (rm -f /tmp/.X11-unix/X0) and restart socat
socat connect ... cid:2 port:106000 ... timed out Was VcXsrv started with -vsock? Is the VM id line in the log? After a WSL restart the old GUID is stale (-vsock rebinds automatically — wait 2–4 seconds)
Not sure which path you are on While the app runs, ss --vsock \| grep '2:106000' should show ESTAB; or start VcXsrv with -nolisten tcp to rule TCP out
No log lines at all The log is %TEMP%\VCXSrv.<display>.log; make sure WSL is running (Task Manager should show a "Vmmem WSL" process)

Clone this wiki locally