Skip to main content

Running Linux GUI Apps Remotely on Windows with SSH and X Server

When working on remote development via SSH, you sometimes need a graphical user interface (GUI). This guide explains how to set up and use an X server on Windows to run graphical Linux applications remotely via SSH, perfect for scenarios like using ROS with VS Code on a Windows machine while connecting to a Linux host.

X Server SSH Setup

Overview

X11 forwarding allows you to run graphical applications on a remote Linux machine and display them on your local Windows desktop. This is particularly useful for:

  • Remote development with GUI tools
  • Running ROS applications with visualization (RViz, Gazebo)
  • Using Linux-specific GUI applications from Windows
  • Docker containers with GUI applications

1. Install X Server for Windows

Download and install VcXsrv, a popular and reliable X Server for Windows:

Download VcXsrv Windows X Server

Installation steps:

  1. Download the installer from SourceForge
  2. Run the installer with administrator privileges
  3. Follow the installation wizard with default settings
  4. VcXsrv will be installed and available in your Start Menu

Option 2: Xming

Alternative X Server option:

Download Xming

Option 3: X410 (Microsoft Store)

Commercial option available in Microsoft Store with enhanced features and support.

2. Configure and Start VcXsrv

2.1 Launch VcXsrv

  1. Open VcXsrv from the Start Menu (search for "VcXsrv")
  2. You'll see the "XLaunch" configuration wizard

2.2 Configuration Steps

Step 1: Display Settings

  • Select "Multiple windows"
  • Display number: 0 (default)
  • Click "Next"

Step 2: Client startup

  • Select "Start no client"
  • Click "Next"

Step 3: Extra Settings

  • ✅ Check "Clipboard" (enables clipboard sharing)
  • ✅ Check "Primary Selection" (additional clipboard support)
  • ✅ Check "Native opengl" (better graphics performance)
  • Important: Check "Disable access control" (allows connections)
  • Additional Parameters: -ac -multiwindow
  • Click "Next"

Step 4: Finish Configuration

  • Optionally save the configuration for future use
  • Click "Finish"

2.3 Verify VcXsrv is Running

  • Check the system tray for the VcXsrv icon
  • The X Server should now be listening on port 6000
Security Note

Disabling access control allows any machine to connect to your X server. Only use this in trusted network environments. For production environments, consider using specific host access controls.

3. Configure Windows Firewall

3.1 Allow VcXsrv Through Firewall

# Open PowerShell as Administrator and run:
New-NetFirewallRule -DisplayName "VcXsrv" -Direction Inbound -Program "C:\Program Files\VcXsrv\vcxsrv.exe" -Action Allow

3.2 Alternative: Manual Firewall Configuration

  1. Open Windows Defender Firewall
  2. Click "Allow an app or feature through Windows Defender Firewall"
  3. Click "Change Settings" → "Allow another app"
  4. Browse to C:\Program Files\VcXsrv\vcxsrv.exe
  5. Add and enable for both Private and Public networks

4. Connect to Linux Host via SSH

4.1 Basic X11 Forwarding

Connect to your Linux machine with X11 forwarding enabled:

# Basic X11 forwarding
ssh -X username@host_ip_address

# Trusted X11 forwarding (faster, less secure)
ssh -Y username@host_ip_address

# With compression for better performance over slow connections
ssh -XC username@host_ip_address

4.2 Advanced SSH Configuration

Create or edit ~/.ssh/config on your Windows machine:

Host mylinuxserver
HostName 192.168.1.100
User myusername
ForwardX11 yes
ForwardX11Trusted yes
Compression yes
CompressionLevel 6

Then connect simply with:

ssh mylinuxserver

4.3 Verify SSH X11 Forwarding

After connecting, check if X11 forwarding is working:

# Check DISPLAY variable
echo $DISPLAY
# Should show something like: localhost:10.0

# Test with a simple X application
xeyes
# or
xclock

5. Configure Linux Host

5.1 Set DISPLAY Environment Variable

On the Linux host, set the DISPLAY variable to point to your Windows machine:

# Get your Windows machine's IP address
export DISPLAY=192.168.1.50:0.0

# Make it persistent (add to ~/.bashrc)
echo "export DISPLAY=192.168.1.50:0.0" >> ~/.bashrc

Finding your Windows IP address:

# On Windows Command Prompt or PowerShell
ipconfig

5.2 Configure xhost for Access Control

# Allow all connections (less secure)
xhost +

# Allow specific IP (more secure)
xhost +192.168.1.50

# Allow specific host
xhost +INET:192.168.1.50

# Check current access control list
xhost

5.3 Alternative: Use SSH X11 Forwarding Only

If you prefer not to modify DISPLAY manually, rely on SSH's automatic X11 forwarding:

# SSH will automatically set DISPLAY variable
ssh -X username@host

# Verify automatic setting
echo $DISPLAY
# Should show: localhost:10.0 or similar

6. Test GUI Applications

6.1 Simple Test Applications

# Test with basic X applications
xclock & # Analog clock
xeyes & # Eyes that follow cursor
xterm & # Terminal window
gedit & # Text editor

6.2 Advanced Applications

# Test with more complex applications
firefox & # Web browser
nautilus & # File manager
gnome-calculator & # Calculator

