-
Notifications
You must be signed in to change notification settings - Fork 0
VcXsrv WSL2 vsock User Guide
This guide shows how to connect X clients in WSL2 to VcXsrv over Hyper-V vsock, replacing the default NAT / localhost-forwarded TCP path.
| 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
|
Prerequisites: WSL2 (Store WSL 2.0+), socat >= 1.7.4
(sudo apt install socat).
- 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
- 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)
- Run X programs:
export DISPLAY=:0
xeyesTo verify you are really on vsock: while the app is running, run
ss --vsock | grep '2:106000' — you should see an ESTAB connection.
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=:0forever,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.targetsudo 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.)
On machines with WSLg enabled, /tmp/.X11-unix/X0 is taken by WSLg.
Either:
- Start VcXsrv on a different display (e.g.
:1) and useUNIX-LISTEN:.../X1+VSOCK-CONNECT:2:106001+export DISPLAY=:1, or - Disable WSLg (
guiApplications=falsein.wslconfig).
| 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.
- 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); withforever,retry, socat reconnects automatically. Manual-vmidmode 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;
-vsocksimply falls back to TCP silently — no error. -
Multiple instances:
vcxsrv :0 -vsockandvcxsrv :1 -vsockbind 106000/106001 respectively; use X0/X1 socats on the WSL side. Give the second instance-noclipboardto 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.
| 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) |