Skip to content

GUI Forwarding & Remote Desktop

Run graphical applications on your Azure VMs and display them locally. azlin supports two approaches: VNC for a full remote desktop session and X11 forwarding for lightweight GUI apps.

Overview

Approach Best For Latency Setup
VNC Desktop Full desktop environment, multiple apps Higher (full desktop) Auto-managed
VNC Minimal Window manager only, no desktop overhead Medium Auto-managed
VNC Single App One app in VNC (e.g. browser), exits when app closes Medium Auto-managed
X11 Forwarding Individual GUI apps (gitk, meld, xeyes) Low (per-window) Minimal

Both approaches work transparently through Azure Bastion tunnels when your VM has no public IP.

Prerequisites

Local Machine

WSL2 (Windows): - WSLg is included with WSL2 by default and provides an X server automatically. - Verify with: echo $DISPLAY (should show something like :0)

Linux: - An X11 display server is already running if you are in a graphical session. - Verify with: echo $DISPLAY

macOS: - Install XQuartz: brew install --cask xquartz - Log out and back in after installation. - Enable "Allow connections from network clients" in XQuartz Preferences > Security.

VNC Viewer (for azlin gui only): - Any VNC client works. Recommendations: - TigerVNC (cross-platform, free) - RealVNC Viewer (cross-platform, free for personal use) - Remmina (Linux, free)

Remote VM

No manual setup required. azlin automatically installs any missing packages on the VM when you use azlin gui or azlin connect --x11.

VNC Desktop

Launch a full remote desktop session on the VM and view it locally.

Usage

# Full XFCE desktop (default)
azlin gui my-vm

# Minimal window manager only (openbox) -- no desktop overhead
azlin gui my-vm --minimal

# Single application mode -- VNC exits when the app closes
azlin gui my-vm --app "chromium-browser --no-sandbox"
azlin gui my-vm --app "gimp"

# Custom resolution
azlin gui my-vm --resolution 2560x1440

# Specify SSH user and key
azlin gui my-vm --user azureuser --key ~/.ssh/azlin_key

VNC Modes

Mode Flag Desktop Window Manager Best For
Full Desktop (default) XFCE XFCE WM Multi-app workflows, full desktop experience
Minimal --minimal None openbox Lightweight sessions, launch apps from right-click menu
Single App --app "cmd" None None Running one heavy GUI app (browser, IDE, GIMP)

Minimal mode starts only the openbox window manager. Right-click on the desktop for an app launcher menu. Drag window edges to resize. Much lighter than a full desktop.

Single app mode runs the specified command directly. The VNC window shows only that application. When the app is closed, the VNC server exits automatically.

Chromium/browsers

Use --no-sandbox flag when running Chromium in VNC: azlin gui my-vm --app "chromium-browser --no-sandbox". This is required because the VNC session runs as a regular user without a full desktop sandbox.

How It Works

  1. Dependency check: azlin SSHs into the VM and checks for required packages (tigervnc-standalone-server, xfce4, dbus-x11). Missing packages are installed automatically.
  2. VNC server start: A TigerVNC server is started on the VM, bound to localhost only (no network exposure). A random password is generated for the session.
  3. Tunnel creation: azlin creates an SSH tunnel (or bastion tunnel) forwarding a local port to the VNC server port on the VM.
  4. Viewer launch: azlin launches your local VNC viewer, connecting to localhost:<local_port> with the session password.
  5. Cleanup: When you close the VNC viewer, azlin stops the VNC server on the VM and tears down the tunnel.

Options

Option Default Description
--resolution 1920x1080 Desktop resolution (WIDTHxHEIGHT)
--depth 24 VNC color depth (8, 16, or 24)
--user azureuser SSH username on the VM
--key ~/.ssh/azlin_key Path to SSH private key
--minimal false Use openbox window manager instead of full XFCE desktop
--app none Run a single application (e.g. --app "chromium-browser")
-y, --yes false Skip dependency installation prompts

Dependency Management

azlin automatically detects and installs missing packages on first use:

Package Purpose
tigervnc-standalone-server VNC server
xfce4 Lightweight desktop environment
xfce4-terminal Terminal emulator for the desktop
dbus-x11 D-Bus session bus (required by XFCE)

Installation happens once per VM and takes 2-3 minutes. Subsequent connections skip this step.

Security

