#!/bin/bash set -euo pipefail ####################################### # RDtop — One-Command RustDesk Headless Installer # Works on any Linux (Intel iGPU, AMD, NVIDIA, CPU-only, VPS) # Usage: curl -fsSL https://git.softuniq.eu/NW/RDtop/raw/branch/main/install.sh | sudo bash ####################################### ARCH=$(uname -m) case "$ARCH" in x86_64) RUSTDESK_ARCH="x86_64"; DEB_ARCH="amd64" ;; aarch64) RUSTDESK_ARCH="aarch64"; DEB_ARCH="arm64" ;; armv7l) RUSTDESK_ARCH="armv7"; DEB_ARCH="armhf" ;; *) echo "ERROR: Unsupported architecture: $ARCH"; exit 1 ;; esac RUSTDESK_VERSION="1.4.6" RUSTDESK_URL="https://github.com/rustdesk/rustdesk/releases/download/${RUSTDESK_VERSION}/rustdesk-${RUSTDESK_VERSION}-${RUSTDESK_ARCH}.deb" TMP_DEB="/tmp/rustdesk-${RUSTDESK_VERSION}-${DEB_ARCH}.deb" LOG="/tmp/rdtop-install.log" log() { echo "[$(date '+%F %T')] $1" | tee -a "$LOG"; } echo "" echo "============================================" echo " RDtop — RustDesk Headless Installer" echo " Arch: $ARCH | Package: ${RUSTDESK_ARCH}.deb" echo "============================================" echo "" # --- 1. Install dependencies --- log "[1/6] Installing dependencies..." if command -v apt-get >/dev/null 2>&1; then export DEBIAN_FRONTEND=noninteractive apt-get update -qq >/dev/null 2>&1 || true apt-get install -y -qq curl wget xserver-xorg-core xserver-xorg-video-dummy >/dev/null 2>&1 || true apt-get install -y -qq libva2 libvdpau1 >/dev/null 2>&1 || true elif command -v dnf >/dev/null 2>&1; then dnf install -y curl wget xorg-x11-server-Xorg xorg-x11-drv-dummy >/dev/null 2>&1 || true elif command -v pacman >/dev/null 2>&1; then pacman -Sy --noconfirm curl wget xorg-server xf86-video-dummy >/dev/null 2>&1 || true else log "WARNING: Unknown package manager. Trying to continue..." fi # --- 2. Detect display environment --- log "[2/6] Detecting display environment..." HAS_DISPLAY=false HAS_XORG=false if [ -n "${DISPLAY:-}" ] && xdpyinfo >/dev/null 2>&1; then HAS_DISPLAY=true log " Active display detected: $DISPLAY" fi if pgrep -x "Xorg" >/dev/null 2>&1 || pgrep -x "X" >/dev/null 2>&1; then HAS_XORG=true log " Xorg already running" fi # --- 3. Setup dummy driver if headless --- log "[3/6] Setting up dummy driver..." mkdir -p /etc/X11/xorg.conf.d/ # Remove conflicting configs rm -f /etc/X11/xorg.conf.d/20-intel-virtual.conf 2>/dev/null || true rm -f /etc/X11/xorg.conf.d/90-fallback.conf 2>/dev/null || true # Create dummy config (works for both host and VPS) cat > /etc/X11/xorg.conf.d/20-dummy-headless.conf <<'XORG' Section "Device" Identifier "DummyHeadless" Driver "dummy" VideoRam 256000 EndSection Section "Monitor" Identifier "DummyMonitor" HorizSync 28-80 VertRefresh 48-75 EndSection Section "Screen" Identifier "DummyScreen" Device "DummyHeadless" Monitor "DummyMonitor" DefaultDepth 24 SubSection "Display" Depth 24 Modes "1920x1080" "1280x720" EndSubSection EndSection XORG chmod 644 /etc/X11/xorg.conf.d/20-dummy-headless.conf # --- 4. Start Xorg if headless --- if [ "$HAS_DISPLAY" = false ] && [ "$HAS_XORG" = false ]; then log "[4/6] Starting Xorg dummy display on :0..." # Ensure no stale locks rm -f /tmp/.X11-unix/X0 /tmp/.X0-lock 2>/dev/null || true mkdir -p /tmp/.X11-unix chmod 1777 /tmp/.X11-unix # Start Xorg with dummy config if [ "$EUID" -eq 0 ]; then nohup Xorg :0 -config /etc/X11/xorg.conf.d/20-dummy-headless.conf -nolisten tcp >/tmp/xorg-dummy.log 2>&1 & else log " WARNING: Not root, trying xvfb-run fallback..." apt-get install -y -qq xvfb >/dev/null 2>&1 || true fi sleep 3 # Verify if [ -S /tmp/.X11-unix/X0 ]; then log " Xorg dummy display :0 created" else log " WARNING: Xorg socket not found, trying Xvfb..." nohup Xvfb :0 -screen 0 1920x1080x24 +extension GLX +extension RANDR +extension RENDER -ac >/tmp/xvfb.log 2>&1 & sleep 2 fi # Setup xauth for root if [ "$EUID" -eq 0 ]; then xauth -f /root/.Xauthority add :0 . $(mcookie) 2>/dev/null || true chmod 600 /root/.Xauthority 2>/dev/null || true fi else log "[4/6] Existing display detected, skipping Xorg startup" fi export DISPLAY=:0 export XAUTHORITY="${XAUTHORITY:-/root/.Xauthority}" # --- 5. Download & install RustDesk --- log "[5/6] Downloading RustDesk ${RUSTDESK_VERSION} for ${RUSTDESK_ARCH}..." if command -v curl >/dev/null 2>&1; then curl -fsSL -o "$TMP_DEB" "$RUSTDESK_URL" 2>&1 || true elif command -v wget >/dev/null 2>&1; then wget -q -O "$TMP_DEB" "$RUSTDESK_URL" 2>&1 || true fi if [ ! -f "$TMP_DEB" ] || [ ! -s "$TMP_DEB" ]; then log "ERROR: Failed to download RustDesk .deb" log "URL: $RUSTDESK_URL" log "Trying to install from repository..." apt-get install -y -qq rustdesk 2>/dev/null || true fi if [ -f "$TMP_DEB" ] && [ -s "$TMP_DEB" ]; then log " Installing from downloaded .deb..." dpkg -i "$TMP_DEB" >/dev/null 2>&1 || apt-get install -f -y -qq >/dev/null 2>&1 || true rm -f "$TMP_DEB" fi # Verify installation if [ ! -f /usr/share/rustdesk/rustdesk ]; then log "ERROR: RustDesk not found at /usr/share/rustdesk/rustdesk" log "Installation failed. Check /tmp/rdtop-install.log" exit 1 fi # --- 6. Start RustDesk & output credentials --- log "[6/6] Starting RustDesk server..." # Create config dir mkdir -p ~/.config/rustdesk # Write initial config with public rendezvous (for stable ID) cat > ~/.config/rustdesk/RustDesk2.toml <<'EOF' rendezvous_server = 'rs-ny.rustdesk.com:21116' nat_type = 1 serial = 0 unlock_pin = '' [options] local-ip-addr = 'auto' EOF chmod 600 ~/.config/rustdesk/RustDesk2.toml # Start server pkill -f "/usr/share/rustdesk/rustdesk" 2>/dev/null || true sleep 1 export DISPLAY=:0 export XAUTHORITY=/root/.Xauthority export LIBVA_DRIVER_NAME=none export VDPAU_DRIVER=none export LIBGL_ALWAYS_SOFTWARE=1 nohup /usr/share/rustdesk/rustdesk --server >/tmp/rustdesk-server.log 2>&1 & sleep 5 # Get credentials RUSTDESK_ID=$(/usr/share/rustdesk/rustdesk --get-id 2>/dev/null || echo "N/A") # Read or set password RUSTDESK_PASS="" if [ -f ~/.config/rustdesk/RustDesk.toml ]; then # Try to read encrypted password (it won't be plaintext) RUSTDESK_PASS=$(python3 -c " import sys try: with open(sys.argv[1]) as f: for line in f: if 'password' in line and '=' in line: parts = line.split('=') if len(parts) > 1: print(parts[1].strip().strip(\"'\")) break except: pass " ~/.config/rustdesk/RustDesk.toml 2>/dev/null || true) fi if [ -z "$RUSTDESK_PASS" ]; then RUSTDESK_PASS="<генерируется RustDesk — посмотрите в GUI>" fi # Summary echo "" echo "============================================" echo " RustDesk Ready!" echo "============================================" echo "" printf " %-12s %s\n" "ID:" "$RUSTDESK_ID" printf " %-12s %s\n" "Password:" "$RUSTDESK_PASS" printf " %-12s %s\n" "Display:" ":0 (1920x1080 dummy)" printf " %-12s %s\n" "Version:" "$RUSTDESK_VERSION" printf " %-12s %s\n" "Arch:" "$ARCH" echo "" echo " Connect: rustdesk $RUSTDESK_ID" echo " Logs: /tmp/rdtop-install.log" echo " RustDesk: /tmp/rustdesk-server.log" echo " Xorg: /tmp/xorg-dummy.log" echo "" echo "============================================" log "Installation complete. ID: $RUSTDESK_ID"