What this builds
The end result is a Linux desktop you open from any browser through the Cloudflare App Launcher — the session is brokered by Cloudflare Access and tunnelled to the host's local VNC port, so nothing is exposed directly to the internet.
Assumes you already have
- A Linux host with the XFCE desktop installed and
sudoaccess. - A Cloudflare Zero Trust account with a tunnel / connector already installed on (or reaching) the host's network.
- The host's private IP address — you'll point the tunnel at
<host-ip>:5901in Phase 3.
Example username is netadmin and the geometry/IP values are illustrative — substitute your own throughout.
Host machine setup (Linux)
1.1 — Install required toolsets
Update the package manager and install TigerVNC along with the required session controllers:
sudo apt update
sudo apt install -y tigervnc-standalone-server tigervnc-common dbus-x111.2 — Configure VNC authentication
Run the password utility as the regular user account (e.g. netadmin). Do not run this as root or with sudo:
vncpasswd- Set your access password when prompted (minimum 6 characters).
- Type
nwhen asked whether to configure a view-only password.
1.3 — Create the desktop startup script
Create or overwrite the environment profile script:
nano ~/.config/tigervnc/xstartupPaste the following exactly. It clears conflicting desktop variables and forces the native XFCE desktop to stay in the foreground:
#!/bin/sh
# Unset previous active desktop variables to avoid conflicts
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
# Grant permissions and define user runtime directories
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
install -d -m 700 "$XDG_RUNTIME_DIR"
# Read user interface resources if present
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
# Execute the local system configuration layers
xsetroot -solid grey
# Launch the desktop environment in the foreground
exec dbus-launch --exit-with-session startxfce4Save and exit (Ctrl+O, Enter, Ctrl+X).
1.4 — Apply script permissions
Grant execute privileges to the profile script:
chmod +x ~/.config/tigervnc/xstartup1.5 — Adjust host firewall (if applicable)
If the host runs a local firewall, open port 5901 for the inner-network routing layer:
sudo ufw allow 5901/tcpThis only opens the port on the host's local firewall for the tunnel to reach it — the port is never published to the internet. Cloudflare brokers all external access.
System-wide automation (systemd)
2.1 — Create the global service file
So the VNC environment launches on boot without first logging into an SSH terminal, build a system-level process wrapper:
sudo nano /etc/systemd/system/vncserver.serviceIf your username differs from netadmin, update the User, Group, WorkingDirectory, and Environment lines to match your exact home directory.
[Unit]
Description=Remote desktop service (VNC) via Cloudflare Architecture
After=network.target network-online.target
[Service]
Type=simple
User=netadmin
Group=netadmin
WorkingDirectory=/home/netadmin
Environment=HOME=/home/netadmin
# Clean up stale pid/lock files from unexpected crashes/reboots
ExecStartPre=-/usr/bin/vncserver -kill :1
# Run VNC in the foreground so systemd can track the process safely
ExecStart=/usr/bin/vncserver :1 -fg -geometry 1920x1080 -depth 24 -localhost no
[Install]
WantedBy=multi-user.targetSave and exit (Ctrl+O, Enter, Ctrl+X).
2.2 — Activate the automation service
Reload the daemon configs, register the service to run on every boot, and start it now:
# Reload the system daemon configs
sudo systemctl daemon-reload
# Enable it to run permanently on every boot
sudo systemctl enable vncserver.service
# Start the service immediately
sudo systemctl start vncserver.service2.3 — Verification commands
| Purpose | Command |
|---|---|
| live status & error handling | sudo systemctl status vncserver.service |
| restart manually | sudo systemctl restart vncserver.service |
| stop manually | sudo systemctl stop vncserver.service |
| verify binding port | ss -tulpn | grep 5901 |
The binding-port check should show *:5901 or 0.0.0.0:5901 listening.
Cloudflare Zero Trust panel mapping
To expose this workspace cleanly through the public Cloudflare App Launcher, map the infrastructure variables in the Cloudflare Zero Trust dashboard as follows:
| Workspace setting | Dashboard field | Selection / destination |
|---|---|---|
| Tunnel configuration | Type / Protocol | Select TCP |
| Tunnel configuration | URL / Service destination | Enter <host-ip>:5901 |
| Access application | Application type | Select Self-hosted |
| Access application | Session rendering toggle | Turn ON "Allow access through browser-based RDP, SSH, or VNC sessions" |
| Access application | Session protocol dropdown | Choose VNC from the revealed selection |
| Access application | App Launcher visibility | Turn ON "Show in App Launcher" |
The desktop now appears as a tile in the Cloudflare App Launcher and opens the VNC session directly in the browser — gated by your Access policies.
The -geometry 1920x1080 parameter in the service file sets the virtual screen size; a future revision will cover adjusting it dynamically for different monitors.