VNC security is handled through multiple layers:

  • Localhost binding: The VNC server listens on 127.0.0.1 only. It is never exposed to the network.
  • Random passwords: A unique password is generated for each session using openssl rand. Passwords are not stored on disk.
  • SSH tunnel: All VNC traffic travels through the encrypted SSH (or bastion) tunnel. No VNC traffic crosses the network unencrypted.
  • Automatic cleanup: The VNC server is stopped when the session ends, leaving no listening services behind.

X11 Forwarding

Forward individual GUI windows from the VM to your local display. Best for lightweight apps where you don't need a full desktop.

Usage

# Connect with X11 forwarding enabled
azlin connect --x11 my-vm
# Short form
azlin connect -X my-vm

# Then on the VM, run any GUI app:
xeyes &
gitk --all &
meld file1 file2 &

How It Works

  1. azlin connect --x11 adds the -Y flag (trusted X11 forwarding) to the SSH connection.
  2. SSH sets up an encrypted tunnel for X11 protocol traffic.
  3. The remote DISPLAY environment variable is set automatically by SSH.
  4. GUI windows render on your local X server through the tunnel.
  5. When connecting through Azure Bastion, the X11 tunnel is layered on top of the bastion tunnel seamlessly.

Running Specific Applications

Run any remote GUI app directly without opening an interactive session:

# Run a single app via X11 -- app window appears locally
azlin connect my-vm --x11 --no-tmux -- chromium-browser
azlin connect my-vm --x11 --no-tmux -- eog ~/screenshot.png
azlin connect my-vm --x11 --no-tmux -- thunar
azlin connect my-vm --x11 --no-tmux -- gitk --all
azlin connect my-vm --x11 --no-tmux -- meld file1.py file2.py

The --no-tmux flag avoids wrapping in tmux, and -- separates azlin args from the remote command. The app renders locally and the connection closes when the app exits.

Common GUI Applications

Application Command Purpose
xeyes xeyes Quick test that X11 forwarding works
gitk gitk --all Visual git history browser
meld meld dir1 dir2 Visual diff and merge tool
gedit gedit file.py Lightweight text editor
Chromium chromium-browser Web browser (consider VNC for better performance)
eog eog image.png Image viewer
thunar thunar File manager
Firefox firefox Web browser (heavier, consider VNC)
VS Code code --disable-gpu Editor (use --disable-gpu over SSH)

Troubleshooting

VNC: Connection refused when viewer launches

The tunnel may not be ready yet. Retry the connection:

azlin gui my-vm

VNC: Black screen or no desktop

The desktop environment may not have started correctly:

# SSH into the VM and check the VNC log
azlin connect my-vm
cat ~/.vnc/*.log

# Restart the desktop environment
vncserver -kill :1
vncserver -localhost yes -geometry 1920x1080 :1

VNC: Screen resolution is wrong

Pass the --resolution flag:

azlin gui my-vm --resolution 2560x1440

VNC: Clipboard not working

Install autocutsel on the VM for bidirectional clipboard support:

# On the VM
sudo apt-get install -y autocutsel
autocutsel -fork

X11: Can't open display

The DISPLAY variable is not set on the VM. Verify the connection was made with --x11:

azlin connect --x11 my-vm

# On the VM, check DISPLAY is set
echo $DISPLAY
# Should show something like: localhost:10.0

X11: Connection rejected (wrong authentication)

Regenerate xauth cookies:

# On the VM
xauth generate $DISPLAY . trusted

X11: Apps are slow or laggy

X11 forwarding sends individual draw commands over the network. For heavy GUI usage, switch to VNC (azlin gui) which sends compressed screen updates instead.

Bastion Tunnel Issues

Both X11 and VNC work through Azure Bastion tunnels. If connections fail:

# Verify Bastion tunnel is working
azlin bastion status my-bastion --resource-group my-rg

# Test basic SSH connectivity first
azlin connect my-vm

# Then try GUI forwarding
azlin connect --x11 my-vm

Performance Tips

  • VNC: Best for multi-app workflows or desktop environments. Choose a reasonable resolution.
  • X11: Best for lightweight apps (gitk, meld, xeyes). Avoid full browsers or IDEs.
  • Region proximity: VMs in regions closer to you will have noticeably lower GUI latency.
  • VM size: GUI rendering uses CPU; choose at least Standard_D2s_v3 or above for smooth performance.