Last active
March 24, 2026 14:47
-
-
Save adujardin/69022c8d5876b4863bd85a865d05290a to your computer and use it in GitHub Desktop.
Jetson setup xrdp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Setup xrdp to share the existing GPU-accelerated virtual display (Jetson / headless NVIDIA) | |
| # Prerequisites: | |
| # - Ubuntu 22.04 (Jetson recommended) | |
| # - Will auto-detect and offer to install virtual display if missing | |
| # | |
| # Usage: sudo ./setup-xrdp-virtual-display.sh [username] | |
| # | |
| # Safe to run multiple times (idempotent). | |
| # | |
| # Connect from Remmina (or any RDP client) to <ip>:3389 | |
| # At the xrdp login screen, select "ExistingDesktop" and enter any password. | |
| set -e | |
| if [ "$(id -u)" -ne 0 ]; then | |
| echo "Error: must run as root (sudo)." | |
| exit 1 | |
| fi | |
| # --- Check if running on a Jetson platform --- | |
| if [ -f /etc/nv_tegra_release ] || [ -d /sys/devices/soc0 ] && grep -qi "tegra\|jetson" /sys/devices/soc0/family 2>/dev/null; then | |
| echo "Jetson platform detected." | |
| else | |
| echo "WARNING: This does not appear to be a Jetson platform." | |
| read -rp "Continue anyway? [y/N] " answer | |
| if [[ ! "$answer" =~ ^[Yy] ]]; then | |
| echo "Aborted." | |
| exit 0 | |
| fi | |
| fi | |
| # --- Check if virtual display is configured --- | |
| VIRTUAL_DISPLAY_OK=false | |
| if grep -q 'AllowEmptyInitialConfiguration' /etc/X11/xorg.conf 2>/dev/null && \ | |
| grep -q 'CustomEDID' /etc/X11/xorg.conf 2>/dev/null; then | |
| VIRTUAL_DISPLAY_OK=true | |
| echo "Virtual display configuration found in /etc/X11/xorg.conf." | |
| fi | |
| if [ "$VIRTUAL_DISPLAY_OK" = false ]; then | |
| echo "WARNING: Virtual display is not configured." | |
| echo " This script requires a virtual display with nvidia DDX + fake EDID" | |
| echo " to provide a GPU-accelerated headless session (EGL, Argus, CUDA)." | |
| read -rp "Download and run setup-virtual-display.sh? [y/N] " answer | |
| if [[ "$answer" =~ ^[Yy] ]]; then | |
| VDISP_SCRIPT="/tmp/setup-virtual-display.sh" | |
| echo " Downloading setup-virtual-display.sh..." | |
| curl -fsSL "https://gist.githubusercontent.com/adujardin/9154a619cbf5a5508e5fad336839702b/raw/d4d3789928fb4855a6759508171836286f9d991e/setup-virtual-display.sh" -o "$VDISP_SCRIPT" | |
| chmod +x "$VDISP_SCRIPT" | |
| echo " Running setup-virtual-display.sh..." | |
| bash "$VDISP_SCRIPT" | |
| echo " Virtual display setup complete." | |
| else | |
| echo "Aborted. Set up the virtual display first, then re-run this script." | |
| exit 0 | |
| fi | |
| fi | |
| USERNAME="${1:-$(logname 2>/dev/null || echo user)}" | |
| USER_UID=$(id -u "$USERNAME") | |
| echo "=== Setting up xrdp for user '$USERNAME' (uid=$USER_UID) ===" | |
| # 1. Enable GDM auto-login (required for headless GNOME session) | |
| echo "[1/5] Configuring GDM auto-login..." | |
| if grep -q "^AutomaticLogin=$USERNAME" /etc/gdm3/custom.conf 2>/dev/null; then | |
| echo " Already configured, skipping." | |
| else | |
| cat > /etc/gdm3/custom.conf << EOF | |
| [daemon] | |
| WaylandEnable=false | |
| AutomaticLoginEnable=true | |
| AutomaticLogin=$USERNAME | |
| [security] | |
| [xdmcp] | |
| [chooser] | |
| [debug] | |
| EOF | |
| echo " Done." | |
| fi | |
| # 2. Install packages | |
| echo "[2/5] Installing xrdp and x11vnc..." | |
| NEEDED="" | |
| dpkg -s xrdp >/dev/null 2>&1 || NEEDED="$NEEDED xrdp" | |
| dpkg -s x11vnc >/dev/null 2>&1 || NEEDED="$NEEDED x11vnc" | |
| if [ -n "$NEEDED" ]; then | |
| apt install -y $NEEDED | |
| else | |
| echo " Already installed, skipping." | |
| fi | |
| # 3. Create x11vnc systemd service | |
| # Auto-detects the display number from /tmp/.X11-unix/ | |
| # Runs as the user so it can access the Xauthority | |
| echo "[3/5] Creating x11vnc service..." | |
| cat > /etc/systemd/system/x11vnc.service << SVC | |
| [Unit] | |
| Description=x11vnc VNC server for existing display | |
| After=gdm.service | |
| StartLimitIntervalSec=60 | |
| StartLimitBurst=5 | |
| [Service] | |
| Type=simple | |
| User=$USERNAME | |
| Environment=XAUTHORITY=/run/user/$USER_UID/gdm/Xauthority | |
| ExecStart=/bin/bash -c 'DISP=\$(ls /tmp/.X11-unix/ | grep X | head -1 | sed s/X/:/); exec /usr/bin/x11vnc -display \$DISP -auth /run/user/$USER_UID/gdm/Xauthority -rfbport 5900 -localhost -forever -nopw -shared -noxdamage' | |
| Restart=on-failure | |
| RestartSec=5 | |
| [Install] | |
| WantedBy=multi-user.target | |
| SVC | |
| echo " Done." | |
| # 4. Configure xrdp to connect to the existing display via x11vnc | |
| echo "[4/5] Configuring xrdp..." | |
| if grep -q "^name=ExistingDesktop" /etc/xrdp/xrdp.ini 2>/dev/null; then | |
| echo " Already configured, skipping." | |
| else | |
| # Backup original config (only on first run) | |
| [ ! -f /etc/xrdp/xrdp.ini.orig ] && cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.orig | |
| sed -i '/^\[Xorg\]/,/^code=20/c\[Xorg]\nname=ExistingDesktop\nlib=libvnc.so\nusername=na\npassword=ask\nip=127.0.0.1\nport=5900' /etc/xrdp/xrdp.ini | |
| echo " Done." | |
| fi | |
| # 5. Enable and start services | |
| echo "[5/5] Enabling services..." | |
| systemctl daemon-reload | |
| systemctl enable x11vnc.service | |
| systemctl enable xrdp | |
| echo " Done." | |
| echo "" | |
| echo "=== Setup complete! Reboot for everything to start cleanly. ===" | |
| echo "After reboot, connect via RDP to port 3389." | |
| echo "At the xrdp login screen, select 'ExistingDesktop' and enter any password." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment