# NetDesk — your own self-hosted remote desktop

Website Version Platform E2E

**Website & live demo:** [netdesk.space](https://netdesk.space) · **Download:** [Windows agent](https://netdesk.space/download) · **Pricing:** [free to self-host](https://netdesk.space/pricing) A TeamViewer/RustDesk-style remote desktop system you fully own: a signaling/relay server for your VPS, a **Windows service** on your powerful PC (reachable at boot, at the logon screen, and across UAC prompts), and a **zero-install web viewer** (Chrome/Edge) you can use from any laptop or phone while traveling. ``` ┌──────────────────────────┐ WSS outbound only ┌──────────┐ WSS ┌──────────────┐ │ HOME PC (Windows service)│ ──────────────────► │ VPS │ ◄────── │ TRAVEL laptop│ │ broker (SYSTEM, boot) │ │ netdesk │ │ any browser │ │ └─ desktop agent │ ◄──── relayed ────► │ server │ │ (phone works)│ │ (console session) │ E2E-encrypted └──────────┘ └──────────────┘ └──────────────────────────┘ │ └──── optional direct mode: ws://home-ip:8901 (LAN / port-forward) ────┘ ``` ## Features **Access & unattended operation** - Boot-time Windows service (SYSTEM): no auto-logon needed, survives reboots - Reachable at the **Windows logon screen** — view and type credentials to log in - Input works across desktop switches (user desktop, logon screen, UAC prompts) via desktop-following injection - Auto-reconnect to server forever (works behind any NAT, no port forwarding) - Wake displays automatically when a viewer connects **Video / audio** - H.264 (x264 ultrafast/zerolatency), up to 1080p60 @ 20 Mbps, idle screens send nothing - Hardware decode in the browser (WebCodecs) + HTML5 canvas - Adaptive **Auto quality** mode (RTT/decoder-queue based preset stepping) - System audio (WASAPI loopback → Opus) — bundled in the packaged exe; `pip install PyAudioWPatch` for source runs **Full control** - Mouse (all buttons, wheel), keyboard via SendInput scancodes, keyboard-lock for Alt+Tab/Win/Ctrl+W in fullscreen - **Privacy mode** — turn the physical monitor off while you keep working - **Lock PC on disconnect** (per-viewer checkbox) - Process manager — list & kill remote processes - Remote power — lock, sign out, reboot, shut down, run command - Clipboard sync (two-way), chat **Files** - Browse/download/upload/rename/delete/mkdir, **folder upload** with drag & drop - Atomic uploads (.part → final), folder creation on demand **Security** - **End-to-end encryption** (default): ephemeral ECDH P-256 → AES-256-GCM per frame — the VPS cannot see your screen - Password never leaves the host un-hashed (PBKDF2 200k challenge/response, 0.4 s throttle per bad attempt) - Optional **TOTP 2FA** (`--set-totp auto` → authenticator code required at connect) - Optional server registration key so only your hosts can register; `/status` API behind a token - The service broker relays opaque bytes only — agents hold all keys **Accounts (RustDesk-style)** - Sign up / sign in **in the desktop app and on the website** — no email verification wall (the account works immediately; the email only confirms it) - **My computers**: every PC where you sign in with your account is listed on the website for one-click connect (online/offline/in-session status shown) - Server address is **pre-filled** (netdesk.space) and no registration key is needed by default; point the app at your own server anytime - Pre-configured builds: name the exe `NetDeskHost-host=your.server,key=SECRET.exe` and it auto-configures — hand it out with zero setup **Viewer niceties** - Address book (saved connections), remember-password, view-only mode - **Session recording** to .webm (one click) - **TCP tunneling** — reach any TCP service on the host (SSH, RDP, web UIs) through the server; portal-gated, with a panel in the viewer - **Installable app (PWA)** — install the viewer like a native app from Chrome/Edge/Safari on laptop or phone - **Host-side remote printing** — send a file to the host's printer from the file manager - Multi-monitor switching, quality presets, live stats (fps/RTT/bitrate/E2E badge) ## Quick start (try on one PC) ```bat cd path\to\netdesk scripts\run_local_demo.bat ``` First run prints and saves a 9-digit ID and a random password (`%APPDATA%\NetDesk\config.json`). Automated end-to-end test: `.venv\Scripts\python tools\smoke_test.py` (23 checks: auth, 2FA, E2E video, clipboard, processes, privacy, files, input, broker path…). ## Portable exe — a regular desktop app, no Python needed `portable\` (and `..\NetDesk-portable-win64.zip`) ships standalone Windows x64 binaries built with PyInstaller, **tested end-to-end** (full 20-check suite passes against the packaged exes): | File | Purpose | |---|---| | `NetDeskHost.exe` (54 MB, windowed) | the agent **desktop app** — double-click it: a control panel opens with live status, your ID, server settings, password/2FA management, start/stop, and one-click service install | | `NetDeskServer.exe` (14 MB, console) | server for a Windows VPS; serves the viewer **and the portal** | Double-clicking `NetDeskHost.exe` opens the control panel (config + logs are created next to the exe — the folder is fully portable). Advanced users can still drive everything from a terminal (`--server …`, `--install`, `--set-password`, `--set-totp auto`, `--uninstall`); the app itself is windowless, so CLI output goes to `host.log` next to the exe. `--install` sets up the same boot-time SYSTEM service with full logon-screen/UAC access. ## macOS (MacBook M4 / Apple Silicon and Intel) Mac binaries cannot be cross-compiled from Windows, so the repo builds them ON the Mac — native, one command: ```bash git scp the netdesk folder to the Mac, then: bash scripts/build_mac.sh # -> dist/NetDeskHost + dist/NetDeskServer (arm64) ``` - `NetDeskHost` on the Mac = control the Mac remotely (capture via mss, input via CoreGraphics CGEvent, clipboard via pbpaste/pbcopy, process manager, power via osascript). First run: grant **Screen Recording** and **Accessibility** permissions (System Settings → Privacy & Security); if Gatekeeper complains: `xattr -cr NetDeskHost`. - Autostart on login: `scripts/deploy/com.netdesk.host.plist` → copy to `~/Library/LaunchAgents/` (edit the path/server inside first), then `launchctl load ~/Library/LaunchAgents/com.netdesk.host.plist`. - `NetDeskServer` also builds on the Mac if you want a Mac VPS. - macOS audio capture needs a loopback device (e.g. BlackHole) — off by default. - Connecting TO a Mac or PC from the MacBook: just the browser — open the server URL in Chrome/Edge/Safari; nothing to install. ## Web management portal Start the server with `--portal-password "YourPortalPassword"` and open `https://your-server:8443/portal` — a TeamViewer-console-style dashboard: - **Computers list** — every host that ever registered, online/offline status, version, last-seen, and a **Connect** button that deep-links into the viewer (`/?id=` — ID prefilled, just type the host password) - **Live stats** — hosts online, sessions total, relayed traffic, uptime - **Activity feed** — host online/offline, connect attempts, accepted sessions, wrong-password/2FA failures (auth failures are visible server-side; passwords never are) - **Downloads** — anything you drop into the server's `files/` folder (e.g. `NetDeskHost.exe`) is offered to logged-in users, so your travel laptop can always grab the current agent from your own server Access control: single portal password (cookie session, HttpOnly, 7 days). The portal runs over the same TLS as everything else — keep TLS on for internet use. By design the portal **cannot** see or store host passwords (end-to-end encryption); connecting always needs the host's own password. ## Production setup ### 1. Server on your VPS (Debian/Ubuntu) ```bash cd netdesk/scripts/deploy && sudo bash deploy_vps.sh # installs systemd service, prints REG_KEY # add --portal-password "..." to the unit for the web portal at /portal sudo ufw allow 8443/tcp ``` TLS (recommended): Let's Encrypt via certbot, then add `--cert/--key` to the unit and restart. Quick alternative: `--gen-cert` (self-signed, accept browser warning once). ### 2. Host on your powerful PC (twice, then forget it) ```bat :: once, as your user: pick the password and server .venv\Scripts\python host\netdesk_host.py --set-password "YourStrongPassword" .venv\Scripts\python host\netdesk_host.py --server wss://desk.yourdomain.com:8443/ws --reg-key REG_KEY --listen 8901 :: once, as Administrator: install the boot-time service scripts\install_autostart.bat (runs: netdesk_host.py --install) ``` The installer copies credentials to `C:\ProgramData\NetDesk` and creates a SYSTEM scheduled task (ONSTART) running the **broker**. The broker spawns a **desktop agent** into your console session and re-spawns it on user switches. Optional: `--set-totp auto` for a 2FA secret (print → add to your authenticator). Optional: `pip install PyAudioWPatch` for remote sound. ### 3. Travel Open `https://desk.yourdomain.com:8443/` — enter ID (+ 2FA code if enabled) and password. Save it in the address book. Works on phones too. At the office logon screen after a reboot? Connect and type your Windows password — you're in. ## Security model TLS to the server + end-to-end AES-GCM media + PBKDF2 password proof + optional TOTP + registration key. Single session per host; second viewer gets "host busy". Everything is stateless on the VPS. ## Silent operation & what "undetected" means here Like RustDesk 1.2, NetDesk is invisible on the host while you work: - The engine is **headless** — no window, no tray icon, nothing pops up when a session starts. In service mode it runs as a hidden SYSTEM task from boot. - **Privacy mode** turns the physical monitor off while you keep working. Enable **"Blank the monitor while controlled"** in the app (or per-session via the viewer's privacy button) and the screen goes dark the moment a viewer connects; it comes back when the session ends. - Sessions inject input only; a person sitting at the PC would see the mouse move (true for RustDesk/TeamViewer too — blocking local input needs a driver). Be honest about the detection surface, because "undetected" does not mean "forensically invisible": the process shows in Task Manager, Windows sees the scheduled task, the host keeps logs (`host.log`), and the machine makes an outbound connection to your VPS. RustDesk has the same surfaces. That is the correct trade-off for administering **your own or explicitly authorized computers**; covertly controlling a machine you do not own or are not authorized to manage is illegal in most jurisdictions and this tool is not designed for it. ## Honest limitations - No UDP P2P hole-punching: browsers can't send raw UDP, so traffic relays through your VPS (~1 extra RTT; same as RustDesk when its punch fails). Direct mode (`--listen` + port-forward) bypasses the VPS on your LAN. - Remote printing is not implemented (needs a printer driver); use file transfer + local printing. - True privacy mode (fake desktop) needs a virtual display driver — NetDesk turns the physical monitor off instead. - Session-0 notes: input at the logon screen/UAC requires the service install (agent as SYSTEM). Ctrl+Alt+Del itself is never injectable without a driver. - No mobile native apps (the web viewer works in phone browsers). ## Files ``` netdesk/ ├── server/netdesk_server.py # signaling + relay + web host (stateless) ├── server/web/ # viewer UI ├── host/netdesk_host.py # broker + desktop agent + service installer ├── tools/smoke_test.py # 23-check end-to-end suite ├── scripts/ # local demo, service install, VPS deploy └── requirements.txt ``` ## Troubleshooting | Symptom | Fix | |---|---| | "host offline" | Broker not running: `schtasks /Run /TN NetDesk`, or start `--broker` manually; logs in the config folder's `host.log` | | "bad 2FA code" | Host clock drift — resync Windows time, or re-set `--set-totp` | | Black screen + "logon screen" banner | Nobody logged in — type credentials via keyboard, desktop switches automatically | | Input dead on UAC prompt | Only in simple (non-service) mode — install the service for SYSTEM desktop access | | Choppy | Auto quality preset, or direct mode on LAN | | E2E badge missing | Old browser — needs WebCodecs + WebCrypto (Chrome/Edge 102+) | ## Get the source code The full source is published on the project website (no GitHub account needed): ```bash # Clone directly from netdesk.space git clone https://netdesk.space/git/netdesk.git # …or download a snapshot # https://netdesk.space/source → .tar.gz / .zip ``` ## Repository layout ``` netdesk/ ├── server/ Python aiohttp signaling + relay + web client ├── host/ Python Windows host/agent + desktop GUI (pywebview) ├── native/ from-scratch native client (Rust core + Flutter UI) ├── docker/ Dockerfile + compose for the server ├── scripts/ tools/ helper + maintenance scripts └── requirements.txt Python deps for the server/host ``` ## License Source-available — free to self-host and modify for your own use. See `LICENSE`.