# Development tools
code & # VS Code (if installed)
geany & # Code editor

6.3 ROS Applications

# ROS visualization tools
rviz & # ROS visualization
rqt & # ROS Qt GUI tools
gazebo & # Robot simulation

# Check ROS environment
roscore &
rviz &

7. Docker Containers with GUI

7.1 Basic Docker GUI Setup

# Run Docker container with GUI support
docker run -it --rm \
--env DISPLAY=$DISPLAY \
--env QT_X11_NO_MITSHM=1 \
--volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
ubuntu:20.04 \
bash

7.2 Full Docker GUI Configuration

# Complete Docker run command for GUI applications
docker run -it --rm \
--name gui-container \
--env DISPLAY=$DISPLAY \
--env QT_X11_NO_MITSHM=1 \
--env XAUTHORITY=$XAUTHORITY \
--volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
--volume $XAUTHORITY:$XAUTHORITY:rw \
--net=host \
--device /dev/dri \
your_image_name \
bash

Parameter explanations:

  • --env DISPLAY=$DISPLAY: Pass display variable to container
  • --env QT_X11_NO_MITSHM=1: Fix Qt shared memory issues
  • --volume /tmp/.X11-unix:/tmp/.X11-unix:rw: Mount X11 socket
  • --net=host: Use host networking (simplifies connection)
  • --device /dev/dri: GPU device access for hardware acceleration

7.3 Docker Compose for GUI Applications

version: '3.8'

services:
gui-app:
image: your-gui-image
environment:
- DISPLAY=${DISPLAY}
- QT_X11_NO_MITSHM=1
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:rw
network_mode: host
stdin_open: true
tty: true

8. Troubleshooting

8.1 Common Issues and Solutions

Issue: "Cannot connect to X server"

Solutions:

# Check if X server is running on Windows
# Restart VcXsrv if necessary

# Verify DISPLAY variable
echo $DISPLAY

# Test xhost permissions
xhost +

# Check SSH X11 forwarding
ssh -v -X username@host # Verbose output

Issue: Applications appear but don't respond

Solutions:

# Add Qt environment variable
export QT_X11_NO_MITSHM=1

# Try different window manager settings
export QT_QPA_PLATFORM=xcb

Issue: Clipboard not working

Solutions:

  • Ensure clipboard options are enabled in VcXsrv configuration
  • Restart VcXsrv with clipboard support
  • Use xclip for manual clipboard operations:
# Install xclip
sudo apt install xclip

# Copy to clipboard
echo "Hello" | xclip -selection clipboard

# Paste from clipboard
xclip -o -selection clipboard

Issue: Poor performance or slow response

Solutions:

# Use SSH compression
ssh -XC username@host

# Reduce color depth in VcXsrv settings
# Enable native OpenGL in VcXsrv
# Consider using VNC for better performance with complex GUIs

8.2 Network Troubleshooting

# Test network connectivity
ping 192.168.1.50

# Check if X server port is open
telnet 192.168.1.50 6000

# Verify SSH is working
ssh -v username@host

8.3 Debugging X11 Issues

# Enable X11 debug output
export DISPLAY=192.168.1.50:0.0
xhost +
xclock 2>&1 | tee x11-debug.log

# Check X11 authentication
xauth list

# Test basic X functionality
xwininfo
xdpyinfo

9. Performance Optimization

9.1 Network Optimization

# SSH with optimized settings
ssh -o Compression=yes -o CompressionLevel=6 -X username@host

# Use faster SSH ciphers
ssh -c aes128-ctr -X username@host

9.2 VcXsrv Optimization

  • Enable "Native OpenGL" for better graphics performance
  • Use "Multiple windows" mode for better window management
  • Adjust DPI settings if applications appear too small/large

9.3 Application-Specific Optimizations

# For Qt applications
export QT_X11_NO_MITSHM=1
export QT_GRAPHICSSYSTEM=native

# For GTK applications
export GDK_SYNCHRONIZE=0

# For Java applications
export _JAVA_AWT_WM_NONREPARENTING=1

10. Security Considerations

10.1 Secure X11 Configuration

Instead of xhost +, use specific permissions:

# Allow only specific hosts
xhost +inet:192.168.1.50

# Use xauth for better security
xauth add $(xauth -f ~/.Xauthority list | tail -1)

# Restrict to localhost only (with SSH forwarding)
export DISPLAY=localhost:10.0

10.2 SSH Security

# Use key-based authentication
ssh-keygen -t rsa -b 4096
ssh-copy-id username@host

# Disable password authentication in SSH config
# Edit /etc/ssh/sshd_config:
# PasswordAuthentication no

10.3 Firewall Configuration

# Restrict X11 port access
sudo ufw allow from 192.168.1.0/24 to any port 6000

# Use SSH tunneling instead of direct X11 connection
ssh -L 6000:localhost:6000 username@host

Resources

Pro Tips
  • Save your VcXsrv configuration for quick startup
  • Use SSH config files for easy connection management
  • Consider using Windows Terminal for better SSH experience
  • Set up key-based authentication for passwordless connections
Performance Note

For intensive GUI applications, consider using VNC or Remote Desktop solutions instead of X11 forwarding for better performance.